zoukankan      html  css  js  c++  java
  • 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();
                    }
                }
            }
    
        }
    }
    
  • 相关阅读:
    perl 监控网站域名劫持
    OpenLayers访问Geoserver发布的地图
    基于OpenLayers的地图封装Javascript类定义
    Linux_正则表达式
    Linux_正则表达式
    帆软出品: 7点搞定制药企业数据分析系统开发需求
    帆软出品: 7点搞定制药企业数据分析系统开发需求
    Geoserver地图样式SLD资料收集
    GeoServer地图开发解决方案:地图数据处理篇
    Geoserver发布shapfile,中文字段乱码问题
  • 原文地址:https://www.cnblogs.com/dubo-/p/7885417.html
Copyright © 2011-2022 走看看