目录
1.申请权限
2.设置意图过滤器
3.判断NFC功能是否可用(NfcAdapter)
4.NFC感应(NfcAdapter)启用与禁用
5.NFC数据解码
6.案例代码一览
NFC的全称是“Near Field Communication”,意思是近场通信、与邻近的区域通信。该功能由NfcAdapter(NFC适配器)控制。
1.申请权限
2.设置意图过滤器
在清单文件(AndroidManifests)中为Activity设置意图过滤器(IntentFilter);在程序检测到NFC操作时将跳转至该界面。
本部分操作用于从外部直接打开指定Activity。
android.nfc.action.NDEF_DISCOVERED:指定了当应用程序收到包含NDEF(NFC Data Exchange Format)数据的NFC标签时应该触发的动作。NDEF是一种用于在NFC设备之间交换信息的标准格式。android.nfc.action.TAG_DISCOVERED:定义了当检测到NFC标签时应该触发的动作。这个动作用于处理未包含NDEF数据的NFC标签。android.nfc.action.TECH_DISCOVERED:指定了当检测到支持的NFC技术时应该触发的动作。这允许应用程序处理特定的NFC技术。其中具体的NFC技术由meta-data标签指定源文件。
android:name=".NFCActivity" android:exported="true" > android:resource="@xml/nfc_tech_filter"/>
3.判断NFC功能是否可用(NfcAdapter)
可使用NfcAdapter(NFC适配器)进行判断,未开启时跳转至NFC设置界面;NfcAdapter常用方法如下:
getDefaultAdapter(静态方法):获取NFC适配器对象;设备无NFC功能时返回null。isEnabled:判断NFC功能是否可用(即是否开启)。enableForegroundDispatch:用于启用NFC感应;第一个参数为上下文环境,第三参数为用于触发的待定意图,第三个参数为过滤器(会触发待定意图的NFC事件类型),第四个参数为指定NFC技术类型的二维数组。disableForegroundDispatch:用于禁用NFC感应。
//获取NFC适配器
NfcAdapter nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this);
//判断设备是否有NFC功能
if(nfcAdapter==null){
textView.setText("设备无NFC功能");
}
//判断设备是否开启NFC功能
else if (!nfcAdapter.isEnabled()) {
textView.setText("设备未开启NFC功能");
//跳转至设置NFC界面
Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS);
startActivity(intent);
}
else {
textView.setText("设备已开启NFC功能");
}
4.NFC感应(NfcAdapter)启用与禁用
建议在页面暂停时禁用NFC感应,在页面运行时启用NFC感应。
用于触发的待定意图(PendingIntent)为读取NFC信息通常为跳转至当前界面(即会触发onNewIntent方法);请注意需将Activity设置为仅有一个,可在清单文件将launchMode设置为singleTop,或为Intent使用.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)。
//准备NFC感应启动参数
//用于触发的待定意图
Intent intent=new Intent(MainActivity.this,MainActivity.class);
//intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);
//过滤器数组(会触发待定意图的NFC事件类型)
IntentFilter[] intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};
//指定NFC技术类型的二维数组
String[][] techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}};
protected void onResume() {
super.onResume();
if(nfcAdapter!=null&&nfcAdapter.isEnabled()){
//启用NFC感应
nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList);
}
}
protected void onPause() {
super.onPause();
if(nfcAdapter!=null&&nfcAdapter.isEnabled()){
//禁用NFC感应
nfcAdapter.disableForegroundDispatch(MainActivity.this);
}
}
5.NFC数据解码
用于触发的待定意图(PendingIntent)为读取NFC信息通常为跳转至当前界面(即会触发onNewIntent方法);请注意需将Activity设置为仅有一个。
可以通过重写onNewIntent方法,获取NFC数据并解码:
使用Intent获取action并判断是否为NFC操作触发;action返回结果可能为null;可无此步使用Intent获取其中包含的Tag型数据;可使用Tag数据获取卡序列号( getId()方法 );tag返回结果可能为null使用Tag数据获取MifareClassic对象MifareClassic对象连接到NFC卡根据MifareClassic对象获取卡中数据关闭MifareClassic与卡的连接,无论是否出现异常
MifareClassic类常用方法:
get(静态方法):从Tag对象中获取卡片对象的信息。connet:连接卡片数据。close:释放卡片数据。getType:获取卡片类型。TYPE_CLASSIC表示传统型,TYPE_PLUS表示加强型,TYPE_PRO表示专业型。getSectorCount:获取扇形区域。getBlockCount:获取分块个数。getSize:获取存储大小,单位字节。
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
//读取NFC信息
Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if(tag!=null){
//获取序列号
byte[] id_bytes=tag.getId();
String id="";
for(int i=0;i id=id+id_bytes[i]; } //创建MifareClassic对象 MifareClassic classic=MifareClassic.get(tag); try { //连接卡片 classic.connect(); //获取类型 int typeI=classic.getType(); String type=null; if(typeI==MifareClassic.TYPE_CLASSIC){ type="传统类型"; } else if(typeI==MifareClassic.TYPE_PLUS) { type="增强类型"; } else if (typeI==MifareClassic.TYPE_PRO) { type="专业类型"; } else { type="未知类型"; } //获取其他数据 int i1=classic.getSectorCount();//扇形区域 int i2=classic.getBlockCount();//分块个数 int i3=classic.getSize();//内存大小 } catch (IOException e) { throw new RuntimeException(e); }finally { try { //无论是否发生异常都要释放卡片数据(关闭连接) classic.close(); } catch (IOException e) { throw new RuntimeException(e); } } } } 6.案例代码一览 以下为MainActivity(界面只有一个TextView)的全部代码,请在清单文件声明(静态申请)NFC权限后使用。 public class MainActivity extends AppCompatActivity { private NfcAdapter nfcAdapter=null; private PendingIntent pendingIntent=null; private IntentFilter[] intentFilter=null; private String[][] techList=null; private TextView textView=null; @SuppressLint("MissingInflatedId") protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取控件 textView=findViewById(R.id.textView); //获取NFC适配器 nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this); //判断设备是否有NFC功能 if(nfcAdapter==null){ textView.setText("设备无NFC功能"); } //判断设备是否开启NFC功能 else if (!nfcAdapter.isEnabled()) { textView.setText("设备未开启NFC功能"); //跳转至NFC设置界面 Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS); startActivity(intent); } else { textView.setText("设备已开启NFC功能"); } //准备NFC感应启动参数 //用于触发的待定意图 Intent intent=new Intent(MainActivity.this,MainActivity.class); //intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE); //过滤器(会触发待定意图的NFC事件类型) intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)}; //指定NFC技术类型 techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}}; } protected void onResume() { super.onResume(); if(nfcAdapter!=null&&nfcAdapter.isEnabled()){ //启用NFC感应 nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList); } } protected void onPause() { super.onPause(); if(nfcAdapter!=null&&nfcAdapter.isEnabled()){ //禁用NFC感应 nfcAdapter.disableForegroundDispatch(MainActivity.this); } } //该界面触发NFC自动调用该方法 protected void onNewIntent(Intent intent) { super.onNewIntent(intent); String outString="NFC卡无数据"; //读取NFC信息 Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if(tag!=null){ //获取序列号 byte[] id_bytes=tag.getId(); String id=""; for(int i=0;i id=id+id_bytes[i]; } outString="序列号为:"+id+"\n"; //创建MifareClassic对象 MifareClassic classic=MifareClassic.get(tag); try { //连接卡片 classic.connect(); //获取类型 int typeI=classic.getType(); String type=null; if(typeI==MifareClassic.TYPE_CLASSIC){ type="传统类型"; } else if(typeI==MifareClassic.TYPE_PLUS) { type="增强类型"; } else if (typeI==MifareClassic.TYPE_PRO) { type="专业类型"; } else { type="未知类型"; } //获取其他数据 int i1=classic.getSectorCount();//扇形区域 int i2=classic.getBlockCount();//分块个数 int i3=classic.getSize();//内存大小 outString=outString+type+"\n"+"扇形区域:"+i1+"\n分块个数:"+i2+"\n内存大小:"+i3; } catch (IOException e) { throw new RuntimeException(e); }finally { try { //无论是否发生异常都要关闭连接 classic.close(); } catch (IOException e) { throw new RuntimeException(e); } } } textView.setText(outString); if(outString.equals("NFC卡无数据")){ Handler handler=new Handler(new Handler.Callback() { public boolean handleMessage(@NonNull Message message) { textView.setText("设备已开启NFC功能"); return true; } }); new Thread(new Runnable() { public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { throw new RuntimeException(e); } handler.sendEmptyMessage(123); } }).start(); } } } tag:NFC,nfc,芯片,磁卡,近距通信