onNewIntent未调用

问题描述 投票:25回答:6

我的情况很奇怪。有了一个应用程序,我决定从第一个应用程序的代码创建另一个应用程序。我复制了.xml文件,复制了.java文件,以便一切正常。但是有一个巨大的问题:我的onNewIntent(Intent intent)方法在第一个项目中被调用,但是在第二个项目中没有被调用(代码是相同的!)方法,该方法可能随后触发,但现在无法触发

public void onClick(View arg0) {
    Intent browserInt = new Intent (Intent.ACTION_VIEW, 
    Uri.parse("https://oauth.yandex.ru/authorize?response_type=token&client_id=zzzzz"));
    browserInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(browserInt);
}

这里是onNewIntent()方法:

@Override
protected void onNewIntent(Intent intent){
    System.out.println(" I WORKED!");
    Uri uri = intent.getData();
    if (uri!=null) {
        String m = uri.toString().split("#")[1];
        String[] args = m.split("&");
        String arg = args[0];
        String token = arg.split("=")[1];
        System.out.println(token);
    }   
}

很遗憾,我没有在日志中看到“我工作过”。我已经在SO和Internet上阅读了很多类似的问题,尝试设置Intent标志SINGLE_TOP,SINGLE_TASK等。

这是Android Manifest的WORKING项目:

<application 
    android:name="yyy"
    android:icon="@drawable/yaru_icon"
    android:allowBackup="false"
    android:label="xxx"
    android:theme="@style/LightTheme">

    <activity
        android:name=".Main"
        android:label="xxx"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>

我非常绝望,为什么类似的代码不再起作用?

EDIT:我已经尝试了所有方法:SINGLE_TOP,SINGLE_INSTANCE,SINGLE_TASK ..但是后来我偶尔在另一项活动中这样做:

Main m = new Main();
m.onNewIntent(this.getIntent());

终于成功了!我不知道这是一个肮脏的解决方法还是一个错误,如果有人可以解释,请发表评论。

android android-intent
6个回答
68
投票

PREAMBLE:

[好吧,我对这个问题有些迟了,但是当我偶然发现相同的问题,在这里或者其他四个stackoverflow问题中的任何一个都没有答案时,我发现了这个问题,为我解决了这个问题,这就是我想通了。

答案:

有几种可能的原因,为什么不调用onNewIntent,而我将列出所有这些原因-我都知道这些。

  1. 如onNewIntent函数的文档之前和文档中的许多答案所述(Yaroslavs答案中的链接),您要么需要活动的android:launchMode="singleTop"清单条目,要么要在其中调用onNewIntent的活动,或者需要将Intent用于启动活动必须具有标志FLAG_ACTIVITY_SINGLE_TOP。您不需要两者(这是|逻辑or而不是&逻辑and)!应该为android:launchMode="singleTask"调用onNewIntent,但是在使用它之前,最好查看android:launchMode文档,因为它带来的后果远不止一个函数调用。
  2. [在较旧的Android版本中,有一个bug,它基本上阻止了android:launchMode="singleTop"按照指定的方式工作,因此无法调用onNewIntent。该错误从未得到正式解决,但我无法在4.4.2版(三星S4 Mini)中进行复制。因此,它似乎已在4.0.x和4.4.2。之间的某个位置修复。
  3. 并非每次都满足上述前提条件时,都会调用onNewIntent。如功能文档所述:

  4. ...当在活动堆栈的顶部重新启动活动而不是启动活动的新实例时,将使用现有Intent在现有实例上调用onNewIntent()重新启动。

    这意味着,如果您是新创建的活动,则无论您设置了什么launchMode或Intent标志,都不会调用onNewIntent!

  • 据我了解,调用了onCreate或onNewIntent,但从未同时调用这两个。
  • 因此,如果您想通过Intent将数据传递给活动,并且该数据应始终有效(如我的情况),则无论是重新启动活动还是重新创建活动,都可以按照this very useful blog post中的说明进行操作。
  • 作为上述博客文章中描述的解决方案的一种变体,您还可以利用以下事实:无论调用了onNewIntent还是onCreate,onResume都将始终被调用,然后执行以下操作:] >

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        Intent intent = getIntent();
        // ... do what you wanna do with the intent
    }
    
  • 在此示例中,getIntent将始终为您提供用于startActivity调用或Notification的Intent,因为如果新创建了Activity(并因此调用了onCreate,则也会为Activity设置新的Intent。)>

    POSTAMBLE:

很抱歉,冗长的帖子。我希望您发现其中有用的东西。

您要在其中接收onNewIntent()的活动应具有

android:launchMode="singleTop"

或添加标志tn意图

browserInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                    Intent.FLAG_ACTIVITY_SINGLE_TOP);

onNewIntent(Intent)中所述

这里是一种可能会咬你的情况,还有更多信息:onNewIntent会通过此代码正常调用:

Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
finish();
startActivity(intent);

但没有此代码

Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();

原因是,在第二个代码块中,在对当前活动调用结束之前,将新活动添加到顶部,因此,要使第二个代码块正常工作,必须按照以下建议添加FLAG_ACTIVITY_CLEAR_TOP标志其他一些答案,例如:

Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

请注意,这里根本没有调用finish,因为它是为您调用的。从documentation for the FLAG_ACTIVITY_CLEAR_TOP flag

[如果已设置,并且正在启动的活动已在当前任务中运行,那么与其启动该活动的新实例,不如关闭该活动之上的所有其他活动,并将此Intent传递给(现在最重要)旧活动作为新的Intent。

我在Android上使用onNewIntent进行搜索。我遇到了一个问题,当我使用仿真器键盘上的“执行”按钮时,没有调用onNewIntent。我通过将用于处理意图的代码也放置在onCreate方法中解决了该问题。需要执行此操作以确保在启动活动的新实例时处理意图动作。

这也造成了问题,因为每当活动也从以前的状态恢复时,都会调用onCreate。因此,即使发生方向变化,也会调用意图处理方法。

解决方案:使用if (savedInstanceState==null)确定活动是从以前的状态恢复还是重新搜索。

onNewIntent处理singleTop的最佳方法就是这样:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}

然后在getIntent内的onResume上执行所有逻辑。

要进入onNewIntent方法,您需要在AndroidManifest.xml文件中,在将主活动设置为启动模式之后,在此启动模式下放置singleInstance例如:

<activity 
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleInstance"
        android:windowSoftInputMode="adjustPan" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>

现在您将可以在onNewIntent方法上向您输入。


20
投票

您要在其中接收onNewIntent()的活动应具有

android:launchMode="singleTop"

8
投票

这里是一种可能会咬你的情况,还有更多信息:onNewIntent会通过此代码正常调用:

Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
finish();
startActivity(intent);

3
投票

我在Android上使用onNewIntent进行搜索。我遇到了一个问题,当我使用仿真器键盘上的“执行”按钮时,没有调用onNewIntent。我通过将用于处理意图的代码也放置在onCreate方法中解决了该问题。需要执行此操作以确保在启动活动的新实例时处理意图动作。

这也造成了问题,因为每当活动也从以前的状态恢复时,都会调用onCreate。因此,即使发生方向变化,也会调用意图处理方法。


1
投票

onNewIntent处理singleTop的最佳方法就是这样:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
}

-2
投票

要进入onNewIntent方法,您需要在AndroidManifest.xml文件中,在将主活动设置为启动模式之后,在此启动模式下放置singleInstance例如:

<activity 
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleInstance"
        android:windowSoftInputMode="adjustPan" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>
© www.soinside.com 2019 - 2024. All rights reserved.