Наличие одного экземпляра активности

У меня проблема с навигацией по Activity и задним стеком, и я надеялся, что вы сможете прояснить это для меня.

Проблема

Корневая активность >>> SecondActivity >> HomeButton

Затем я попадаю на домашнюю страницу, и оттуда я выбираю ...

Gmail >> Сообщение >> Открыть вложение в моем приложении >> ImportActivity >> RootActivity

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

Желаемый результат

Я хочу, чтобы произошло то, что пользователь открывает вложение, а ImportActivity завершает свои действия (для него android:noHistory установлено значение true) и вызывает startActivity(intent), RootActivity запускается, но сохраняет только один экземпляр, а остальные действия, расположенные поверх него в исходной задаче (в данном случае SecondActivity), удаляются.

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

Что я пробовал

Я поигрался с режимом запуска, но ни один из них не дает мне той функциональности, которая мне нужна.

Режимы запуска, которые я пробовал ..

android: launchMode = "singleTask" - это просто запускало корневую активность каждый раз при ее запуске. Даже если пользователь нажал кнопку «Домой» внутри моего приложения и коснулся значка приложения, задний стек был уничтожен.

android: launchMode = "singleInstance = не разрешает выполнение каких-либо других действий в задаче.

Также при вызове намерения запустить RootActivity я безрезультатно использовал следующее.

Intent i = new Intent(ImportActivity.this,TrackingActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);

Можно ли делать то, что я хочу?

Заранее благодарим


person StuStirling    schedule 12.12.2012    source источник
comment
Вы пробовали использовать флаг Single Top?   -  person Vinay S Shenoy    schedule 12.12.2012
comment
А как насчет RootActivity в режиме singleTask, где вы сохраняете его состояние в onPause (). Когда пользователь возвращается в RootActivity, создается новый экземпляр, который считывает сохраненное состояние.   -  person onosendai    schedule 15.12.2012
comment
Используйте Intent.FLAG_ACTIVITY_CLEAR_TASK при запуске TrackingActivity   -  person Sherif elKhatib    schedule 17.12.2012
comment
Вы пробовали мое предложение относительно taskAffinity?   -  person David Wasser    schedule 19.12.2012


Ответы (3)


Ты говоришь

Gmail >> Message >> Open attachment in my application >> ImportActivity >> RootActivity

но это может быть не так. В этом случае Gmail выдаст Intent адрес ImportActivity в вашем приложении. ImportActivity будет выполняться. Однако мое чтение https://developer.android.com/guide/components/tasks-and-back-stack.html предполагает, что ImportActivity будет выполняться как часть той же задачи, что и gmail, и будет помещен в верхнюю часть заднего стека для задачи gmail, если вы не предпримете особых действий. в манифесте, чтобы предотвратить это, или Gmail специально вызывает его как отдельную задачу. Когда ImportActivity завершает работу, он не должен вызывать startActivity(intentForRootActivity), а должен просто вызывать finish(), чтобы он был уничтожен и появилось действие из gmail, которое находится под ним в заднем стеке.

Если ImportActivity действительно вызвал startActivity(intentForRootActivity), то RootActivity просто перешел бы в начало задачи Gmail и появился бы в обратном стеке Gmail. Коснувшись home, а затем значка запуска Gmail, вы увидите, как RootActivity снова появится, скрывая под собой Gmail.

Я думаю, вам нужно android:launchMode="standard" в декларации манифеста ImportActivity.

Задача, представляющая старый автономный экземпляр вашего приложения, не будет изменена. Если кто-то коснется значка запуска вашего приложения, старое состояние вашего приложения будет восстановлено, независимо от того, что произошло в задаче Gmail.

Документ http://developer.android.com/guide/components/processes-and-threads.html довольно расплывчато описывает, как здесь действия отображаются на процессы (в результате чего Дэвид Вассер прокомментировал мою более раннюю версию этого ответа), но кажется, что действия gmail будут выполняться в одном процессе Linux с одним идентификатор пользователя linux, а ImportActivity будет выполняться в другом процессе Linux с другим идентификатором пользователя. Однако все они могут составлять часть одной задачи с одним задним стеком.

ImportActivity будет выполняться как часть задачи gmail с тем же эффективным идентификатором пользователя Linux, как если бы он выполнялся как часть вашего автономного приложения, и отличался от идентификатора пользователя Linux, с которым работает gmail. Это звучит маловероятно и сложно, но, похоже, подразумевается https://developer.android.com/guide/components/fundamentals.html. В этом есть смысл; если ImportActivity необходимо получить, скажем, пользовательские настройки, сохраненные для вашего приложения, ему необходимо прочитать файл настроек, как если бы это был пользователь, определенный для вашего приложения, а не пользователь, определенный для Gmail.

