【问题标题】:Android NFC activity being relaunched even though its on the top of the stackAndroid NFC 活动正在重新启动,即使它位于堆栈的顶部
【发布时间】:2023-03-21 07:51:01
【问题描述】:

我猜你们中的大多数人在看到这个标题时都会脸色苍白,并且认为我们以前见过这个我同意,但我已经尝试了一切来解决这个问题,但它无法解决。就这样吧。

我的应用程序可以从主屏幕(图标)启动,一切正常,它会扫描 NFC 标签并将相关数据发送到服务器。 但是,我还想要从 NFC 标签启动应用程序,这没有问题。 然而!当应用程序通过 NFC 标签启动时,您然后移除手机并将其重新呈现给它应该的标签,然后读取标签并将数据发送到服务器。与通过图标启动应用程序的行为完全相同,但是这次当您扫描 NFC 标签时,会启动应用程序的 new 实例,最终将当前实例踢下堆栈,版本正忙于读取标签的实例,所以我得到了 ANR。

简而言之:
从主屏幕 -> 扫描标签 -> 应用启动。
然后你重新扫描标签->
应用程序的当前实例消失并被新实例替换。 我希望前一个实例保持原样并正常工作。

此时我的一些猜测是: - NFC 未正确注册到应用程序,因此操作系统执行默认行为。
- 通过 NFC 标签启动时存在未正确设置的标志,告诉操作系统无需重新启动活动。

代码如下:

<uses-permission android:name="android.permission.NFC"/>

<intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="http"android:host="@string/URL_for_intent_filtering" android:pathPrefix="/id/" />

//Procedure of NFC startup called from OnCreate
private void startNFC()
{
    mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if(! mNfcAdapter.isEnabled())//check the NFC is switched on
    {
        mMainActivityHandler.sendEmptyMessage(NFC_DISABLED);
    }

    //its ok to carry on and instantiate the NFC even though its not enabled.
    if(mNfcAdapter != null)
    {
        int requestID = (int) System.currentTimeMillis();
        mPendingIntent = PendingIntent.getActivity(this, requestID, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT);

        IntentFilter intentF = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        intentF.addDataScheme("http");

        intentfilter = new IntentFilter[] {intentF};



        if(DEBUG) Log.i("DEBUG","+++++++++++++++++++++++++++++++++++++++++++++++ NFC HAS BEEN STARTED");

    }else
    {
        //we have a problem with the NFC adapter probably because the device doesn't have one.
        if(DEBUG) Log.i("DEBUG","+++++++++++++++++++++++++++++++++++++++++++++++ NFC HAS FAILED");
        mMainActivityHandler.sendEmptyMessage(NFC_FAILED);
    }
}

@Override
protected void onPause()
{
    if(DEBUG) Log.i("MA","+++++++++++++++++++++++++++++++++++++++ ON PAUSE");
    try{
        mNfcAdapter.disableForegroundDispatch(this);
    }catch(Exception e)
    {

    }
    super.onPause();
}

//and here we should reinstate the NFC adapter
@Override
protected void onResume()
{
    if(DEBUG) Log.i("MA","+++++++++++++++++++++++++++++++++++++++ ON RESUME");

    //setupDataListener(true);
    setupServerComms(getApplicationContext());
    //mNfcAdapter.enableForegroundDispatch(this,mPendingIntent,intentfilter,null);
    mNfcAdapter.enableForegroundDispatch(this,mPendingIntent,null,null);
    super.onResume();
}

【问题讨论】:

  • 你解决过这个问题吗?我也有同样的问题。
  • @ProgrammerJames 你能解决这个问题吗?我现在也面临同样的情况。每次都会调用 onCreate()。
  • @Anil 是的,我做到了 - 我在意图中添加了一个标志 NewTask。我正在使用堆栈溢出应用程序,看不到如何链接到我的完整答案,但如果您点击我的名字并转到我提出的问题,那么您会看到我提出的问题和已回答的问题。

标签: android android-intent nfc flags android-pendingintent


【解决方案1】:

只需将您的AndroidManifest.xml 中的这一行添加到您的Activity 中,您可能就完成了。

        android:launchMode="singleTask"

【讨论】:

  • 我已经试过了,谢谢你的建议。我愿意尝试任何事情。
  • 我认为你应该重写 onNewIntent() 函数。您应该能够从那里的 NFC 标签获取新意图。当您启用 foregroundDispatch 时,不会触发新的 Intent,而是使用 NFC 标签中的数据创建的 Intent 通过 onNewIntent 回调传递给您的 Activity。
  • onNewIntent 在我的代码中被覆盖,然后我过滤掉 NDEF_discovered 等。当我单步执行代码时,最初会在看到标签时触发 onNewIntent,但是,当应用程序正在处理时,一个新实例应用程序的出现......它非常奇怪,就像应用程序表现完美但出于某种原因操作系统想要启动一个新实例。
  • 您可以尝试从您的活动中删除意图过滤器吗?
  • 您是否也可以尝试如下设置待处理意图: PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP), 0 );
【解决方案2】:

那么您想要应用程序捕捉意图,然后读取信息并正确处理它吗?好吧,您有一个用于执行此操作的未决意图,但您的设置似乎与我通常做的有点不同。这是我如何使用待处理意图来捕获标签数据的示例(从那里您可以做任何您想做的事情,例如将其发送到服务器):

Class example{

NfcAdapter adapter;
Tag motor;
String FileName;
PendingIntent detectTag;
IntentFilter NFC;
IntentFilter [] Catcher;
String [][] TechList;
TextView readToField;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_activity);

// Catch NFC detects
adapter = NfcAdapter.getDefaultAdapter(this);
detectTag = PendingIntent.getActivity(this,0,new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
NFC = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
Catcher = new IntentFilter[] {NFC,};
TechList = new String [][]{new String[]{android.nfc.tech.NfcV.class.getName()}};
}

public void onNewIntent(Intent intent)
{
    super.onNewIntent(intent);
    motor = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    Bridge bridge = (Bridge) getApplication();
    bridge.setCurrentTag(motor);
}

public void onPause()
{
    super.onPause();
    adapter.disableForegroundDispatch(this);
}

public void onResume()
{
    super.onResume();
    adapter.enableForegroundDispatch(this,detectTag ,Catcher , TechList);
}
}

Bridge 对象只是我用来保存标签信息的一个类,因此我可以将信息从其他(幕后)类发送到标签。

最后,我一直被告知,对于onResumeonPause,您应该先调用super.method

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2011-07-15
    相关资源
    最近更新 更多