Tag发布系统
描述
当android设备扫描到一个NFC tag,通用的行为是自动找最合适的Activity会处理这个tag Intent而不需要用户来选择哪个Activity来处理。因为设备扫描NFC tags是在很短的范围和时间,如果让用户选择的话,那就有可能需要移动设备,这样将会打断这个扫描过程。你应该开发你只处理需要处理的tags的Activity,以防止让用户选择使用哪个Activity来处理的情况。Android提供两个系统来帮助你正确的识别一个NFC tag是否是你的Activity想要处理的:Intent发布系统和前台Activity发布系统。
Intent发布系统检查所有Activities的intent filters,找出那些定义了可以处理此tag的Activity,如果有多个Activity都配置了处理同一个tag Intent,那么将使用Activity选择器来让用户选择使用哪个Activity。用户选择之后,将使用选择的Activity来处理此Intent.
前台发布系统允许一个Activity覆盖掉Intent发布系统而首先处理此tag Intent,这要求你将要处理Tag Intent的Activity运行在前台,这样当一个NFC tag被扫描到,系统先检测前台的Activity是否支持处理此Intent,如果支持,即将此Intent传给此Activity,如果不支持,则转到Intent发布系统。
使用前台发布系统
前台发布系统允许一个Activity 拦截一个tag Intent 获得最高优先级的处理,这种方式很容易使用和实现:
1.在OnCreate()方法中创建一个 PendingIntent对象, 这样Android系统就能在一个tag被检测到时定位到这个对象
PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0); or PendingIntent mpendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0)
launchMode设为singleTop,这样无论NFC标签靠近手机多少次,保障只有一个Activity实例。(除一次靠近调用OnCreate()方法外,标签每一次靠近都会调用OnNewIntent()方法。)
2. 在主线程里调用enableForegroundDispatch(Activity, PendingIntent, IntentFilter[], String[][])而且Activity在前台(可以在onResume()里调用来保证这点)。
@Override//页面获取到焦点 public void onResume() { super.onResume(); resumeNfc(); } private void resumeNfc() { if (mNfcAdapter != null && mNfcAdapter.isEnabled()) { //打开前台发布系统,使页面优于其它nfc处理 mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null); } } //页面失去焦点 @Override public void onPause() { if (mNfcAdapter != null) { stopNFC_Listener(); } } private void stopNFC_Listener() { //关闭前台发布系统 mNfcAdapter.disableForegroundDispatch(this); }
3.在OnNewIntent中获取Tag对象
@Override public void onNewIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { processIntent(intent); } } or @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); mTag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String[] techList=mTag.getTechList(); System.out.println("标签支持的tachnology类型:"); for (String tech:techList){ System.out.println(tech); } }
参考博客:
https://blog.csdn.net/zhangbijun1230/article/details/82586436
下面是整体代码
// IC Card private NfcAdapter mNfcAdapter; PendingIntent mPendingIntent=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NfcManager mNfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE); mNfcAdapter = mNfcManager.getDefaultAdapter(); mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0); init_NFC(); } /** * 通过NFC读取IC卡号 */ private void init_NFC() { IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED); tagDetected.addCategory(Intent.CATEGORY_DEFAULT); } @Override public void onNewIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { processIntent(intent); } } public void processIntent(Intent intent) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if (tag == null) return; String[] techList = tag.getTechList(); byte[] ID = new byte[20]; ID = tag.getId(); //code here } @Override public void onResume() { super.onResume(); resumeNfc(); } private void resumeNfc() { if (mNfcAdapter != null && mNfcAdapter.isEnabled()) { mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null); } } private void stopNFC_Listener() { mNfcAdapter.disableForegroundDispatch(this); }