Я ничего из этого не пробовал. Если я возьму совсем не тот конец палки, я уверен, что кто-то скоро нам об этом скажет!

person emrys57    schedule 17.12.2012
comment
Ваши утверждения в начале этого ответа неверны. Вы путаете 2 совершенно разных понятия: задача Android НЕ является процессом операционной системы. Модель безопасности для Android использует уникальные идентификаторы пользователей для каждого приложения и полагается на механизм безопасности операционной системы. Это означает, что ваш код никогда не будет выполняться в том же пространстве процесса (памяти), что и код Gmail, и у него никогда не будет того же идентификатора пользователя, что и у Gmail (или любого другого приложения. ). Действие импорта может находиться в том же стеке задач, что и приложение Gmail, это зависит от того, как Gmail начинает действие. - person David Wasser; 17.12.2012
comment
Да, я согласен с вами, что задача не является процессом, и что идентификаторы пользователей зависят от приложения, и что стек задач import может зависеть от того, как gmail отправляет намерение. Не могли бы вы направить меня к документу, в котором объясняется, как действия отображаются на процессы? Я не мог его найти. - person emrys57; 17.12.2012
comment
developer.android.com/guide/components/ Первый В абзаце говорится, что компоненты (Activity, Service, BroadcastReceiver, ContentProvider) приложения выполняются вместе в одном процессе (по умолчанию). При желании вы можете указать в манифесте, какие компоненты запускаются в каком процессе. Подробное описание модели безопасности (которое также многое объясняет о компонентах, процессах и т. Д.) Можно найти здесь: source.android.com/tech/security/index.html - person David Wasser; 17.12.2012
comment
Да, спасибо, я отыскал это и переписал ответ, пока вы печатали. Все компоненты приложения по умолчанию запускаются в одном процессе, но что происходит с Activity, которое является частью другого приложения, которое в данный момент не запущено? Это не однозначно. Однако я согласен, что ваша интерпретация кажется более вероятной, чем моя первоначальная. Спасибо за исправление. - person emrys57; 17.12.2012
comment
Первое предложение: когда компонент приложения запускается, а в приложении не работают другие компоненты, система Android запускает новый процесс Linux для приложения с одним потоком выполнения. Итак, это ясно. Если я запускаю одно из ваших действий, а ваше приложение не работает, создается новый процесс для размещения вашего действия. - person David Wasser; 17.12.2012

Для этого не нужно никаких специальных launchMode. Если ваша операция импорта запускает корневую операцию с Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP, это должно делать то, что вы хотите. Полагаю, у вас проблема с taskAffinity. Попробуй это:

В своем манифесте в объявлении importActivity добавьте следующее:

android:taskAffinity=""

Если это не сработает, опубликуйте свой манифест, чтобы мы могли его рассмотреть.

person David Wasser    schedule 17.12.2012

Я действительно не уверен, получил ли я это, но если вы хотите перейти к своей "корневой" деятельности без потери лишнего стека приложений, это будет Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP прямо на флагах на вашем intent, и без дополнительных конфигураций на _3 _... и если вам нужно разделить задачу для создания нового полного нового стека, вы можете использовать Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP, как вы описали.

person Pozzo Apps    schedule 12.12.2012
comment
Извините, если я не понял, и я не думаю, что вы ответили на него здесь. Я хочу потерять свой предыдущий стек, если вызывается ImportActivity. Оттуда я перехожу к RootActivity предыдущей задачи. Я не хочу двух отдельных задач - person StuStirling; 12.12.2012
comment
android: launchMode = singleTask на мэйнфесте в ImportActivity. Система создает действие в корне новой задачи и направляет ей намерение. Однако, если экземпляр действия уже существует, система направляет намерение существующему экземпляру через вызов своего метода onNewIntent (), а не создает новый. - person Pozzo Apps; 12.12.2012
comment
Я хочу быть в основе деятельности RootActivity. Я пробовал singleTask на нем, однако всегда казалось, что он создает новую задачу вместо (как вы цитировали) системы, перенаправляющей намерение в существующий экземпляр - person StuStirling; 12.12.2012
comment
Вы пробовали использовать android: launchMode = singleInstance на своем AndroidManifest.xml? - person vsm; 13.12.2012
comment
Да, проблема в том, что тогда это действие будет само по себе ... - person StuStirling; 14.12.2012