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);
    }