Android NFC连接后是否需延迟?多检测问题求助
NFC Type A卡Android应用问题排查
我开发了一款通过APDU连接NFC Type A卡的Android应用,调试模式下添加断点时能成功连接卡片并发送Select指令,但真机安装运行时应用崩溃。在连接标签后、选择小程序前加入Thread.sleep(2000)延迟(1500ms仍崩溃)后问题解决,想了解该延迟是否必要及原因;此外每次触碰NFC卡时,Android会多次发出检测提示音,求解决办法。
MainActivity.java
package nfcapp; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.NfcA; import android.os.Bundle; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import com.google.common.primitives.Bytes; import java.io.IOException; import java.lang.reflect.Array; public class MainActivity extends AppCompatActivity { byte[] resp; private NfcAdapter nfcAdapter; static final byte[] APPLET_AID = {(byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06}; static final byte[] APPLET_PIN = {(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04}; static final byte[] APDU_SELECT = {(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x00}; TextView tv_status; @SuppressLint("MissingInflatedId") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_status = findViewById(R.id.tv_status); nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter == null) { Toast.makeText(this, "NFC is not supported", Toast.LENGTH_LONG).show(); finish(); } else if (!nfcAdapter.isEnabled()) { Toast.makeText(this, "Turn on device NFC", Toast.LENGTH_LONG).show(); } } @Override protected void onResume() { super.onResume(); Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE); nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null); } @Override protected void onPause() { super.onPause(); nfcAdapter.disableForegroundDispatch(this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if ( NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()) ) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if (NfcA.get(tag) != null) { NfcA nfcaTag = NfcA.get(tag); try { nfcaTag = SCConnect(nfcaTag); if (nfcaTag == null) { finish(); } tv_status.append("Connected To NFC Card Successfully!\n"); Thread.sleep(2000); resp = SCSelectApplet(nfcaTag, APPLET_AID); tv_status.append("SCSelectApplet: " + byteArrayToHexString(resp) + "\n"); } catch (IOException e) { tv_status.append("IOException : "+ e.getMessage().toString() + "\n"); } catch (InterruptedException e) { throw new RuntimeException(e); } } else { Toast.makeText(this, "Unsupported tag technology", Toast.LENGTH_LONG).show(); } intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); } } private NfcA SCConnect(NfcA nfcA) throws IOException { nfcA.connect(); if (!nfcA.isConnected()) { return null; } return nfcA; } private static byte[] SCSelectApplet(NfcA nfcA, byte[] AID) throws IOException { if(!nfcA.isConnected()) { return null; } byte[] APDU = new byte[13]; System.arraycopy(APDU_SELECT,0,APDU,0,5); if (AID.length != 0) { Array.setByte(APDU,4,(byte)AID.length); System.arraycopy(AID,0,APDU,5,AID.length); } byte[] resp = nfcA.transceive(APDU); return resp; } private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); public static String byteArrayToHexString(byte[] bytes) { if (bytes == null) return null; char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = HEX_ARRAY[v >>> 4]; hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; } return new String(hexChars); } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <uses-permission android:name="android.permission.NFC" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:roundIcon="@mipmap/ic_launcher_round" android:theme="@style/Theme.NFCApp" tools:targetApi="31"> <activity android:name=".MainActivity" android:launchMode="singleTask" android:exported="true"> <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" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_status" android:layout_width="400dp" android:layout_height="400dp" android:layout_marginTop="100dp" android:layout_marginStart="5dp" android:textSize="18dp" android:justificationMode="inter_word" android:hint="Status" /> </LinearLayout>
内容的提问来源于stack exchange,提问作者MJay
相关产品推荐
相关产品推荐

