欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

如何判断Android程序前后台切换的几种有效方法

程序员文章站 2022-04-07 18:24:49
Android在前后台切换时,我们可能需要做一些处理:发送 通知栏消息,提示APP在后台运行;或者我们需要暂停程序里的 某些线程,或者让线程池的执行时间降低,以保证较高的内...

Android在前后台切换时,我们可能需要做一些处理:发送

通知栏消息,提示APP在后台运行;或者我们需要暂停程序里的

某些线程,或者让线程池的执行时间降低,以保证较高的内存,

而避免被回收。那么我们有几种方式可以来判断呢?

思路1:在一个service里,使用一个线程,通过
ActivityManager.RunningAppProcessInfo轮询检测。

public class AppService extends Service implements Runnable{

    public static boolean isOnBackground = true;
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();

        new Thread(this).start();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void run() {
        while(true){
            boolean isOnBackgroundNew = DeviceUtils.isRunningOnBackground(this);
            Log.d("appstatus", "app is on background ? " + (isOnBackgroundNew ?"yes":"no"));

            if(isOnBackgroundNew != isOnBackground){
                //检测到前后台状态不一致,做一些处理
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public static boolean isRunningOnBackground(Context context){

        ActivityManager acm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        if(acm != null){
            List runApps = acm.getRunningAppProcesses();
            if(runApps != null && !runApps.isEmpty()){
                for(RunningAppProcessInfo app : runApps){
                    if(app.processName.equals(context.getPackageName())){
                        if(app.importance == RunningAppProcessInfo.IMPORTANCE_BACKGROUND){
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556

缺点:需要创建service,以及线程,暂用大量CPU时间;切换至后台运行时会有延迟。


思路2:实现一个BaseActivity,然后让我们应用程序的Activity都继承自BaseActivity,子类继承BaseActivity非私属性和方法,通过BaseActivity的onStart()和onStop()方法中进行判断应用程序是否进入到后台并且是否从后台返回到了前台。这里我曾经遇到一个坑,先来看看我的第一个版本实现吧。

public class BaseActivity extends Activity {

    public static boolean isBackground; //全局变量

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base);
    }

    @Override
    protected void onStart() {
        if (isBackground) {
            //app 从后台唤醒,进入前台
            isBackground = false;
            Log.i("ACTIVITY", "程序从后台唤醒");
        }
        super.onStart();
    }

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

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

    @Override
    protected void onStop() {
        if (isAppOnForeground()) {
            //app 进入后台
            isBackground = true;//记录当前已经进入后台
            Log.i("ACTIVITY", "程序进入后台");
        }
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    /**
     * APP是否处于前台唤醒状态
     *
     * @return
     */
    public boolean isAppOnForeground() {
        ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        String packageName = getApplicationContext().getPackageName();
        List appProcesses = activityManager
                .getRunningAppProcesses();
        if (appProcesses == null)
            return false;

        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            // The name of the process that this object is associated with.
            if (appProcess.processName.equals(packageName)
                    && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return true;
            }
        }

        return false;
    }
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869

isAppOnForeground()在不同的Android系统上返回值不同。我的想法是美好的,可是实际却是一个坑。当我点击home时,onStop也被调用了,可以isAppOnForeground()却返回false,系统还没更新状态吗?这可能要去深究源代码才清楚了。后来,就有了以下改进版。

public class BaseActivity extends Activity {

    public static boolean activityActive; //全局变量,表示当前在前台的activity数量
    public static boolean isBackground ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base);
    }

    @Override
    protected void onStart() {
        //app 从后台唤醒,进入前台
        activityActive++;
        isBackground = false;
        Log.i("ACTIVITY", "程序从后台唤醒");

        super.onStart();
    }

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

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

    @Override
    protected void onStop() {
        activityActive--;
        if (activityActive == 0) {
            //app 进入后台
            isBackground = true;//记录当前已经进入后台
            Log.i("ACTIVITY", "程序进入后台");
        }
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}
  • 12345678910111213141516171819202122232425262728293031323334353637383940414243444546

这个方法是不是很简单 ! ^_^

思路3:其实跟第二种改进版是一样的,只不过放在Application中实现了,感觉还是第二种方法简单哈。

public class TheApplication extends Application {

    private int mFinalCount;

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

            }

            @Override
            public void onActivityStarted(Activity activity) {
                mFinalCount++;
                //如果mFinalCount ==1,说明是从后台到前台
                Log.e("onActivityStarted", mFinalCount +"");
                if (mFinalCount == 1){
                    //说明从后台回到了前台
                }
            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {
                mFinalCount--;
                //如果mFinalCount ==0,说明是前台到后台
                Log.i("onActivityStopped", mFinalCount +"");
                if (mFinalCount == 0){
                    //说明从前台回到了后台
                }
            }

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

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });
    }
}
  • 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455