Используйте постоянное уведомление, чтобы позволить пользователю вернуться к запущенному приложению Android - PullRequest
9 голосов
/ 25 августа 2010

Я занимаюсь разработкой приложения с многочисленными активностями.Я хотел бы создать постоянное уведомление, которое (более или менее) гласит: «AppName - Return to AppName», которое будет присутствовать при каждом запуске моих фоновых служб. Создание и удаление уведомления не составило проблем.

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

Моя первая попытка уродливого обходного пути состояла в том, чтобы выполнить действие (давайте назовем его"returnFromNotify"), чья единственная работа заключалась в том, чтобы "закончить" себя в своем "onCreate".Уведомление откроет «returnFromNotify» в области истории приложений, которая затем немедленно удалит себя, отправив пользователя обратно в предыдущее состояние истории в стеке приложений.Кажется, это работает ... если пользователь не использовал "назад", чтобы полностью выйти из приложения.Затем, когда они нажимают на уведомление, «returnFromNotify» загружается, а затем завершает работу, отправляя их обратно на домашний экран (так как в стеке операций для приложения нет операций).

Я подумал попытаться обнаружитьесли что-то было в стеке истории до «returnFromNotify», и если нет, запустите мою основную активность.Кажется, я тоже не могу найти способ сделать это.

Есть какие-либо предложения или предложения для новичка в Java / Android?К вашему сведению, моя основная история связана с языками сценариев.

Ответы [ 5 ]

6 голосов
/ 22 сентября 2012

Мне нравится ваша первоначальная идея создания действия "returnFromNotify" лучше, чем предложенный вами обходной путь, поскольку позволяет определить, находится ли ResumeActivity в нижней части стека (и, следовательно, единственное действие встек).

Вот как это можно сделать:

Добавьте свой ResumeActivity в манифест и укажите атрибут noHistory :

<activity android:name=".ResumeActivity" android:noHistory="true" />

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

Чтобы проверить стек приложения, вам также потребуется запросить разрешение GET_TASKS:

<uses-permission android:name="android.permission.GET_TASKS" />

Теперь вы можете использовать ActivityManager :: getRunningTasks () , чтобы определить, является ли ResumeActivity единственным действием в стеке:

public class ResumeActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if(isOnlyActivityInStack()) { //check the application stack
            //This activity is the only activity in the application stack, so we need to launch the main activity
            Intent main = new Intent(this, MainActivity.class);
            main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(main);
        } else {
            //Return the user to the last activity they had open
            this.finish();
        }
    }

    /**
     * Checks the currently running tasks. If this activity is the base activity, we know it's the only activity in the stack
     *
     * @return  boolean  This activity is the only activity in the stack?
     **/
    private boolean isOnlyActivityInStack() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        boolean onlyActivityInStack = false;

        for(RunningTaskInfo tasks : manager.getRunningTasks(Integer.MAX_VALUE)) {
            if(tasks.baseActivity.getPackageName().equals(this.getPackageName())) { //find this package's application stack
                if(tasks.baseActivity.getClassName().equals(this.getClass().getName())) {
                    //If the ResumeActivity is the base activity, we know that it is the only activity in the stack
                    onlyActivityInStack = true;
                    break;
                }
            }
        }

        return onlyActivityInStack;
    }

}

Я знаю, что вы задавали этот вопрос более 2лет назад, но я даю этот ответ на случай, если кто-то еще столкнется с этой конкретной ситуацией (как я сделал).Я думаю, что вы были на правильном пути с решением, над которым вы изначально работали.

3 голосов
/ 26 августа 2010

Хорошо, я считаю, что нашел удовлетворительный обходной путь для моего конкретного случая .Я добавил статическое целое число к своей mainActivity, и каждый раз, когда запускается onCreate, оно увеличивает целое число.Каждый раз, когда его "onDestroy" запускается, он уменьшается.

В моем "returnFromNotify" я смотрю на статическое целое число, чтобы увидеть, если оно больше 0. Если это так, я предполагаю, что есть активная "mainActivity", и что запущенный" финиш "внутри" returnFromNotify "вернется туда.В противном случае он предполагает, что пользователи «отступили», завершают свою работу, а затем используют «startActivity» для запуска нового экземпляра «mainActivity».

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

1 голос
/ 31 августа 2010

Мой первый подход заключается в использовании SharedPreferences и сохранении пары ключ-значение, которая называется что-то вроде lastDisplayedActivity. Тогда в каждом действии onResume (и, возможно, `onCreate ') у вас будет такая строка:

sharedPreferences.edit().putInteger("lastDisplayedActivity", ReturnFromNotify.THIS_ACTIVITY_NAME);

Другими словами, вы сохраняете переменную всего приложения, указывающую, какое действие было отображено в последний раз. Затем вы просто берете эту переменную из SharedPreferences и запускаете соответствующее действие.

1 голос
/ 30 августа 2010

Я думаю, что нет простого способа сделать это, но вместо добавления счетчика в mainActivity я бы расширил Приложение :

Базовый класс для тех, кому нужно поддерживать глобальное состояние приложения. Вы может обеспечить вашу собственную реализацию указав его имя в вашем AndroidManifest.xml-х тег, который приведет к тому, что этот класс будет создан для вас, когда процесс для вашего приложения / пакета создано.

Я бы описал логику и имел бы такой метод:

public Intent getIntentForLastActivityShown();

вызывается при нажатии на элемент уведомления.

0 голосов
/ 20 июля 2011

Я обычно использую действие с именем "Launcher", которое проверяет состояние моего приложения модель и запускает действия (или выполняет другие действия) в зависимости от правил модели.Я поместил объект Model в мой класс Application. Модель может использовать Предпочтения для сохранения своего состояния.Я делаю это, чтобы избежать статических полей в деятельности.

...