Как использовать действия NFC

Я пытаюсь зарегистрировать приемник программно, чтобы получить уведомление после обнаружения тега NFC. Как показано в моем коде, я зарегистрировался для желаемого действия и создал широковещательный приемник программно. Я также добавил требуемое разрешение в файл манифеста, но проблема в том, что onReceiveникогда не вызывается.

Пожалуйста, дайте мне знать, что я делаю неправильно и как это исправить.

IntentFilter intentFilter1 = new IntentFilter();
intentFilter1.addAction("android.nfc.action.TAG_DISCOVERED");
registerReceiver(mBCR_TAG_DISCOVERED, intentFilter1);

private BroadcastReceiver mBCR_TAG_DISCOVERED = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        mTv.setText("mBCR_TAG_DISCOVERED");
    }
};

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest 
package="example.com.myapplication">

<uses-permission android_name="android.permission.NFC" />

<uses-feature
    android_name="android.hardware.nfc"
    android_required="true" />

<application
    android_allowBackup="true"
    android_icon="@mipmap/ic_launcher"
    android_label="@string/app_name"
    android_supportsRtl="true"
    android_theme="@style/AppTheme">
    <activity android_name=".MainActivity">
        <intent-filter>
            <action android_name="android.intent.action.MAIN" />

            <category android_name="android.intent.category.LAUNCHER" />
        </intent-filter>

    </activity>
</application>

</manifest>

