android - 多个扫描/Intent 传递给接收 Activity

标签 android android-intent nfc

我有一个持续存在的问题,我的应用程序在 NFC 标签扫描后向接收 Activity 传送多个 Intent 。

我的应用程序本质上是扫描一个 NFC 标签,上面有一些数据并将其发送到服务器。 一般来说它工作正常。我知道 NFC 在几厘米的阈值内工作,也许我的问题是用户错误,例如用户在标签周围挥动手机,标签可以在几毫秒内扫描两次。

我在 Application 对象中放置了一个计时器。当用户扫描标签时,我启动计时器并将标志设置为 false,在处理 NFC Intent 的 Activity 中检查此标志,如果标志为 false,则丢弃 Intent 。这(应该)在 10 秒内停止对标签的多次扫描。

我的应用用于家庭护理工作,因此用户将在客户家中扫描标签。当他们第一次扫描标签时,它会使用数据和时间戳将他们登录到该客户端。标签的第二次扫描会将它们注销。

一般来说它是有效的,但有时护理人员会在第一个客户处登录和注销,然后在第二个客户处或有时几小时后,护理人员会在前一个客户处重新登录。

我认为正在发生的事情是护理人员误扫描了触发 NFC 适配器两次的标签。第一个 Intent 立即交付,然后第二个 Intent 在几分钟/几小时后交付。

事情是如何流动的。 扫描标签 -> Intent 传递给 Activity -> 启动 AppObj 计时器。 将数据写入 sqlite DB -> 启动 IntentService 将事务发送到服务器(10 秒后取消)。

谁能看到一个我遗漏的问题,它可以解释为什么在几个小时后交付了一个重复的 Intent?

谁能提出阻止这种情况发生的解决方案?

在 Activity 中处理 Intent 的方式是否存在问题?例如错误的 Activity 生命周期方法中的错误代码?

有没有办法取消/拦截第二次误扫描的第二个 Intent ?

基本上,我想要的是 nfcAdapter 可以在一秒钟内被触发 10 次,但只有第一次扫描被传送到 Activity 。我怎样才能做到这一点?

我会发布一些代码。

[编辑2]

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();

        }

.

[编辑3]

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

. [编辑4]

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) {
                }
            }

最佳答案

根据您的描述,我假设受影响的用户通过按主页键“关闭”(实际上是隐藏)应用程序。稍后他们会从历史记录(长按主页键)中打开应用程序(或者更确切地说是那个 Activity )。

假设您在 onCreate() 中处理与 NFC 相关的 Intent ,您通常不会遇到您在从历史记录开始 Activity 时描述的问题如果您的 Activity 仍然存在于后台,则不会调用 onCreate() 方法。 但是 如果您的 Activity 同时被销毁(例如,应用程序被手动杀死,应用程序被系统杀死以释放资源等),从历史记录中重新启动应用程序将导致您的 onCreate() 方法再次运行。当 Android 重建 Activity 堆栈并重新发送原始 Intent (即最初启动您的 Activity 的 Intent )时,从历史记录中打开应用程序时,您的 Activity 将收到它收到的 NFC Intent 它最初是开始的。

您可以通过检查您收到的 Intent 是否设置了 FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY 来解决这个问题。如果您的 Activity 是从历史开始的,那么只有是这种情况。

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())) {
        ...
    }
}

不是解决您最初的问题,而是作为最后的手段,请记住,在收到 Intent 后,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) {
    }
}

对于非 NDEF 标签,您需要知道如何使用低级命令访问标签。但至少连接测试适用于任何标签。

关于android - 多个扫描/Intent 传递给接收 Activity ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23362675/

相关文章:

java - 尽快在 Gradle 中测试子模块(无需配置其余项目)

java - 等待更新程序单例

android - 通过 Android 应用程序使 MIFARE Classic 1K 只读

android - 任务 :app:testDebugUnitTest in Android studio 执行失败

java - Android 中的 Firebase 加入数据

android - 通过 android intents 传递 Hashmap

java - 在 JAVA ANDROID SDK 中动态创建按钮和文本

android - 如何接收 android.nfc.action.TAG_LOST Intent 来检测标签移除?

安卓 NFC : Intercept all Tags

android - 在保持 ADB Activity 的同时断开 Android 模拟器中的网络