简体   繁体   English

onNewIntent 没有被调用

[英]onNewIntent is not called

I have very strange situation.我的情况很奇怪。
Having one app, I decided to create another one from the code of first one.有了一个应用程序,我决定从第一个应用程序的代码中创建另一个应用程序。
I copied.xml files, copied.java files so that everything is OK.我复制了.xml文件,复制了.java文件,这样一切正常。
But there's one HUGE problem: my onNewIntent(Intent intent) method is called in first project, but it's not called in the second project (the code is the same!)但是有一个巨大的问题:我的onNewIntent(Intent intent)方法在第一个项目中被调用,但在第二个项目中没有被调用(代码相同!)

Method, which could trigger then, but can't trigger now方法,当时可以触发,现在不能触发

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

Here's onNewIntent() method:这是 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);
    }   
}

I don't see "I WORKED" in my logs, unfortunately.不幸的是,我的日志中没有看到“我工作过”。
I've read lots of similar questions both on SO and over the Internet, tried setting Intent flags SINGLE_TOP, SINGLE_TASK and so on.我在 SO 和 Internet 上阅读了很多类似的问题,尝试设置 Intent 标志 SINGLE_TOP、SINGLE_TASK 等。

Here's the Android Manifest of WORKING project:这是工作项目的 Android 清单:

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

I'm quite desperate, why the similar code is not working anymore?我很绝望,为什么类似的代码不再工作了?

EDIT: I've tried everything: SINGLE_TOP, SINGLE_INSTANCE, SINGLE_TASK..编辑:我已经尝试了一切:SINGLE_TOP、SINGLE_INSTANCE、SINGLE_TASK..
but then I occasionally did this on another activity:但后来我偶尔会在另一项活动中这样做:

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

And it finally worked!它终于奏效了!
I don't know, whether it's a dirty workaround or a bug, if anyone can explain it, please, comment.我不知道这是一个肮脏的解决方法还是一个错误,如果有人可以解释它,请发表评论。

PREAMBLE:前言:

Allright, I'm a little late to this one, but as I stumbled over the same issue and no answer here or for any of the other four stackoverflow questions, I found for this issue, solved the problem for me, here's what I figured out.好吧,我对这个问题有点晚了,但是当我偶然发现同样的问题并且在这里或其他四个 stackoverflow 问题中的任何一个都没有答案时,我找到了这个问题,为我解决了这个问题,这就是我的想法出去。

ANSWER:回答:

There are several possible reasons, why onNewIntent isn't called and I'm gonna list them all - well all of which I know.有几个可能的原因,为什么没有调用 onNewIntent,我将列出所有这些 - 我知道所有这些。

  1. As mentioned in many answers before and in the doc for the onNewIntent function (link in Yaroslavs answer), you either need the android:launchMode="singleTop" manifest entry for the activity, where you want onNewIntent to be called, or the Intent used for starting the activity must have the flag FLAG_ACTIVITY_SINGLE_TOP .正如之前和 onNewIntent 函数的文档中提到的许多答案(Yaroslavs 答案中的链接),您需要android:launchMode="singleTop"活动清单条目,您希望在其中调用 onNewIntent,或者使用 Intent开始活动必须有标志FLAG_ACTIVITY_SINGLE_TOP You don't need both (it's a | aka. logical or not a & aka. logical and )!你不需要两者(它是| aka.logical or not a & aka.logical and )! onNewIntent should also be called for android:launchMode="singleTask" , but before you use that, you better check out the android:launchMode documentation, because it has much more consequences, than just one function call.也应该为android:launchMode="singleTask"调用android:launchMode="singleTask" ,但在使用之前,您最好查看 android:launchMode 文档,因为它具有更多的后果,而不仅仅是一个函数调用。
  2. In older versions of Android there was a bug , which basically prevented android:launchMode="singleTop" from working as specified and thus onNewIntent from being called.在旧版本的 Android 中有一个错误,它基本上阻止了android:launchMode="singleTop"按指定工作,因此无法调用 onNewIntent。 The bug was never officially solved, but I couldn't reproduce it in version 4.4.2 (Samsung S4 Mini).该错误从未正式解决,但我无法在版本 4.4.2(Samsung S4 Mini)中重现它。 So it seems to have been fixed at some point between 4.0.x and 4.4.2.所以它似乎已在 4.0.x 和 4.4.2 之间的某个时间点得到修复。
  3. Not every time the preconditions as mentioned before are fulfilled, onNewIntent will be called.并非每次满足前面提到的先决条件时,都会调用 onNewIntent。 As the documentation of the function states:正如该函数的文档所述:

    ...when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it. ...当活动在活动堆栈的顶部重新启动而不是启动活动的新实例时,将在现有实例上调用 onNewIntent() 并使用用于重新启动它的 Intent . "

    That means, if the activity is newly created, onNewIntent won't be called, no matter what launchMode or Intent flags you did set!这意味着,如果活动是新创建的,则不会调用 onNewIntent,无论您设置了什么 launchMode 或 Intent 标志!

    • To my understanding, either onCreate or onNewIntent is called, but never both.据我了解,onCreate 或 onNewIntent 都被调用,但永远不会同时调用。
    • So, if you wanna pass data to the activity through the Intent and it should always work (as in my case), no matter if the activity is relaunched or the activity is freshly created, you can do as described in this very useful blog post .因此,如果您想通过 Intent 将数据传递给 Activity 并且它应该始终有效(就像我的情况一样),无论是重新启动 Activity 还是新创建的 Activity,您都可以按照这篇非常有用的博客文章中的描述进行操作.
    • As a variation of the solution described in the above blog post, you could also take advantage of the fact, that no matter if onNewIntent or onCreate was called, onResume will always be called afterwards, and do something like this:作为上述博客文章中描述的解决方案的变体,您还可以利用这样一个事实,即无论是调用 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 }

      For this example getIntent will always get you the Intent you used for the startActivity call or the Notification, as the new Intent will also be set for the Activity, if the Activity is freshly created (and thus onCreate was called).对于此示例,getIntent 将始终为您提供用于 startActivity 调用或通知的 Intent,因为如果 Activity 是新创建的(因此调用了 onCreate),也将为该 Activity 设置新的 Intent。

