tur*_*boy 6 android nfc android-intent
I have an ongoing problem where my app is delivering multiple intents to the recieving Activity after an NFC tag scan.
My App essentially scans an NFC tag which has some data on it and sends it to the server. In general it works fine. I understand that NFC works within a threshold of a few cms and perhaps my problem is user error, for example the user is waving the phone around the tag which could scan it twice within millisecs.
I have put a timer in the Application object. When the user scans a tag, i start the timer going and set a flag to false, this flag is checked within the Activity that handles the NFC intent and the the intent is dropped if the flag is false. This (should) stop multiple scans of a tag within 10 secs.
My app is used for HomeCare work, so a user will scan a tag in the clients house. When they scan the tag the first time it logs them in at that client with data and a time stamp. The second scan of the tag will log them out.
In general it works but sometimes a carer will log in and out at the first client, then at the second client or sometimes hours later, the carer will be logged back in at the previous client.
What i think is happening is the carer is mis-scanning the tag which is triggering the NFC adpter twice. The first intent is delivered straight away, then the second is delivered minutes/hours later.
How things flow. scan tag -> intent delivered to Activity -> start AppObj timer. write data to sqlite DB -> start an IntentService to send the transaction to server(cancelled after 10 seconds).
Can anyone see a problem i've missed that could account for why a duplicate Intent is delivered hours later?
Can anyone suggest a solution which would stop this happening?
Is there a problem whith how the intent is handled in the activity? eg the wrong code in the wrong Activity lifecycle method?
Is there a way to cancel/intercept the second intent from the second mis-scan?
Basically, what i want is that the nfcAdapter could be triggered 10 times in one second, but only the first scan is delivered to the activity. How can i achieve this?
i'll post some code.
[edit2]
Toast.makeText(this, "about to test flags", Toast.LENGTH_LONG).show();
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
Toast.makeText(this, "intent is from history", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "intent is not from history", Toast.LENGTH_LONG).show();
}
Run Code Online (Sandbox Code Playgroud)
.
[edit3]
<activity
android:name=".NfcscannerActivity"
android:screenOrientation="portrait"
>
<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="com.carefreegroup.rr3.QRCODE_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<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>
<activity
android:name=".EntryActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.carefreegroup.rr3.INVALID_CARER_TAG_SCANNED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)
. [edit4]
Tag tagTest = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef ndefTag = Ndef.get(tagTest);
try {
Log.e(TAG, "about to test io operations on Ndef Tag");
ndefTag.connect(); // this should already perform an IO operation and should therefore fail if there is no tag
NdefMessage ndefMsg = ndefTag.getNdefMessage(); // this reads the current NDEF message from the tag and consequently causes an IO operation
Log.e(TAG, "tested io operations on Ndef Tag, must be a real Tag!!!!!******!!!!!!");
} catch (Exception e) {
// there is no tag or communication with tag dropped
Log.e(TAG, "tested io operations on Ndef Tag, No Tag there, must be a re-delivery of the old Tag via an intent!!!!!******!!!!!!!!!!!!!!!!!!!!!!");
onResume();
} finally {
try {
ndefTag.close();
} catch (Exception e) {
}
}
Run Code Online (Sandbox Code Playgroud)
根据您的描述,我会假设受影响的用户通过按主页键"关闭"(实际隐藏)应用程序.之后他们从历史记录(长按主页键)打开应用程序(或者更确切地说是那个活动).
假设你处理NFC相关的意图只在onCreate(),你通常不会碰上你从历史开始你的活动时作为描述的问题onCreate()方法就不会被调用,如果你的活动在后台仍然存在.但是如果你的活动同时遭到破坏(例如app被手动杀死,app被系统杀死以释放资源等),从历史记录中重新启动应用程序将导致你的onCreate()方法再次运行.当Android重建活动堆栈并在从历史记录中打开应用程序时重新发送原始意图(即最初启动您的活动的意图)时,您的活动将收到它在最初启动时收到的NFC意图.
您可以通过检查您收到的意图是否具有该FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY设置来克服此问题.只有当您的活动是从历史记录开始时才会出现这种情况.
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) ||
NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
不解决您的初始问题,但作为最后的手段,请记住,在收到意图后,IO操作可以访问NFC标签.因此,为了检查您在intent中收到的标记是否实际存在,您可以执行此类IO操作.
例如,如果您的标记是NDEF标记:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef ndefTag = Ndef.get(tag);
try {
ndefTag.connect(); // this should already perform an IO operation and should therefore fail if there is no tag
NdefMessage ndefMsg = ndefTag.getNdefMessage(); // this reads the current NDEF message from the tag and consequently causes an IO operation
} catch (Exception e) {
// there is no tag or communication with tag dropped
} finally {
try {
ndefTag.close();
} catch (Exception e) {
}
}
Run Code Online (Sandbox Code Playgroud)
对于非NDEF标记,您需要知道如何使用低级命令访问标记.但至少连接测试适用于任何标签.
| 归档时间: |
|
| 查看次数: |
893 次 |
| 最近记录: |