Как узнать, работает ли приложение Android на переднем плане? - PullRequest
81 голосов
/ 31 марта 2011

Я делаю уведомление в строке состояния в моем приложении для Android, которое запускается c2dm.Я не хочу отображать уведомление, если приложение работает.Как определить, запущено ли приложение и находится ли оно на переднем плане?

Ответы [ 18 ]

2 голосов
/ 06 января 2015

Я хотел бы добавить, что более безопасный способ сделать это - чем проверить, находится ли ваше приложение в фоновом режиме перед созданием уведомления, - это просто отключить и включить Broadcast Receiver onPause () и onResume () соответственно.

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

@Override
protected void onPause() {
    unregisterReceiver(mHandleMessageReceiver);
    super.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));
}
2 голосов
/ 12 мая 2017

Вот метод, который я использую (и поддерживающий метод):

private boolean checkIfAppIsRunningInForeground() {
    ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
    for(ActivityManager.RunningAppProcessInfo appProcessInfo : activityManager.getRunningAppProcesses()) {
        if(appProcessInfo.processName.contains(this.getPackageName())) {
            return checkIfAppIsRunningInForegroundByAppImportance(appProcessInfo.importance);
        }
    }
    return false;
}

private boolean checkIfAppIsRunningInForegroundByAppImportance(int appImportance) {
    switch (appImportance) {
        //user is aware of app
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE:
            return true;
        //user is not aware of app
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE:
        default:
            return false;
    }
}
1 голос
/ 25 ноября 2015

Вот код для простого простого решения, описанного выше пользователем @ user2690455. Хотя это выглядит немного многословно, вы увидите, что в целом оно довольно легкое

В моем случае мы также используем AppCompatActivity, поэтому мне пришлось иметь 2 базовых класса.

public class BaseActivity extends Activity {

    /**
     * Let field be set only in base class
     * All callers must use accessors,
     * and then it's not up to them to manage state.
     *
     * Making it static since ..
     * 1. It needs to be used across two base classes
     * 2. It's a singleton state in the app
     */
    private static boolean IS_APP_IN_BACKGROUND = false;

    @Override
    protected void onResume() {
        super.onResume();

        BaseActivity.onResumeAppTracking(this);

        BaseActivity.setAppInBackgroundFalse();
    }

    @Override
    protected void onStop() {
        super.onStop();

        BaseActivity.setAppInBackgroundTrue();
    }

    @Override
    protected void onPause() {
        super.onPause();

        BaseActivity.setAppInBackgroundFalse();
    }

    protected static void onResumeAppTracking(Activity activity) {

        if (BaseActivity.isAppInBackground()) {

            // do requirements for returning app to foreground
        }

    }

    protected static void setAppInBackgroundFalse() {

        IS_APP_IN_BACKGROUND = false;
    }

    protected static void setAppInBackgroundTrue() {

        IS_APP_IN_BACKGROUND = true;
    }

    protected static boolean isAppInBackground() {

        return IS_APP_IN_BACKGROUND;
    }
}
1 голос
/ 24 ноября 2013

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

public static boolean isAppInForeground(Context context) {
  List<RunningTaskInfo> task =
      ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
          .getRunningTasks(1);
  if (task.isEmpty()) {
    return false;
  }
  return task
      .get(0)
      .topActivity
      .getPackageName()
      .equalsIgnoreCase(context.getPackageName());
}

Как уже упоминалось в других ответах, вам необходимо добавить следующее разрешение к вашему AndroidManifest.xml.

<uses-permission android:name="android.permission.GET_TASKS"/>
0 голосов
/ 10 июля 2016

Предыдущие подходы, упомянутые здесь, не являются оптимальными.Подход, основанный на задачах, требует разрешения, которое может быть нежелательным, а «булевский» подход склонен к одновременным ошибкам модификации.

Подход, который я использую и который (я считаю) работает довольно хорошо в большинстве случаев:

Наличие класса "MainApplication" для отслеживания количества операций в AtomicInteger :

import android.app.Application;

import java.util.concurrent.atomic.AtomicInteger;

public class MainApplication extends Application {
    static class ActivityCounter {
        private static AtomicInteger ACTIVITY_COUNT = new AtomicInteger(0);

        public static boolean isAppActive() {
            return ACTIVITY_COUNT.get() > 0;
        }

        public static void activityStarted() {
            ACTIVITY_COUNT.incrementAndGet();
        }

        public static void activityStopped() {
            ACTIVITY_COUNT.decrementAndGet();
        }
    }
}

И создание базового класса действий, который будут расширяться другими действиями:

import android.app.Activity;
import android.support.annotation.CallSuper;

public class TestActivity extends Activity {
    @Override
    @CallSuper
    protected void onStart() {
        MainApplication.ActivityCounter.activityStarted();
        super.onStart();
    }

    @Override
    @CallSuper
    protected void onStop() {
        MainApplication.ActivityCounter.activityStopped();
        super.onStop();
    }
}
0 голосов
/ 28 марта 2016
     public static boolean isAppRunning(Context context) {

 // check with the first task(task in the foreground)
 // in the returned list of tasks

   ActivityManager activityManager = (ActivityManager)
   context.getSystemService(Context.ACTIVITY_SERVICE);
 List<RunningTaskInfo> services =
 activityManager.getRunningTasks(Integer.MAX_VALUE);
     if
     (services.get(0).topActivity.getPackageName().toString().equalsIgnoreCase(context.getPackageName().toString()))
     {
     return true;
     }
     return false;
     }
0 голосов
/ 06 октября 2018

Начиная с версии 26 библиотеки поддержки, вы можете использовать ProcessLifecycleOwner для определения текущего состояния приложения, просто добавьте его в свои зависимости, как описано здесь , например:

dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData).
    //     Support library depends on this lightweight import
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // use kapt for Kotlin
}

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

 boolean isAppInForeground = ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
 if(!isAppInForeground)
    //Show Notification in status bar
0 голосов
/ 11 апреля 2015

Для этого не существует глобального обратного вызова, но для каждого действия это onStop ().Вам не нужно связываться с атомным Int.Просто создайте глобальное целое число с числом запущенных операций, для каждого действия увеличивайте его в onStart () и уменьшайте в onStop ().

Follow this

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...