NFC broadcastreceiver problem

2019-03-22 03:54发布

I want my app to listen to nfc tags only when is activated. For this I tried to register an nfc listener as following, without any success.

IntentFilter filter = new IntentFilter("android.nfc.action.TECH_DISCOVERED"); 
registerReceiver(nfcTagListener, filter); 

BroadcastReceiver nfcTagListener = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) { 
            String action = intent.getAction(); 

            if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { 
                Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
                Log.d("nfc", "" + tag.getId());     
            }
        }
    };

I tried as well to declare the intent in my manifest following the apidemos and works perfectly, it launches my activity and gets the nfc tag id. But this is not what I want, I want to detect the tag id only when I am inside that activity. I am thinking it might be related to the following line included in the api demos. But I dont know how to do that programatically

      <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
            android:resource="@xml/filter_nfc"> 

Any hint?

Thanks!

2条回答
兄弟一词,经得起流年.
2楼-- · 2019-03-22 04:03

Try to use Foreground Dispatch System.

To enable it, on the activity's onCreate method, you should prepare some stuffs:

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

after that, create the IntentFilters (in my example, all actions are handled using Intent Filters):

    IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
    try {
        ndef.addDataType("*/*");
    } catch (MalformedMimeTypeException e) {
        throw new RuntimeException("fail", e);
    }

    IntentFilter tech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
    try {
        tech.addDataType("*/*");
    } catch (MalformedMimeTypeException e) {
        throw new RuntimeException("fail", e);
    }

    IntentFilter[] intentFiltersArray = new IntentFilter[] { tag, ndef, tech };

after that, you'll need a String array to contain supported technologies:

    String[][] techList = new String[][] { new String[] { NfcA.class.getName(),
            NfcB.class.getName(), NfcF.class.getName(),
            NfcV.class.getName(), IsoDep.class.getName(),
            MifareClassic.class.getName(),
            MifareUltralight.class.getName(), Ndef.class.getName() } };

in the onResume method, you should enable the foreground dispatch method:

NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techList);

and disable in onPause:

@Override
protected void onPause() {
    super.onPause();
    nfcAdapter.disableForegroundDispatch(this);
}

By this way, you have successfully initialized the needed mechanism. To handle a received Intent you should override the onNewIntent(Intent intent) method.

@Override
public void onNewIntent(Intent intent) {
    String action = intent.getAction();

    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
        // reag TagTechnology object...
    } else if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
        // read NDEF message...
    } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {

    }
}

Note: if you want to handle the intents by only foreground dispatching, do not enable Intent Dispatch System in your manifest file, just give the right permissions to your application there.

I hope that helps.

查看更多
仙女界的扛把子
3楼-- · 2019-03-22 04:15

If you do not want to use foreground mode, your can always programmatically enable or disable intent filters.

The NDEF Tools for Android project has working sample using foreground mode, also detects

  1. NFC device support
  2. NFC enabled / disabled on activity launch, or later changed
  3. NFC push enabled / disabled on activity launch, or later changed
查看更多
登录 后发表回答