1. 程式人生 > >Android實現app長時間未操作時自動退出app

Android實現app長時間未操作時自動退出app

這裡要考慮3個問題,第一個是鎖屏問題,第二個是app被切換至後臺的問題,第三個是螢幕鎖定和解除時app在後臺時的問題

一,監聽螢幕解鎖,鎖定

public class ScreenObserver {

    private static String TAG = "ScreenObserver";
    private Context mContext;
    private ScreenBroadcastReceiver mScreenReceiver;
    private ScreenStateListener mScreenStateListener;
    private static Method mReflectScreenState;

    public ScreenObserver(Context context) {
        mContext = context;
        mScreenReceiver = new ScreenBroadcastReceiver();
        try {
            mReflectScreenState = PowerManager.class.getMethod("isScreenOn",
                    new Class[] {});
        } catch (NoSuchMethodException nsme) {
            Log.d(TAG, "API < 7," + nsme);
        }
    }

    /**
     * screen狀態廣播接收者
     *
     * @author xishaomin
     *
     */
    private class ScreenBroadcastReceiver extends BroadcastReceiver {
        private String action = null;

        @Override
        public void onReceive(Context context, Intent intent) {
            action = intent.getAction();
            if (Intent.ACTION_SCREEN_ON.equals(action)) {
                mScreenStateListener.onScreenOn();
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                mScreenStateListener.onScreenOff();
            }else if(Intent.ACTION_USER_PRESENT.equals(action)){
                LogUtils.d("---->螢幕解鎖完成");
            }
        }
    }

    /**
     * 請求screen狀態更新
     *
     * @param listener
     */
    public void requestScreenStateUpdate(ScreenStateListener listener) {
        mScreenStateListener = listener;
        startScreenBroadcastReceiver();

        firstGetScreenState();
    }

    /**
     * 第一次請求screen狀態
     */
    private void firstGetScreenState() {
        PowerManager manager = (PowerManager) mContext
                .getSystemService(Activity.POWER_SERVICE);
        if (isScreenOn(manager)) {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOn();
            }
        } else {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOff();
            }
        }
    }

    /**
     * 停止screen狀態更新
     */
    public void stopScreenStateUpdate() {
        mContext.unregisterReceiver(mScreenReceiver);
    }

    /**
     * 啟動screen狀態廣播接收器
     */
    private void startScreenBroadcastReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        //當用戶解鎖螢幕時
        filter.addAction(Intent.ACTION_USER_PRESENT);
        mContext.registerReceiver(mScreenReceiver, filter);
    }

    /**
     * screen是否開啟狀態
     *
     * @param pm
     * @return
     */
    private static boolean isScreenOn(PowerManager pm) {
        boolean screenState;
        try {
            screenState = (Boolean) mReflectScreenState.invoke(pm);
        } catch (Exception e) {
            screenState = false;
        }
        return screenState;
    }

    public interface ScreenStateListener {
        public void onScreenOn();

        public void onScreenOff();
    }
    /**
     * 判斷螢幕是否已被鎖定
     * @param c
     * @return
     */
    public final static boolean isScreenLocked(Context c)
    {
        android.app.KeyguardManager mKeyguardManager = (KeyguardManager) c
                .getSystemService(Context.KEYGUARD_SERVICE);
        return mKeyguardManager.inKeyguardRestrictedInputMode();
    }  

    /**
     * 判斷當前應用是否是本應用
     * @param context
     * @return
     */
    public static boolean isApplicationBroughtToBackground(final Context context) {
        ActivityManager am = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> tasks = am.getRunningTasks(1);
        if (!tasks.isEmpty()) {
            ComponentName topActivity = tasks.get(0).topActivity;
            if (!topActivity.getPackageName().equals(context.getPackageName())) {
                return true;
            }
        }
        return false;
    }
}

然後在app的BaseActivity中實現ScreenObserver

       private ScreenObservermScreenObserver;

       @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mScreenObserver = new ScreenObserver(this);
        mScreenObserver.requestScreenStateUpdate(new ScreenStateListener() {
            @Override
            public void onScreenOn() {
                if(!ScreenObserver.isApplicationBroughtToBackground(MainActivity.this))
                {
                    cancelAlarmManager();
                }
            }

            @Override
            public void onScreenOff() {
                if(!ScreenObserver.isApplicationBroughtToBackground(MainActivity.this))
                {
                    cancelAlarmManager();
                    setAlarmManager();
                }
            }
        });

    }

///此處省略一大坨程式碼
/**
 * 設定定時器管理器
 */
private void setAlarmManager()
{

        long numTimeout = 300*1000;//5分鐘
        LogUtils.d("isTimeOutMode=yes,timeout="+numTimeout);
        Intent alarmIntent = new Intent(MainActivity.this, TimeoutService.class);
        alarmIntent.putExtra("action", "timeout"); //自定義引數
        PendingIntent pi = PendingIntent.getService(MainActivity.this, 1024, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
        long triggerAtTime =  (System.currentTimeMillis()+numTimeout);
        am.set(AlarmManager.RTC_WAKEUP, triggerAtTime, pi); //設定的一次性鬧鐘,這裡決定是否使用絕對時間
        LogUtils.d("----->設定定時器");
    }
    /**
     * 取消定時管理器
     */
    private void cancelAlarmManager()
    {
        AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(MainActivity.this, TimeoutService.class);
        PendingIntent pi = PendingIntent.getService(MainActivity.this, 1024, intent,PendingIntent.FLAG_UPDATE_CURRENT);
        // 與上面的intent匹配(filterEquals(intent))的鬧鐘會被取消
        alarmMgr.cancel(pi);
        LogUtils.d("----->取消定時器");
    }

        @Override
    protected void onResume() {
        LogUtils.e("MainActivity-onResume");
        super.onResume();
        cancelAlarmManager();
        activityIsActive = true;
        LogUtils.d("activityIsActive="+activityIsActive);
    }

    @Override
    protected void onStop() {
        LogUtils.e("onStop");
        super.onStop();
        if (ScreenObserver.isApplicationBroughtToBackground(this))
        {
            cancelAlarmManager();
            setAlarmManager();
        }
    }

然後在後臺finishActivity

public class TimeoutService extends Service implements AppConstants {

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

    boolean isrun = true;

    @Override
    public void onCreate() {
        LogUtils.e("BindService-->onCreate()");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtils.e("BindService-->onStartCommand()");
        forceApplicationExit();
        return super.onStartCommand(intent, flags, startId);

    }

    private void forceApplicationExit()
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ActivityListUtil.getInstence().cleanActivityList();
                stopSelf();
                    }
            }).start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isrun = false;
    }

}

ActivityListUtil類如下

public class ActivityListUtil {
    private static ActivityListUtil instence;
    public ArrayList<Activity> activityList;

    public ActivityListUtil() {
        activityList = new ArrayList<Activity>();
    }
    public static ActivityListUtil getInstence()
    {
        if (instence == null) {
            instence = new ActivityListUtil();
        }
        return instence;
    }
    public void addActivityToList(Activity activity) {
        if(activity!=null)
        {
            activityList.add(activity);
        }
    }
    public void removeActivityFromList(Activity activity)
    {
        if(activityList!=null && activityList.size()>0)
        {
            activityList.remove(activity);
        }
    }
    public void cleanActivityList() {
        if (activityList!=null && activityList.size() > 0) {
            for (int i = 0; i < activityList.size(); i++) {
                Activity activity = activityList.get(i);
                if(activity!=null && !activity.isFinishing())
                {
                    activity.finish();
                }
            }
        }

    }
}