近场通信(Near Field Communication,NFC)是一种短距离高频的无线电技术,在13.56MHz频率运行与20厘米距离内 。其运行速度有106Kbit/秒、212Kbit/秒或者424Kbit/秒三种。目前近场通信已成为ISO/IEC IS 18092国际标准、ECMA-340标准与ETSI TS 190标准。
NFCl蓝牙红外网络类型点对点单点对多点点对点使用距离<=0.1m<=10m<=1m速度106、212、424、868、721、115kbps2.1Mbps-1.0Mbps建立时间<0.1s6s0.5s安全性具备,硬件实现具备,软件实现不具备,使用IRFM时除外通行模式主动-主动/被动主动-主动主动-主动成本低中注意:使用NFC需要有一部有NFC功能的手机和NFC标签(需在某宝上购买。。。)
添加权限
<uses-permission android:name="android.permission.NFC"/> <uses-feature android:name="android.hardware.nfc" android:required="true"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>添加过滤器
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity> //检查设备是否支持NFC功能 nfcAdapter=NfcAdapter.getDefaultAdapter(this); if (nfcAdapter==null){ Toast.makeText(this, "设备不支持NFC功能", Toast.LENGTH_SHORT).show(); finish(); } //判断设备是否打开NFC功能 if (!nfcAdapter.isEnabled()){ Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS); startActivity(intent); }获取系统应用列表
package com.example.nfc; import android.graphics.drawable.Drawable; public class AppInfo { int versionCode=0; //名称 String appname=""; //包 String packagename=""; String versionName=""; //图标 Drawable appicon=null; } package com.example.nfc; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class PackageListActivity extends Activity implements AdapterView.OnItemClickListener { private ListView packageList; private List<AppInfo> list = new ArrayList<>(); private MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_package_list); packageList = findViewById(R.id.listView); packageList.setOnItemClickListener(this); PackageManager pm = getPackageManager(); List<PackageInfo> packageInfos = pm.getInstalledPackages(PackageManager.GET_ACTIVITIES); for (PackageInfo p : packageInfos) { AppInfo appInfo = new AppInfo(); appInfo.appname = p.applicationInfo.loadLabel(pm).toString(); appInfo.packagename = p.packageName; appInfo.versionName = p.versionName; appInfo.versionCode = p.versionCode; appInfo.appicon = p.applicationInfo.loadIcon(getPackageManager()); list.add(appInfo); } myAdapter = new MyAdapter(); packageList.setAdapter(myAdapter); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { AppInfo appInfo = list.get(position); Intent data = new Intent(); data.putExtra("packageName", appInfo.packagename); setResult(RESULT_OK, data); finish(); } private class MyAdapter extends BaseAdapter { @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder vh = null; if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.list_item_layout, null); vh = new ViewHolder(); vh.imageView_logo = convertView.findViewById(R.id.imageView2_logo); vh.textView_name = convertView.findViewById(R.id.textView_name); convertView.setTag(vh); } else { vh = (ViewHolder) convertView.getTag(); AppInfo info = list.get(position); vh.imageView_logo.setImageDrawable(info.appicon); vh.textView_name.setText(info.appname); } return convertView; } class ViewHolder { ImageView imageView_logo; TextView textView_name; } } }布局文件
activity_package_list.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/listView" android:layout_centerHorizontal="true" android:layout_centerVertical="true"/> </RelativeLayout> list_item_layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView2_logo" android:src="@mipmap/ic_launcher"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView_name" android:text="new text"/> </LinearLayout> </LinearLayout>activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="选择要启动的程序" android:onClick="selectStartAppClick" android:id="@+id/button"/> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/button" android:scaleType="center" android:src="@mipmap/ic_launcher"/> <Button android:id="@+id/button_write" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/button" android:text="写入标签" android:onClick="writeClick"/> </RelativeLayout> package com.example.nfc; import android.app.PendingIntent; import android.content.Intent; import android.nfc.FormatException; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.Ndef; import android.nfc.tech.NdefFormatable; import android.provider.Settings; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Toast; import java.io.IOException; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE=0x1; private NfcAdapter nfcAdapter; private String packageName; private PendingIntent pi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //检查设备是否支持NFC功能 nfcAdapter=NfcAdapter.getDefaultAdapter(this); if (nfcAdapter==null){ Toast.makeText(this, "设备不支持NFC功能", Toast.LENGTH_SHORT).show(); finish(); } //判断设备是否打开NFC功能 if (!nfcAdapter.isEnabled()){ Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS); startActivity(intent); } pi=PendingIntent.getActivity(this,0,new Intent(this,getClass()),0); } public void selectStartAppClick(View view){ Intent intent=new Intent(this,PackageListActivity.class); startActivityForResult(intent,REQUEST_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode==REQUEST_CODE&&requestCode==RESULT_OK){ packageName=data.getStringExtra("packageName"); Log.i("tag",packageName); } } @Override protected void onResume() { super.onResume(); if (nfcAdapter!=null){ //设置当前程序为优先处理NFC的程序 nfcAdapter.enableForegroundDispatch(this,pi,null,null); } } @Override protected void onPause() { super.onPause(); if (nfcAdapter!=null){ //取消当前程序为优先处理NFC的程序 nfcAdapter.disableForegroundDispatch(this); } } }写入数据
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); write(intent); } private void write(Intent intent){ Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if (tag==null){ return; } //写入数据 // NdefRecord[] records=new NdefRecord[]{NdefRecord.createApplicationRecord(packageName)};//打开指定应用程序 // NdefRecord[] records=new NdefRecord[]{NdefRecord.createUri("http://www.baidu.com")};//打开uri NdefRecord[] records=new NdefRecord[2];//打开uri records[0]=new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,new byte[]{0},packageName.getBytes(Charset.forName("gb2312"))); records[1]=new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,new byte[]{1},"1".getBytes(Charset.forName("gb2312"))); NdefMessage ndefMessage=new NdefMessage(records); Ndef ndef=Ndef.get(tag); if (ndef!=null){ try { ndef.connect(); if (ndef.isWritable()){ int size=ndefMessage.toByteArray().length; if (ndef.getMaxSize()>size){ ndef.writeNdefMessage(ndefMessage); } } } catch (IOException e) { e.printStackTrace(); } catch (FormatException e) { e.printStackTrace(); } }else { try { NdefFormatable ndefFormatable=NdefFormatable.get(tag); if (ndefFormatable!=null){ ndefFormatable.connect(); ndefFormatable.format(ndefMessage);//格式化并写入 } } catch (IOException e) { e.printStackTrace(); } catch (FormatException e) { e.printStackTrace(); } } Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); } private boolean isRead=true;//true读取,false写入 //写入状态 public void writeClick(View view){ isRead=false; Toast.makeText(this, "当前为写入状态", Toast.LENGTH_SHORT).show(); }解析数据
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (isRead){ read(intent); }else { write(intent); } } //读取NFC标签数据并解析 private void read(Intent intent){ Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if (tag==null){ return; } if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())){ Parcelable[] data=intent.getParcelableExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (data!=null){ NdefMessage[] ndefMessages=new NdefMessage[data.length]; for (int i = 0; i < ndefMessages.length ; i++) { ndefMessages[i]= (NdefMessage) data[i]; NdefRecord[] records=ndefMessages[i].getRecords(); String package_name=new String(records[0].getPayload()); String flag=new String(records[1].getPayload()); //开启蓝牙 if ("1".equals(flag)){ BluetoothAdapter bluetoothAdapter=BluetoothAdapter.getDefaultAdapter(); bluetoothAdapter.enable(); } //根据包名运行程序 Intent startApp=this.getPackageManager().getLaunchIntentForPackage(package_name); startActivity(startApp); } } } } //读取状态 public void readClick(View view){ isRead=true; Toast.makeText(this, "当前为读取状态", Toast.LENGTH_SHORT).show(); }