POSTAMBLE:后文:

Sorry for the long post.抱歉,帖子太长了。 I hope you found something useful in it.我希望你能从中找到有用的东西。

The Activity you want to receive onNewIntent() in should have您想要接收 onNewIntent() 的 Activity 应该有

android:launchMode="singleTop"

Or add the flag tn intent或添加标志 tn 意图

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

As documented in onNewIntent(Intent)onNewIntent(Intent) 中所述

Here's one situation that might bite you, along with a bit more information: onNewIntent is called as expected with this code:以下是一种可能会让您onNewIntent的情况,以及更多信息:使用以下代码按预期调用onNewIntent

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

but not with this code但不是用这个代码

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

The reason for that is that, in the second code block, the new activity is added on top before calling finish for the current activity, so to get the second code block to work you must add the FLAG_ACTIVITY_CLEAR_TOP flag as suggested by some of the other answers, like this:这样做的原因是,在第二个代码块中,新活动在为当前活动调用完成之前添加到顶部,因此FLAG_ACTIVITY_CLEAR_TOP第二个代码块工作,您必须按照其他一些人的建议添加FLAG_ACTIVITY_CLEAR_TOP标志答案,像这样:

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

Note that finish is not called at all here, because it is called for you.请注意,这里根本没有调用finish ,因为它是为您调用的。 From the documentation for the FLAG_ACTIVITY_CLEAR_TOP flag :FLAG_ACTIVITY_CLEAR_TOP 标志文档中

If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.如果设置,并且正在启动的活动已经在当前任务中运行,那么不是启动该活动的新实例,而是将关闭它之上的所有其他活动,并且此 Intent 将被传递到(现在在顶部)旧活动作为新意图。

I was using onNewIntent for search implementation in Android.我在 Android 中使用onNewIntent进行搜索实现。 I came across the problem that onNewIntent wasn't being called when I used the Go button on the keyboard in the emulator.我遇到了在模拟器中使用键盘上的 Go 按钮时没有调用onNewIntent的问题。 I solved the issue by placing my code for handling the intent in the onCreate method also.我通过在onCreate方法中放置处理意图的代码解决了这个问题。 This needs to be done to make sure that the intent action is handled when a fresh instance of the activity is started.需要这样做以确保在启动活动的新实例时处理意图操作。

This posed a problem as onCreate is called whenever the activity is restored from a previous state too.这带来了一个问题,因为只要活动从先前的状态恢复,就会调用onCreate So, the intent handling method gets called even when an orientation change occurs.因此,即使发生方向更改,也会调用意图处理方法。

Solution : Use if (savedInstanceState==null) to determine if activity is being restored from a previous state, or is it a fresh search.解决方案:使用if (savedInstanceState==null)来确定活动是否正在从以前的状态恢复,或者是新搜索。

The best way to handle onNewIntent with singleTop is simply this:使用singleTop处理onNewIntent的最佳方法很简单:

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

Then do all of your logic on getIntent inside onResume .然后在onResume内的getIntent上执行所有逻辑。

for me I didn't add search action to the activity in the manifest:对我来说,我没有向清单中的活动添加搜索操作:

<activity android:name=".SearchResultsActivity" ... >
    ...
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    ...
</activity>

Check your steps here: https://developer.android.com/training/search/setup在此处检查您的步骤: https : //developer.android.com/training/search/setup

In my case, I just add launchMode="singleInstance" in the activity tag in the AndroidManifest file.在我的例子中,我只是在AndroidManifest文件的活动标签中添加launchMode="singleInstance"

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleInstance">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

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

Note: I was using kotlin.注意:我使用的是 kotlin。

To enter to the onNewIntent method, you need in your AndroidManifest.xml file, put after set you main activity a launch mode, in this launch mode you have to put singleInstance eg:要进入 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>

Now you will able to enter to you onNewIntent method.现在您将能够输入您的 onNewIntent 方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM