OnNewIntent не вызывается

У меня очень странная ситуация.
Имея одно приложение, я решил создать еще один из кода первого.
Я скопировал файлы .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, так и через Интернет, попробовал установить флаги Intent SINGLE_TOP, SINGLE_TASK и т.д.

Здесь проект Android Manifest of 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());

И это наконец сработало!
Я не знаю, будет ли это грязным обходным путем или ошибкой, если кто-нибудь может это объяснить, пожалуйста, комментируйте.

Ответ 1

Преамбула:

Хорошо, я немного опоздал к этому, но поскольку я наткнулся на ту же проблему и не нашел ответа здесь или на любой из других четырех вопросов stackoverflow, я нашел для этой проблемы, решил проблему для меня, вот что я понял вне.

ОТВЕТ:

Есть несколько возможных причин, по которым onNewIntent не вызывается, и я собираюсь перечислить их все - ну, все из которых я знаю.

  1. Как упоминалось во многих ответах до и в документе для функции onNewIntent (ссылка в ответе Ярослава), вам либо нужна запись манифеста android:launchMode="singleTop" для действия, для которой вы хотите вызвать onNewIntent, либо Intent, используемый для запуска действия должен иметь флаг FLAG_ACTIVITY_SINGLE_TOP. Вам не нужны оба (это | aka. Логический or, а не & aka. Логический and)! onNewIntent также следует вызывать для android:launchMode="singleTask", но перед тем, как его использовать, лучше ознакомьтесь с документацией по android: launchMode, поскольку она имеет гораздо больше последствий, чем просто один вызов функции.
  2. В более старых версиях Android существовала ошибка, которая в основном не позволяла android:launchMode="singleTop" работать так, как указано, и, следовательно, вызывать onNewIntent. Ошибка никогда не была официально решена, но я не мог воспроизвести ее в версии 4.4.2 (Samsung S4 Mini). Похоже, что это было исправлено в какой-то момент между 4.0.x и 4.4.2.
  3. Не каждый раз, когда упомянутые выше предварительные условия выполняются, вызывается onNewIntent. Как указано в документации по функции:

    ... когда действие перезапускается в верхней части стека действий вместо нового экземпляра запускаемого действия, onNewIntent() вызывается для существующего экземпляра с Intent, который использовался для его повторного запуска. "

    Это означает, что если действие создается заново, onNewIntent не будет вызываться, независимо от того, какие флаги launchMode или Intent вы установили!

    • Насколько я понимаю, вызывается либо onCreate, либо onNewIntent, но не оба одновременно.
    • Итак, если вы хотите передать данные в действие через Intent, и оно всегда должно работать (как в моем случае), независимо от того, возобновлено ли действие или вновь создано действие, вы можете сделать это, как описано в полезное сообщение в блоге.
    • В качестве варианта решения, описанного в приведенном выше сообщении в блоге, вы также можете воспользоваться тем фактом, что независимо от того, были ли вызваны 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 всегда получит вам Intent, который вы использовали для вызова startActivity или Notification, так как новый Intent также будет установлен для Activity, если Activity была создана недавно (и, следовательно, вызывался onCreate).

Постамбула:

Извините, за длинную статью. Я надеюсь, что вы нашли что-то полезное в этом.

Ответ 2

Активность, которую вы хотите получить onNewIntent(), должна иметь

android:launchMode="singleTop"

Или добавьте флаг tn намерение

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

Как описано в onNewIntent (Intent)

Ответ 3

Вот одна ситуация, которая может вас укусить, а также немного больше информации: 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 здесь вообще не вызывается, потому что он вызывается для вас. Из документа для флага FLAG_ACTIVITY_CLEAR_TOP:

Если установлено, и запущенная деятельность уже запущена в текущей задаче, вместо того, чтобы запускать новый экземпляр этого действия, все остальные действия поверх него будут закрыты, и это намерение будет доставлено в (сейчас сверху) старой деятельности как нового намерения.

Ответ 4

Я использовал onNewIntent для поиска в Android. Я столкнулся с проблемой, что onNewIntent не вызывался, когда я использовал кнопку Go на клавиатуре в эмуляторе. Я решил проблему, поставив свой код для обработки намерения в методе onCreate. Это необходимо сделать, чтобы убедиться, что действие намерения выполняется, когда запущен новый экземпляр активности.

Это создает проблему, поскольку onCreate вызывается всякий раз, когда активность восстанавливается из предыдущего состояния. Таким образом, метод обработки намерений вызывается даже при изменении ориентации.

Решение. Используйте if (savedInstanceState==null), чтобы определить, восстанавливается ли активность из предыдущего состояния, или это новый поиск.

Ответ 5

Лучший способ справиться с onNewIntent с помощью singleTop - это просто:

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

Затем выполните всю свою логику на getIntent внутри onResume.

Ответ 6

Чтобы войти в метод 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>

Теперь вы сможете ввести для вас методNewIntent.