Не е показано правилно действие за намеренията на NFC

Имам работа с устройство, оборудвано с Android NFC, просто се опитвам да прочета етикет и да получа информацията от дейност. Маркерът е от типа MifareUltralight. Само като чета за този случай в документите за Android изглежда, че първо трябва да регистрирам намерението за стартиране на моята активност във файла на манифеста и по-късно ще мога да получа NFC намерението от него. Ето как изглежда моят манифестен файл:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mycompany.android">

    <uses-feature android:name="android.hardware.nfc" android:required="false" />
    <uses-permission android:name="android.permission.NFC" />

    <application
        android:allowBackup="true"
        android:label="Test">

        <activity
            android:name="com.mycompany.android.activities.NfcTestActivity"
            android:launchMode="singleTop"
            android:label="Test">
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="text/plain" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED"/>
            </intent-filter>
            <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

Зададох функцията nfc като незадължителна, защото не е от съществено значение за работата на приложението ми. Що се отнася до NFC техническите филтри, това е моят файл nfc_tech_filter.xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

Е, след като конфигурирах това, изглежда, че моят NfcTestActivity трябва да може да получава NFC намерения. Ето как го прилагам:

public class NfcTestActivity  extends Activity {

    final String TAG = NfcTestActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "IntentAction (onCreate): " + getIntent().getAction());
        NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
        NfcAdapter adapter = manager.getDefaultAdapter();
        if (adapter != null && adapter.isEnabled()) {
            Log.i(TAG, "NFC adapter is enabled");
        } else {
            Log.i(TAG, "NFC adapter is disabled");
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.i(TAG, "IntentAction (onNewIntent): " + getIntent().getAction());
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.i(TAG, "IntentAction (onResume): " + getIntent().getAction());
    }

}

Когато стартирам приложението, получавам следните регистрационни файлове:

05-28 10:41:52.044  31182-31182/com.mycompany.android I/NfcTestActivity? IntentAction (onCreate): android.intent.action.MAIN
05-28 10:41:52.054  31182-31182/com.mycompany.android I/NfcTestActivity? NFC adapter is enabled
05-28 10:41:52.054  31182-31182/com.mycompany.android I/NfcTestActivity? IntentAction (onResume): android.intent.action.MAIN

По-късно прочетох етикета си и се показва този журнал:

05-28 10:41:59.661  31182-31182/com.mycompany.android I/NfcTestActivity? IntentAction (onResume): android.intent.action.MAIN

Това означава, че методът Activity#onResume се извиква, когато етикетът се чете, както се казва в документацията, но това, което получавам тук, е android.intent.action.MAIN вместо NFC (ACTION_NDEF_DISCOVERED, ACTION_TECH_DISCOVERED или ACTION_TAG_DISCOVERED).

Освен това, като подсказка, когато премахна тази част от кода от моята декларация за активност, не се появява onResume регистрационен файл, когато прочета маркера:

<intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>

Така че изглежда, че действието TAG_DISCOVERED определено е стартирано по някакъв начин, не другите, но не мога да го хвана правилно от активността.

Някой знае ли за това?


person Xtreme Biker    schedule 28.05.2014    source източник


Отговори (2)


След известно обмисляне разбрах, че android.nfc.action.TAG_DISCOVERED по подразбиране вместо android.nfc.action.NDEF_DISCOVERED върши работата вместо мен:

 <intent-filter>
     <action android:name="android.nfc.action.TAG_DISCOVERED"/>
     <category android:name="android.intent.category.DEFAULT"/>
 </intent-filter>

Все още не знам защо трябва да използвам TAG_DISCOVERED, когато типът ми етикет се покрива от TECH_DISCOVERED, който е за предпочитане да използвам. Както и да е, това е кодът, който използвам, за да получа идентификатора на етикета по-късно:

@Override
public void onResume() {
    super.onResume();
    Log.d(TAG, "onResume: action-"+getIntent().getAction());
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {
        Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
        String tagId = bytesToHexString(tag.getId());
        Log.i(TAG, "NFC tag: " + tagId);
    }
}

Вижте също:

person Xtreme Biker    schedule 28.05.2014

Първо, вашият nfc_tech_filter.xml не е правилен. Филтърът

<tech-list>
    <tech>android.nfc.tech.IsoDep</tech>
    <tech>android.nfc.tech.NfcA</tech>
    <tech>android.nfc.tech.NfcB</tech>
    <tech>android.nfc.tech.NfcF</tech>
    <tech>android.nfc.tech.NfcV</tech>
    <tech>android.nfc.tech.Ndef</tech>
    <tech>android.nfc.tech.NdefFormatable</tech>
    <tech>android.nfc.tech.MifareClassic</tech>
    <tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>

означава, че искате да съвпаднете с етикет, който е IsoDep и NfcA и NfcB и NfcF и ... Въпреки това , технологиите за тагове NfcX се изключват взаимно (както и Ndef и NdefFormatable), така че филтърът няма да съответства на нито един етикет. Това, което всъщност бихте искали, е нещо подобно:

<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>

Което просто ще съответства на всяка технология на тагове. Или ако искате да съпоставите само MifareUltralight, можете просто да използвате:

<tech-list>
    <tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>

Използването на филтъра за намерения TAG_DISCOVERED обикновено не е добра идея. Той е предназначен само като резервен вариант и за обратна съвместимост с първия Android NFC API.

Когато искате да получавате NFC намерения, докато приложението ви е на преден план, обикновено е по-добре да се регистрирате за система за изпращане на преден план, вместо да разчитате на филтри за намерения в манифеста на приложението. Това ще гарантира, че вашата дейност получава събитията и че не се показва инструмент за избор на активност, дори ако друго приложение също има филтри за намерения за тези събития.

person Michael Roland    schedule 30.05.2014
comment
Много благодаря за отговора ;-) Той ми изясни концепцията за технологичното филтриране. Изглежда, че определено е ключът на проблема. - person Xtreme Biker; 30.05.2014