Как узнать, уничтожена ли моя активность в сервисе?

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

Все работает хорошо, но когда я нажимаю кнопку закрытия в своем уведомлении, когда мое приложение все еще работает, я получаю много NPE.

Код, который выполняется при нажатии кнопки закрытия в уведомлении:

mMediaSessionCompat.setCallback(new MediaSessionCompat.Callback() {
        @Override
        public void onStop() {
            super.onStop();
            Main.unbindService(getApplicationContext());
            stopSelf();
            Log.d(TAG,"stop!");
}

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

Итак, мой вопрос: как я могу определить, когда мое приложение все еще работает (видимо для пользователя или в фоновом режиме (последние приложения), и когда оно уничтожается и присутствует только уведомление?

Итак, я могу создать операторы if, чтобы вызывать stopSelf(); только тогда, когда приложение уничтожено, и не вызывать его, когда мое приложение все еще работает.


person Vince VD    schedule 11.06.2019    source источник


Ответы (1)


Возможно, вам может пригодиться метод Application.registerActivityLifecycleCallbacks(). Вы можете поместить что-то подобное в метод onCreate() вашего приложения:

registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
        int activityCount = 0;

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            activityCount++;
        }

        @Override
        public void onActivityStarted(Activity activity) {}

        @Override
        public void onActivityResumed(Activity activity) {}

        @Override
        public void onActivityPaused(Activity activity) {}

        @Override
        public void onActivityStopped(Activity activity) {}

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

        @Override
        public void onActivityDestroyed(Activity activity) {
            activityCount--;
        }
    });

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

EDIT: хорошо, если вы хотите избежать ситуации, когда завершенная активность зависает в течение некоторого времени до вызова метода onDestroyed(), вы можете использовать немного более продвинутый подход, когда вы проверяете, является ли активность заканчивая в onActivityPaused и onActivityStopped. Итак, вы делаете класс следующим образом:

private class ActivityWatcher implements Application.ActivityLifecycleCallbacks {

    //a set of currently running activities
    private Set<Activity> activities = new HashSet<>();

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        activities.add(activity);
    }

    @Override
    public void onActivityStarted(Activity activity) {}

    @Override
    public void onActivityResumed(Activity activity) {}

    @Override
    public void onActivityPaused(Activity activity) {
        if (activity.isFinishing()) {
            activities.remove(activity);
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if (activity.isFinishing()) {
            activities.remove(activity);
        }
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

    @Override
    public void onActivityDestroyed(Activity activity) {
        activities.remove(activity);
    }

    public boolean isAnyActivityRunning() {
        return !activities.isEmpty();
    }
}

а затем в своем классе приложения вы создаете экземпляр и регистрируете его как обратный вызов жизненного цикла активности:

public class MyApplication extends Application {

    private ActivityWatcher activityWatcher = new ActivityWatcher();

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(activityWatcher);
    }

    public boolean isAppAlive() {
        return activityWatcher.isAnyActivityRunning();
    }
}

Должно сработать.

person Michal Dvorak    schedule 12.06.2019
comment
OnDestroy не всегда вызывается, так что это небезопасный способ проверить, выполняется ли моя активность. - person Vince VD; 13.06.2019
comment
Если ваша активность не уничтожена, значит, она все еще работает, не так ли? В любом случае, если вы обеспокоены тем, что может пройти много времени, прежде чем завершенная активность будет действительно уничтожена, вы можете проверить в onActivityPaused, завершается ли активность (вызов activity.isFinishing()), и обработать ее так же, как уничтожение активности. Конечно, в этом случае вы не могли бы использовать простой счетчик, потому что вы могли бы уменьшить его дважды для одного действия. Вместо этого вам нужно будет отслеживать, какая активность завершается и/или уничтожается. - person Michal Dvorak; 13.06.2019
comment
Но кажется, что может быть ситуация, когда onDestroy не вызывается. stackoverflow.com/a/19608985 - person Vince VD; 13.06.2019
comment
И если это произойдет, мое приложение выйдет из строя, что негативно скажется на пользовательском опыте. - person Vince VD; 13.06.2019
comment
Да, onDestroy не будет вызываться, если ОС убьет весь ваш процесс. Но если это произойдет, вам тоже позовут в службу, так что вопрос спорный, не так ли? - person Michal Dvorak; 13.06.2019
comment
мой onDestroy не вызывается, когда я удаляю приложение из своих последних приложений по какой-то причине, но иногда он вызывается? - person Vince VD; 13.06.2019