我一直在尝试创建一个可以读取两种不同类型NFC标签的应用。一个应该是HCE-IsoDep,在Nexus 5上模拟,一个是Ndef-tag。然而,我遇到了一个小问题:
我设法读取两种类型的标签,但不是我想要的方式。 Ndef标签完全没问题。当我尝试阅读我遇到问题的HCE标签时。我只能在手机打开时读取标签,我模拟标签打开(屏幕打开,但锁定打开)。每当我解锁屏幕时,它就不会再进行交互了,据我所知,它会尝试射击。
如果我在没有onNewIntent
的情况下尝试这样做而只是直接转到onTagDiscovered
,那么当HCE设备被锁定和解锁时它既可以工作,但是我无法读取Ndef -标签。
在logcat中,当我在解锁时读取HCE标记时,我收到消息:NfcService LLCP Activation Message
。
锁定后,我会收到以下消息:NativeNfcTag Connect to a tag with a different handle
(之前我得到:audio_hw_primary select_devices: out_snd_device(2: speaker) in_snd_device(0: )
)
我的代码如下所示:
public class NfcReader extends Activity implements OnMessageReceived {
private static String TAG = NfcReader.class.getSimpleName();
private Button sendButton;
private ProgressBar callProgress;
private NfcAdapter nfcAdapter;
private PendingIntent pIntent;
private IntentFilter[] writeTagFilters;
private String[][] mTechLists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView dateView = (TextView) findViewById(R.id.dateTextView);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
pIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
writeTagFilters = new IntentFilter[] { tagDetected };
mTechLists = new String[][] {new String[] {
Ndef.class.getName(),
IsoDep.class.getName()
}};
}
@Override
protected void onPause() {
super.onPause();
disableForegroundMode();
}
@Override
protected void onResume() {
super.onResume();
enableForegroundMode();
}
public void enableForegroundMode() {
Log.d(TAG, "onResume");
nfcAdapter.enableForegroundDispatch(this, pIntent, writeTagFilters, mTechLists);
}
public void disableForegroundMode() {
Log.d(TAG, "onPause");
nfcAdapter.disableForegroundDispatch(this);
}
@Override
public void onNewIntent(Intent intent) {
Log.d(TAG, "onNewIntent");
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef nDef = Ndef.get(tag);
if (nDef != null) {
onNdefDiscovered(tag);
}
else {
onTagDiscovered(tag);
}
}
}
public void onNdefDiscovered(Tag tag) {
Log.d(TAG, "Ndef found");
new ReadTag().execute(tag);
}
public void onTagDiscovered(Tag tag) {
Log.d(TAG, "HCEfound");
IsoDep isoDep = IsoDep.get(tag);
IsoDepTransceiver transceiver = new IsoDepTransceiver(isoDep, this);
transceiver.run();
}
@Override
public void onMessage(final byte[] message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
String readFromHce = new String(message);
TextView result = (TextView) findViewById(R.id.refTextView);
result.setText(readFromHce);
}
});
}
@Override
public void onError(Exception exception) {
onMessage(exception.getMessage().getBytes());
}
}
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="19" />
<uses-permission
android:name="android.permission.INTERNET" />
<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" >
<activity
android:name=".HceReader"
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"/>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc"/>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
有人知道我做错了什么吗?我在没有找到解决方案的情况下搜索了很多。 再说一遍。我可以毫无问题地阅读Ndef标签。当HCE设备上的屏幕被锁定时,我只能读取已经用过的IsoDep标签。
感谢任何帮助 此致
public class NfcReader extends Activity implements OnMessageReceived, ReaderCallback {
private static String TAG = NfcReader.class.getSimpleName();
private NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView result = (TextView) findViewById(R.id.refTextView);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
}
@Override
protected void onPause() {
super.onPause();
nfcAdapter.disableReaderMode(this);
}
@Override
protected void onResume() {
super.onResume();
nfcAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A, null);
}
public void onTagDiscovered(Tag tag) {
Log.d(TAG, "Tag Found");
Ndef nDef = Ndef.get(tag);
IsoDep isoDep = IsoDep.get(tag);
if (nDef != null) {
new ReadTag().execute(tag);
}
else if (isoDep != null){
IsoDepTransceiver transceiver = new IsoDepTransceiver(isoDep, this);
transceiver.run();
}
}
@Override
public void onMessage(final byte[] message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
String readFromHce = new String(message);
TextView result = (TextView) findViewById(R.id.refTextView);
result.setText(readFromHce);
}
});
}
@Override
public void onError(Exception exception) {
onMessage(exception.getMessage().getBytes());
}
}
非常感谢NFC小伙伴提示。
答案 0 :(得分:8)
在Android 4.4及更高版本上,您应该使用enableReaderMode()。
在此模式下,NFC控制器仅充当NFC标签读取器/写入器,从而禁用此设备上NFC适配器的任何对等(Android Beam)和卡仿真模式。
为了与使用Android基于主机的卡片仿真在其他Android设备上模拟的标签进行交互,建议的标志为FLAG_READER_NFC_A和FLAG_READER_SKIP_NDEF_CHECK。
答案 1 :(得分:1)
你没有做错任何事。不幸的是,你试图做的事情是行不通的。
如果您的手机同时运行卡片仿真和点对点(安卓光束),并且阅读器(您的另一部手机)也支持点对点,那么点对点技术将会优先考虑卡模拟。
如果您考虑一下,这是完全合理的:如果您将支持NFC的SIM卡插入手机,您将会运行一些基于SIM的脱离主机卡模拟。如果点对点不会优先于卡片仿真,那么android梁会停止工作,你会看到与IsoDep标签的连接。
如果您的电话被锁定,将禁用点对点并且卡仿真优先。因此,您可以在此状态下访问卡仿真。
如果您想要在屏幕解锁状态下访问卡模拟,您唯一的选择是使用不激活点对点协议的读卡器设备(例如独立支付终端)。 / p>
在Android上,没有办法禁用点对点。在设置中禁用Android Beam也无济于事,因为只会禁用高级Beam协议。点对点协议仍将运行以主动阻止您查看其他人卡模拟。出现这种行为是因为出于安全原因,Google不希望人们意外访问支付卡模拟。