1. 程式人生 > >Android app新增後臺拉起機制

Android app新增後臺拉起機制

本demo原始碼下載地址 App拉起機制原始碼下載

簡介:

做智慧售賣裝置需要app一直在前臺顯示,但是有時由於一些不當操作或者系統原因會使app退出,導致裝置不能使用。這時就需要拉起機制了。

拉起機制目前實現方式主要有2種。

1、利用Activity生命週期

建立一個類MyApp繼承自Application類,在該類通過監聽所有activity生命週期來判斷activity是否全部銷燬,以此來判斷app是否退出。
程式碼如下:

/**
*  監聽各個Activity生命週期情況
*/
private void startActivityLifeListener(){
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            showLog("add activity "+activity.toString());
        }

        @Override
        public void onActivityStarted(Activity activity) {
            mActivityCount++;
            showLog(activity.getComponentName()+" onActivityStarted activityCounts= "+mActivityCount);
        }

        @Override
        public void onActivityResumed(Activity activity) {

        }

        @Override
        public void onActivityPaused(Activity activity) {
            showLog(activity.getComponentName().toString()+" onActivityPaused");
        }

        @Override
        public void onActivityStopped(Activity activity) {
            mActivityCount--;
            showLog(activity.getComponentName()+" onActivityStopped activityCounts= "+mActivityCount);
            if (mActivityCount <= 0){
                // 5秒後拉起
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        showLog("try to restart");
                        Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                    }
                }, 5000);
            }
        }

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

        }

        @Override
        public void onActivityDestroyed(Activity activity) {
            showLog("remove activity "+activity.toString());
        }
    });
}

然後在onCreate方法裡面呼叫startActivityLifeListener()方法。
在這裡插入圖片描述

2、利用RunningAppProcessInfo類判斷

通過ActivityManager類獲取所有正在執行的程序,然後利用app包名找到應用的執行程序,再判斷是否處於後臺,不過該方法在有些系統版本可能不能用。
建立一個遠端服務類PullUpService在後臺一直執行輪詢檢查app是否後臺執行。程式碼如下:

package com.mhwang.apppullup;

import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;

import java.util.List;

/** 後臺拉起服務
* Author : mhwang
* Date : 2018/11/6
* Version : V1.0
*/
public class PullUpService extends Service implements Runnable{
    private boolean running = false;
    private Intent intent;
    private Thread thread;

    private static void showLog(String s){
        Log.d("PullUpService=>", s);
    }

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

    public void onCreate(){
        super.onCreate();
        intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
        if (intent != null) {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        showLog("onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        showLog("onStartCommand");
        if(thread == null){
            thread = new Thread(this);
            thread.start();
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        showLog("onDestroy");
        running = false;
        if(thread != null && !thread.isInterrupted()){
            try {
                thread.interrupt();
                thread.join(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        thread = null;
        super.onDestroy();
    }

    @Override
    public void run() {
        running = true;
        showLog("background service start");
        while(running){
            showLog("check background");
            if(isBackground(PullUpService.this)){
                showLog("restart activity");
                startActivity(intent);
            }
            SystemClock.sleep(10 * 1000);         // 由於模擬器較卡,這裡提高10秒檢查一次
        }
    }

    /** 判斷是否處於後臺
     * @param context
     * @return true:處於後臺, false:不處於後臺
     */
    public static boolean isBackground(Context context) {
        ActivityManager activityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
                .getRunningAppProcesses();
        if(appProcesses == null){
            return false;
        }
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.processName.equals(context.getPackageName())) {
                if (appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        return false;
    }

}

記得在AndroidMainifest.xml註冊該服務。

<service android:name=".PullUpService" android:process=":remote"/>

然後在MyApp類開啟服務:
在這裡插入圖片描述

如下圖所示,使用back鍵和home鍵退出app,每隔5秒後都能有效拉起(圖示效果執行在模擬器系統版本4.4.2)。但是有個缺點就是使用多工鍵殺死時,由於此時整個app都被幹掉了,因此MyApp裡面的拉起機制不能生效。
在這裡插入圖片描述