Как я могу получить события для всех типов NFC?
В настоящее время у меня есть приложение, в котором пользователь должен войти в систему, чтобы использовать его. В ближайшем будущем мы могли бы поддерживать NFC-чип для входа в систему без ввода имени пользователя и пароля. Я абсолютно не представляю, как работает сканирование чипа NFC, поэтому я посмотрел некоторые учебники и нашел Этот.
Я скопировал код из учебника и думаю, что понимаю, как он работает. Проблема в том, что он не работает для карты, которую я должен проверить (метод onNewIntent не вызывается, в отличие от то, что говорит мне учебник). Карта работает (другие приложения берут ее просто отлично), поэтому я думаю, что проблема в том, что это другой тип, чем тот, который используется в учебнике. Поэтому я изменил xml, упомянутый в учебнике, на следующий:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
</tech-list>
<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.Ndef</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NdefFormatable</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.MifareClassic</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
Это мой файл манифеста:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="nl.boomerweb.nfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="nl.boomerweb.nfc.MainActivity"
android:label="@string/app_name" >
<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.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<meta-data
android:name="android.nfc.action.NDEF_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
</activity>
</application>
</manifest>
Я предполагал, что это будет сканировать не только тип чипа Ndef, но и все остальные. Но мое приложение по-прежнему не отвечает, Когда я подношу карту к телефону.
Это карта подробности, полученные с помощью приложения NFC scanner:
Технология RF:
Тип А (ISO/IEC 14443 TYPE A)
Тип Тега:
Mifare Classic 1K
ATQA:
0004
Сак:
08
Целевые классы технологий (Android):
android.nfc.tech.MifareClassic,
android.nfc.tech.NfcA,
android.nfc.tech.NdefFormatable
Я тестирую на Samsung Galaxy SIII, с android 4.1.2. Я включил nfc и sBeam на устройстве и другое приложение, которое сканирует чипы nfc, работает отлично, так что проблема, должно быть, в моем коде. Я создал отдельный проект для тестирования этого, который содержит только код, как показано в заключительной части учебника, упомянутого выше (так что только MainActivity, манифест и nfc_tech_filter.XML).
Лучшим было бы решение, которое может читать все карты, но сейчас что-то, что может читать эту карту, было бы прекрасно. Я также был бы признателен, если бы кто-нибудь объяснил, как работает добавление нового типа чипа nfc. Мы, вероятно, будем поддерживать более одного типа после этот работает.
1 ответ:
Я нашел решение, которое работает на меня. На самом деле было две проблемы с учебником, одна из которых заключалась в том, что мое приложение вообще не реагировало на карту, другая возникла после того, как я решил первую, и это было то, что приложение было повторно открыто, когда оно уже работало. Вот весь код, который я использовал для решения обеих задач:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.nfc" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.nfc.MainActivity" android:label="@string/app_name" > <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.NDEF_DISCOVERED" /> <action android:name="android.nfc.action.TAG_DISCOVERED" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> <meta-data android:name="android.nfc.action.NDEF_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> <meta-data android:name="android.nfc.action.TAG_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> </activity> </application> </manifest>
Nfc_tech_filter.xml
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.IsoDep</tech> </tech-list> <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.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareClassic</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
Основная активность.java
package com.example.nfc; import android.nfc.NfcAdapter; import android.os.Bundle; import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.widget.Toast; public class MainActivity extends Activity { public static final String MIME_TEXT_PLAIN = "text/plain"; public static final String TAG = "NfcDemo"; private NfcAdapter mNfcAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mNfcAdapter = NfcAdapter.getDefaultAdapter(this); if (mNfcAdapter == null) { // Stop here, we definitely need NFC Toast.makeText(this, "Dit apparaat ondersteund geen NFC.", Toast.LENGTH_LONG).show(); finish(); return; } if (!mNfcAdapter.isEnabled()) { Toast.makeText(this, "NFC staat niet aan", Toast.LENGTH_SHORT).show(); } handleIntent(getIntent()); } @Override protected void onResume() { super.onResume(); setupForegroundDispatch(this, mNfcAdapter); } @Override protected void onPause() { stopForegroundDispatch(this, mNfcAdapter); super.onPause(); } @Override protected void onNewIntent(Intent intent) { handleIntent(intent); } private void handleIntent(Intent intent) { if (intent != null && intent.getAction().contains("android.nfc")) { //if we are here, we captured an nfc event } } public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) { final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass()); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0); String[][] techList = new String[][]{}; adapter.enableForegroundDispatch(activity, pendingIntent, null, techList); } public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) { adapter.disableForegroundDispatch(activity); } }
Как вы можете видеть, я добавили в манифест все возможные действия. Чтобы убедиться, что диспетчер переднего плана работает, я удалил фильтры из учебника. Это, конечно, создаст проблемы, когда будут запущены другие события, но я решил, что всегда смогу отфильтровать их позже. Не самое элегантное решение,но оно делает свою работу.