5 ответов

  1. В методе onCreate можно зарегистрировать приемник следующим образом:

     private BroadcastReceiver receiver;
    
    @Override
    public void onCreate(Bundle savedInstanceState){
    
     // your oncreate code should be
    
     IntentFilter filter = new IntentFilter();
     filter.addAction("SOME_ACTION");
    filter.addAction("SOME_OTHER_ACTION");
    
     receiver = new BroadcastReceiver() {
     @Override
      public void onReceive(Context context, Intent intent) {
       //do something based on the intent's action
     }
     };
      registerReceiver(receiver, filter);
      }
    

    Не забудьте выполнить это в методе onDestroy:

     @Override
    protected void onDestroy() {
    if (receiver != null) {
     unregisterReceiver(receiver);
     receiver = null;
    }
    super.onDestroy();
    }
    
  2. УСОВЕРШЕНСТВОВАННЫЙ

    Добавить в манифест:

    <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.TECH_DISCOVERED" />
            <action android_name="android.nfc.action.TAG_DISCOVERED" />
            <category android_name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    
  3. Я думаю, у вас есть ошибка :
    вы используете intentFilter1 без действия, так как действие добавляется в intentFilter0 , попробуйте добавить действие в intentFilter1 и запустите его.

  4. Намерениеandroid.nfc.action.TAG_DISCOVERED, как и все намерения NFC, является намерением действия, а не широковещательным намерением. Просто невозможно зарегистрировать радиоприемник для него. Вместо этого можно зарегистрировать действие для получения намерений NFC. Это может быть сделано либо через манифест, через систему диспетчеризации NFC переднего плана, или на Android 4.4+ через API режима чтения NFC.

    1. Декларация

    В зависимости от того, какие данные находятся на вашем теге, вы бы хотели зарегистрироваться для ndef_discovered intent (если есть структурированные данные NDEF на теге) или для TECH_DISCOVERED intent (если вы просто хотите слушать определенные технологии тегов независимо от данных на тегах). Как правило, вы не хотите регистрироваться для фильтра tag_discovered intent, так как это только подразумевается в качестве резервного механизма (чтобы поймать события, не обрабатываемые любым другим приложением) при использовании через AndroidManifest.XML.

    Например. если тег содержит URL-адрес http://www.example.com/, можно использовать следующий фильтр намерений:

    <activity android_name=".MainActivity">
        ...
        <intent-filter>
            <action android_name="android.nfc.action.NDEF_DISCOVERED" />
            <category android_name="android.intent.category.DEFAULT" />
            <data android_scheme="http" android_host="www.example.com" />
        </intent-filter>
    </activity>
    

    Если ваш тег не содержит каких-либо конкретных данных и может относиться к какой-либо технологии тегов, можно использовать следующий фильтр намерений:

    <activity android_name=".MainActivity">
        ...
        <intent-filter>
            <action android_name="android.nfc.action.TECH_DISCOVERED" />
            <category android_name="android.intent.category.DEFAULT" />
        </intent-filter>
        <meta-data android_name="android.nfc.action.TECH_DISCOVERED"
                   android_resource="@xml/nfc_tech_filter" />
    </activity>
    

    Для работы этого фильтра intent также потребуется XML-ресурс xml/nfc_tech_filter.xmlв res/каталоге приложения. Если технический фильтр должен соответствовать только любому тегу, этот файл будет содержать это:

    <resources >
        <tech-list>
            <tech>android.nfc.tech.NfcA</tech>
        </tech-list>
        <tech-list>
            <tech>android.nfc.tech.NfcB</tech>
        </tech-list>
        <tech-list>
            <tech>android.nfc.tech.NfcF</tech>
        </tech-list>
        <tech-list>
            <tech>android.nfc.tech.NfcV</tech>
        </tech-list>
        <tech-list>
            <tech>android.nfc.tech.NfcBarcode</tech>
        </tech-list>
    </resources>
    

    Как только ваша активность зарегистрирована для получения этих событий, вы можете получить эти намерения в вашей деятельности либо через onCreate()(Если ваша активность запускается событием NFC), либо через onNewIntent()(Если ваша активность получает последующее намерение NFC во время открытия):

    @Override
    public void onCreate(Bundle savedInstanceState) {
    
        [...]
    
        Intent startIntent = getIntent();
        if ((startIntent != null) &&
            (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(startIntent.getAction()) ||
            NfcAdapter.ACTION_TECH_DISCOVERED.equals(startIntent.getAction()))) {
            // TODO: process intent
        }
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) ||
            NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
            // TODO: process intent
        }
    }
    

    2. Система Диспетчеризации Переднего Плана

    Если вы заинтересованы только в получении намерений обнаружения NFC, пока ваша деятельность видна на переднем плане, вам лучше использовать систему диспетчеризации NFC переднего плана вместо регистрации для получения событий NFC через манифест. Вы делаете это, регистрируя свои действия во время onResume():

    @Override
    public void onResume() {
        super.onResume();
    
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
    }
    

    Вы также должны убедиться, чтобы отменить регистрацию во время onPause():

    @Override
    public void onPause() {
        super.onPause();
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.disableForegroundDispatch(this);
    }
    

    Затем вы получите события NFC как tag_discovered intents через onNewIntent():

    @Override
    public void onNewIntent(Intent intent) {
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
            // TODO: process intent
        }
    }
    

    3. API режима чтения

    Если вы заинтересованы только в обнаружении тегов NFC и только в то время как ваша деятельность видна на переднем плане, и вам нужно только нацелить Android 4.4+, лучший метод, вероятно, использовать NFC reader mode API. Вы делаете это, регистрируя свои действия во время onStart():

    @Override
    public void onStart() {
        super.onStart();
    
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.enableReaderMode(this, new NfcAdapter.ReaderCallback() {
            @Override
            public void onTagDiscovered(Tag tag) {
                // TODO: use NFC tag
            }
        }, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_NFC_F | NfcAdapter.FLAG_READER_NFC_V | NfcAdapter.FLAG_READER_NFC_BARCODE, null);
    }
    

    Вы также должны убедиться, чтобы отменить регистрацию во время onStop():

    @Override
    public void onStop() {
        super.onStop();
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.disableReaderMode(this);
    }
    

    Обнаруженные дескрипторы тегов можно получить с помощью onTagDiscovered(Tag tag)метода обратного вызова.