Как вывести действие на передний план (или создать, если оно не существует)?

Я перехватываю смс-сообщения с некоторой информацией в них. Затем в моем SmsListener я создаю уведомление для отображения в строке состояния. Затем, когда пользователь нажимает на уведомление, я хочу

  1. Выведите MainActivity на передний план (если такой активности еще нет, ее следует создать)
  2. Передать на него данные из смс
  3. Выполните некоторые изменения пользовательского интерфейса на основе этих данных в этом MainActivity.

Моя деятельность определяется как

    <activity
        android:name=".MainActivity"
        android:screenOrientation="sensor"
        android:label="@string/app_name"
        android:launchMode="singleTask"/>

Активность запускается как

 Intent i = new Intent();
 i.setClass(context, MainActivity.class);
 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 context.startActivity(i);

Также в моей деятельности я переопределил метод onNewActivity

 @Override
 public void onNewIntent(Intent intent){
    super.onNewIntent(intent);

    // I have data from broadcast in intent variable passed to this activity
    processDataFromBroadcast(intent);
}

Он отлично работает, если MainActivity уже существует, но если MainActivity не существует, он запускается, однако onNewIntent не вызывался

Затем я попытался вызвать processDataFromBroadcast из onCreate: processDataFromBroadcast(getIntent()). Данные в первый раз правильно передаются из моей трансляции в активность. Однако, если MainActivity отправляется в фоновый режим, а затем снова выводится на передний план, вызывается onCreate или onNewIntent, а processDataFromBroadcast снова выполняется с намерением, отправленным широковещательной передачей, и, таким образом, моя MainActivity обновляется данными из широковещательной передачи каждый раз, когда приложение выводится на передний план - последнее нежелательно, как я могу заставить свою деятельность забыть об этом намерении после первой обработки. Вот пример приложения.


person Solvek    schedule 05.02.2011    source источник


Ответы (3)


Чтобы действие запускало только один экземпляр самого себя, взгляните на элемент манифеста <activity> и, в частности, android:launchMode. Вы хотите настроить его с помощью singleTask или singleInstance.

Чтобы передать данные в свою активность, вы добавляете данные в Intent, который используете для ее открытия. Чтобы передать данные с намерением, используйте putExtra() методы намерения перед его отправкой и getExtra() методы для их извлечения в процессе получения.

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

person rogerkk    schedule 05.02.2011
comment
Спасибо за ответ. Однако, пожалуйста, смотрите мои обновления к вопросу. - person Solvek; 05.02.2011
comment
У Activity есть метод getIntent() для получения намерения, вызвавшего действие. Если вы хотите обработать намерение только при первом создании, вы можете сделать это из onCreate(). Как вы, возможно, знаете, onCreate() вызывается только тогда, когда действие еще не находится в памяти. - person rogerkk; 05.02.2011
comment
Хм, извините, я вижу, что не прочитал ваше обновление должным образом, поскольку вы уже пробовали это. Я делаю почти то же самое, что и вы, в одном из моих приложений, и единственная разница, которую я вижу прямо сейчас, заключается в том, что я использую режим запуска singleInstance и установил для android:alwaysRetainTaskState значение true. Мой onCreate() определенно не срабатывает при повторном открытии активности. - person rogerkk; 05.02.2011
comment
И просто чтобы убедиться... вы удалили вызов processDataFromBroadcast() из onNewIntent(), когда добавили его в onCreate()? :-) - person rogerkk; 05.02.2011
comment
Нет, processDataFromBroadcast вызывается в onCreate и onNewIntent, потому что, когда я получаю широковещательное уведомление, а MainActivity не существует, onNewInent не вызывается. Я предполагаю, что в моем случае onCreate запускается, потому что у моего эмулятора мало ресурсов, и система убивает активность. Когда это происходит, старое намерение getIntent() содержит некоторые данные, переданные из широковещательной рассылки в прошлый раз, и поэтому во время onCreate выполняются нежелательные действия. Я также пытался изменить намерение с помощью setIntent, но это также не работает. - person Solvek; 05.02.2011
comment
Вы выходите из активности, используя кнопку «Назад», кстати? Если это так, активность будет уничтожена и в следующий раз будет создана новая. Я также думаю, что onNewIntent() будет вызываться всякий раз, когда действие будет повторно открыто, независимо от того, будет ли оно перемещено на передний план вашим намерением или каким-либо другим способом. Возможно, вы захотите проверить тип намерения внутри onNewIntent() и запустить processDataFromBroadCast() только в том случае, если вы можете определить намерение как то, которое вы настраиваете вручную. - person rogerkk; 05.02.2011
comment
Наконец, если это не сработает, я бы по крайней мере рекомендовал добавить несколько операторов ведения журнала в onCreate() и onNewIntent(), чтобы увидеть, из какого метода processDataFromBroadcast() действительно запускается. - person rogerkk; 05.02.2011
comment
Вы правы rogerkk. onCreate вызывался только в том случае, если я перешел на задний план с помощью кнопки «Назад», в противном случае вызывается onNewActivity - точно так, как вы написали (и мой последний комментарий немного неверен). Но старое намерение передается либо в onCreate, либо в onNewIntent, и это приводит к повторному выполнению processDataFromBroadcast(), но я хочу, чтобы processDataFromBroadcast выполнялся только один раз. - person Solvek; 05.02.2011
comment
Я чувствую себя немного медленным, я не могу понять, что происходит, и я не понимаю, какие намерения срабатывают. Что вы подразумеваете под старым намерением? Не могли бы вы сделать краткий пример использования, чтобы я понял ход вещей, как они есть сейчас, и как вы действительно хотели бы, чтобы они были? - person rogerkk; 06.02.2011
comment
rogerkk - пожалуйста, посмотрите на мой последний абзац вопроса (обновлено) - person Solvek; 06.02.2011
comment
Спасибо за разъяснения! Я гуглил и экспериментировал, но боюсь, что не нашел решения для этого. - person rogerkk; 07.02.2011

если ваша проблема все еще не решена, так как я только что столкнулся с той же проблемой, вот как я ее решил:

Я ставлю временную метку как намерение Id в качестве дополнительного намерения во время его создания. в первый раз я обрабатываю намерение в onCreate() или onNewIntent(). Я читаю намерениеId и сохраняю его как последнее обработанное намерение. поэтому при следующем вызове onCreate() или onNewIntet() я могу проверить идентификатор намерения, и если он равен идентификатору последнего обработанного намерения, я игнорирую его! Не знаю, поможет ли это в вашем случае, возможно, вы сможете его принять.

Чтобы сохранить намерение Id независимым от жизненных циклов активности, вы можете сохранить его в userdefaults.

Я согласен, что можно ожидать, что вызов setIntent(new Intent()) в onNewIntent должен помочь.

person robscure    schedule 17.02.2012

Уже поздно отвечать, но это может быть полезно для других, ищущих решение.

Просто добавьте следующие строки кода:

Intent mIntent = new Intent(this, SplashActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // You need this if starting the activity from a service
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);

Где SplashActivity — это имя начального приложения, которое является первым экраном вашего приложения.

Надеюсь, поможет. :)

person Smeet    schedule 03.11.2014