Android检查应用是否已关闭

时间:2017-03-03 10:42:33

标签: android android-activity android-lifecycle android-activitymanager

我有一个Android应用程序,我需要一个功能或任何广播接收器,可以检查应用程序是否关闭..我不需要在每个活动中调用destroy(应用程序中有大约20个活动) 我试图在应用程序类

中添加此功能
public class ApplicationLifeCycleManager implements ActivityLifecycleCallbacks {

/** Manages the state of opened vs closed activities, should be 0 or 1.
 * It will be 2 if this value is checked between activity B onStart() and
 * activity A onStop().
 * It could be greater if the top activities are not fullscreen or have
 * transparent backgrounds.
 */
private static int visibleActivityCount = 0;

/** Manages the state of opened vs closed activities, should be 0 or 1
 * because only one can be in foreground at a time. It will be 2 if this
 * value is checked between activity B onResume() and activity A onPause().
 */
private static int foregroundActivityCount = 0;

/** Returns true if app has foreground */
public static boolean isAppInForeground(){
    return foregroundActivityCount > 0;
}

/** Returns true if any activity of app is visible (or device is sleep when
 * an activity was visible) */
public static boolean isAppVisible(){
    return visibleActivityCount > 0;
}

public void onActivityCreated(Activity activity, Bundle bundle) {
}

public void onActivityDestroyed(Activity activity) {
    Log.wtf("destroyed","app closed!!");
}

public void onActivityResumed(Activity activity) {
    foregroundActivityCount ++;
}

public void onActivityPaused(Activity activity) {
    foregroundActivityCount --;
}

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

public void onActivityStarted(Activity activity) {
    visibleActivityCount ++;
}

public void onActivityStopped(Activity activity) {
    visibleActivityCount --;
}
}

此外,我已在应用程序类

中创建了
@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(new ApplicationLifeCycleManager());
}

但是当我在activity之间切换时会调用onPaused和onResumed以及onDestroyed函数:因为它检测是否有任何活动被关闭或被破坏甚至恢复

所以检查应用程序是否在一个函数中关闭的任何解决方案??

6 个答案:

答案 0 :(得分:5)

此答案使用ProcessLifecycleOwner来检测应用程序可见性。

Android Architecture Component的一部分。


1。将此库添加到您的项目中

implementation "android.arch.lifecycle:extensions:1.1.1"

2。扩展实现LifecycleObserver的应用程序类

public class AppController extends Application implements LifecycleObserver {


///////////////////////////////////////////////
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onEnterForeground() {
        Log.d("AppController", "Foreground");
        isAppInBackground(false);
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onEnterBackground() {
        Log.d("AppController", "Background");
        isAppInBackground(true);
    }
///////////////////////////////////////////////



    // Adding some callbacks for test and log
    public interface ValueChangeListener {
        void onChanged(Boolean value);
    }
    private ValueChangeListener visibilityChangeListener;
    public void setOnVisibilityChangeListener(ValueChangeListener listener) {
        this.visibilityChangeListener = listener;
    }
    private void isAppInBackground(Boolean isBackground) {
        if (null != visibilityChangeListener) {
            visibilityChangeListener.onChanged(isBackground);
        }
    }
    private static AppController mInstance;
    public static AppController getInstance() {
        return mInstance;
    }



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

        mInstance = this;

        // addObserver
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }

}

并像这样使用它:

AppController.getInstance().setOnVisibilityChangeListener(new ValueChangeListener() {
    @Override
    public void onChanged(Boolean value) {
        Log.d("isAppInBackground", String.valueOf(value));
    }
});

不要忘记将应用程序name添加到您的manifest

<application
    android:name="myPackageName.AppController"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"">

完成。


(Kotlin示例)

https://github.com/jshvarts/AppLifecycleDemo

答案 1 :(得分:2)

您可以使用此功能确定应用是否已关闭(不在后台或前台)。

private boolean isAppRunning() {
    ActivityManager m = (ActivityManager) this.getSystemService( ACTIVITY_SERVICE );
    List<ActivityManager.RunningTaskInfo> runningTaskInfoList =  m.getRunningTasks(10);
    Iterator<ActivityManager.RunningTaskInfo> itr = runningTaskInfoList.iterator();
    int n=0;
    while(itr.hasNext()){
        n++;
        itr.next();
    }
    if(n==1){ // App is killed
        return false;
    }

    return true; // App is in background or foreground
}

您还可以使用此功能检查应用是否在前台: https://stackoverflow.com/a/8490088/9005188

答案 2 :(得分:1)

基本上查看您的问题,您希望跟踪应用中的状态更改。

要正确处理所有用例可能非常困难。但是有一个令人惊叹的库,它非常好用,非常容易使用 - RxAppState

我已经使用这个库很长一段时间了,它在所有情况下都能很好地工作。 我强烈建议您试试这个。

答案 3 :(得分:0)

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (isAppForground(context)) {
            // App is in Foreground
        } else {
            // App is in Background
        }
    }

     private boolean isAppOnForeground(Context context,String appPackageName) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        if (appProcesses == null) {
             //App is closed
            return false;
        }
        final String packageName = appPackageName;
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
     //                Log.e("app",appPackageName);
                return true;
            }else{
                //App is closed
            }
        }
        return false;
    }

}  

添加此权限

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

试试希望它有所帮助

答案 4 :(得分:0)

就像@ S.R答案一样,您也可以在自定义应用程序中使用接口“ Application.ActivityLifecycleCallbacks”,然后在“ onActivityStopped”中使用“ isAppOnForeground(Context)”方法。

public class MyApplication extends Application import Application.ActivityLifecycleCallbacks{

[ Code of ur app class...]

/* START Override ActivityLifecycleCallbacks Methods */
    @Override
    public void onActivityCreated(Activity activity, Bundle bundle) {
        mActivitiesBackStack.add(activity.getClass());
    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {
        if(!AppUtils.isAppOnForeground(this)){
            [Code when app in background...]
        }
    }

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

    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        if(mActivitiesBackStack.contains(activity.getClass())){
            mActivitiesBackStack.remove(activity.getClass());
        }
    }
    /* END Override ActivityLifecycleCallbacks Methods */

[ Code of ur app class...]

应用每次在后台运行时都会调用,而不是在关闭时调用。 如果将“ isAppOnForeground”放入“ onActivityDestroyed”中,则它将与上面的“ isAppOnForeground”代码不兼容,因为它找不到进程(我认为),也许更改了上面的代码或使用了其他实现,它将起作用。 关闭应用程序时将调用“ onActivityDestroyed”,因此,如果您可以在调用时检查该应用程序是否在后台(因此该应用程序已关闭),则可以精确地关闭该应用程序的那一刻。 / p>

“ isAppOnForeground”的代码(我在Utils静态类中使用它):

public static boolean isAppOnForeground(Context context) {
        boolean ret = false;
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        if(appProcesses != null){
            String packageName = context.getPackageName();
            for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
                if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
                    ret = true;
                }
            }
        }
        return ret;
    }

希望这会有所帮助,再见,祝您编程愉快! :D

答案 5 :(得分:-1)

使用一项从Application类开始的服务。

public class AppService extends Service {

    @Override
    public void onTaskRemoved(Intent rootIntent) {

        super.onTaskRemoved(rootIntent);
        //here you will get call when app close.
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

从Application类启动此服务。

@Override
public void onCreate() {
    super.onCreate();
    Intent intent = new Intent(getApplicationContext(), AppService.class);
    startService(intent);
}