Android 锁屏机制

Android 禁止系统休眠,使屏幕不变暗,保持游戏中屏幕高亮

实现这一功能的方法有两种,一种是在Manifest.xml文件里面声明,一种是在代码里面修改LayoutParams的标志位。具体如下:

1、在Manifest.xml文件里面用user-permission声明。代码如下:

  •    
  •      



  这种方法,在安装apk时,系统会提示安装人是否允许使用禁止休眠功能。

2、在程序中用代码实现。代码如下:

  • getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

================================================================

锁屏机制分析

  1.         /** Called when the ringer mode changes. */
  2.         void onRingerModeChanged(int state);
  3.         /** 电话状态发生了改变  值可能为:EXTRA_STATE_IDLE、EXTRA_STATE_RINGING、EXTRA_STATE_OFFHOOK*/
  4.         void onPhoneStateChanged(String newState);
  5.     }
  6.     /** Callback to notify of sim state change. */
  7.     interface SimStateCallback {
  8.         void onSimStateChanged(IccCard.State simState); //Sim卡信息发生了改变,例如有正常状况变为ABSENT/MISSING状态
  9.     }[/align][align=left]    /*** Register to receive notifications about general keyguard information
  10.      * (see [url=mailto:%7B@link]{@link[/url] InfoCallback}. */
  11.     public void registerInfoCallback(InfoCallback callback) {
  12.         if (!mInfoCallbacks.contains(callback)) {
  13.             mInfoCallbacks.add(callback);  //注册一个监听器
  14.         } ...
  15.     }
  16.    ...
  17. }

复制代码 7, LockPatternKeyguardView类  (自定义ViewGroup)
功能:作为LockScreen和UnLockScreen界面的载体,控制显示哪个界面。
              其源代码释义如下:

  1. public class LockPatternKeyguardView extends KeyguardViewBase {
  2.      ...
  3.      private View mLockScreen;
  4.      private View mUnlockScreen;     private boolean mScreenOn = false;//是否亮屏   enum Mode {
  5.          //当前显示界面的Mode Lock 或者UnLock
  6.      }
  7.      enum UnlockMode {
  8.          ...//开锁界面的几种不同Mode
  9.      }
  10.      //构造函数
  11.      public LockPatternKeyguardView( ...) {     
  12.          //KeyguardScreenCallback的实现对象
  13.          mKeyguardScreenCallback = new KeyguardScreenCallback() {
  14.             ...
  15.          };
  16.          ...
  17.      }
  18.      public void reset() {
  19.         ...//重置显示界面
  20.      }
  21.      private void recreateLockScreen() {
  22.             ...//重新构建LockScreen
  23.      }
  24.      private void recreateUnlockScreen() {
  25.         ...//重新构建UnlockScreen
  26.      }
  27.      private void recreateScreens() {
  28.         ...//重新构建该视图
  29.      }
  30.      public void verifyUnlock() {
  31.         ...
  32.      }
  33.      public void cleanUp() {
  34.             ... //清理资源对象
  35.      }
  36.      private boolean isSecure() {
  37.         ...//手机设置是否处于安全状态
  38.      }
  39.      private void updateScreen(final Mode mode) {
  40.         ...//根据参数(Lock/unLock),判断显示为LockScreen或者UnlockScreen界面
  41.      }
  42.      View createLockScreen() {
  43.             ...//创建lockScreen
  44.      }
  45.      View createUnlockScreenFor(UnlockMode unlockMode) {
  46.         ...//根据不同的Unlock Mode , 创建不同的UnlockScreen
  47.      }
  48.      private Mode getInitialMode() {
  49.         ...//得到初始化的状态Mode (lock or unlock).
  50.      }
  51.      /** Given the current state of things, what should the unlock screen be? */
  52.      private UnlockMode getUnlockMode() {
  53.         ...//返回开锁的状态Unlock Mode
  54.      }
  55.      private void showTimeoutDialog() {
  56.          ... //输入密码超过一定次数时,提示30s后在登录的对话框
  57.      }
  58.      private void showAlmostAtAccountLoginDialog() {
  59.         ... //显示Google 账户登录对话框
  60.      }
  61. }

复制代码
8、KeyguardViewBase类  抽象类  (自定义ViewGroup)

功能:为LockPatternKeyguardView提供了一组通用的方法  。需要值得注意的方法就是他对某些KeyEvent的监听,
      当他消费监听到这些KeyEvent,我们的App就监听不到这些KeyEvent了  。常用的有KEYEVENT_VOLUME_UP/DOWN等。

  1. public abstract class KeyguardViewBase extends FrameLayout {
  2.          ...
  3.   @Override
  4.     public boolean dispatchKeyEvent(KeyEvent event) {
  5.         ...
  6.         if (interceptMediaKey(event)) {
  7.             return true;
  8.         }
  9.         return super.dispatchKeyEvent(event);
  10.     }   private boolean interceptMediaKey(KeyEvent event) {
  11.         final int keyCode = event.getKeyCode();
  12.         if (event.getAction() == KeyEvent.ACTION_DOWN) {
  13.             switch (keyCode) {
  14.                 ...//more keyevent
  15.                 case KeyEvent.KEYCODE_VOLUME_UP:
  16.                 case KeyEvent.KEYCODE_VOLUME_DOWN: {
  17.                     ...
  18.                     // Don't execute default volume behavior
  19.                     return true; //直接返回不在向下传递处理
  20.                 }
  21.             }
  22.         }
  23.         return false;
  24.     }
  25. }

复制代码
9、 KeyguardViewProperties.java 接口
                 功能:提供了创建界面的通用方法。

  1.    public interface KeyguardViewProperties {  
  2.             //创建一个KeyguardViewBase实例 , 实际是指LockPatternKeyguardView实例
  3.             KeyguardViewBase createKeyguardView(Context context,
  4.                     KeyguardUpdateMonitor updateMonitor,
  5.                     KeyguardWindowController controller);[/align][align=left]            boolean isSecure();
  6.         }

复制代码
其唯一实现类是是LockPatternKeyguardViewProperties类(稍后讲到)。

10、 LockPatternKeyguardViewProperties
                 源代码释义如下:

  1. public class LockPatternKeyguardViewProperties implements KeyguardViewProperties {
  2.     ...
  3.     //创建一个LockPatternKeyguardView对象
  4.     public KeyguardViewBase createKeyguardView(Context context,
  5.             KeyguardUpdateMonitor updateMonitor,
  6.             KeyguardWindowController controller) {
  7.         return new LockPatternKeyguardView(context, updateMonitor,
  8.                 mLockPatternUtils, controller);
  9.     }
  10. }

复制代码
11、KeyguardViewMediator核心类  ,该类是唯一实现了KeyguardViewCallback的类。
           功能:  功能:该类提供了一些接口,由PhoneWindowManager)去访问控制Keyguard....
该类的初始化是在PolicyWindowManager的构造函数中创建的。如下:

  1. public class PhoneWindowManager implements WindowManagerPolicy {
  2.            ...
  3.           /** [url=mailto:%7B@inheritDoc]{@inheritDoc[/url]} */  //由SystemServer调用
  4.           public void init(Context context, IWindowManager windowManager,
  5.                   LocalPowerManager powerManager) {
  6.               ...//初始化该实例
  7.               mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
  8.           }
  9.   }
  10.   

复制代码
参照源代码,把一些重要的属性和方法的大意给分析下:

  1. public class KeyguardViewMediator implements KeyguardViewCallback, KeyguardUpdateMonitor.SimStateCallback {
  2.     private boolean mSystemReady;  //启动成功 由SystemServer调用[/size][/font][/align][align=left][font=微软雅黑][size=16px]    /**Used to keep the device awake while to ensure the keyguard finishes opening before
  3.      * we sleep.*/ //在需要显示锁屏界面时,保持屏幕在某个时间段内为暗屏状态  
  4.     private PowerManager.WakeLock mShowKeyguardWakeLock;
  5.     private KeyguardViewManager mKeyguardViewManager; //KeyguardViewManager实例
  6.     /**  * External apps (like the phone app) can tell us to disable the keygaurd.*/
  7.     //是否允许其他App禁止锁屏 , 例如来电时 禁止锁屏
  8.     private boolean mExternallyEnabled = true;
  9.     //处于锁屏状态 , 即显示锁屏
  10.     private boolean mShowing = false;
  11.     // true if the keyguard is hidden by another window
  12.     private boolean mHidden = false; //被其他窗口掩盖 , 例如来电时锁屏被掩盖
  13.     private boolean mScreenOn = false; // 是否亮屏[/size][/font][/align][align=left][font=微软雅黑][size=16px]    public KeyguardViewMediator(Context context, PhoneWindowManager callback,
  14.             LocalPowerManager powerManager) {
  15.         ...
  16.         //构造相关实例对象
  17.         mKeyguardViewProperties = new LockPatternKeyguardViewProperties(
  18.                 new LockPatternUtils(mContext), mUpdateMonitor);[/size][/font][/align][align=left][size=16px][font=微软雅黑]        mKeyguardViewManager = new KeyguardViewManager(
  19.                 context, WindowManagerImpl.getDefault(), this,
  20.                 mKeyguardViewProperties, mUpdateMonitor);
  21.         //解锁成功后发送的Intent
  22.         mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
  23.         mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
  24.     }
  25.    
  26.     //屏幕变灰暗  , 原因有如下:以及对应的逻辑处理。
  27.     // 1、OFF_BECAUSE_OF_USER : 用户按下POWER键 , 当前是否处于锁屏界面,若是(mShowing)则重置显示界面,否则重新显示锁屏界面
  28.     // 2、OFF_BECAUSE_OF_TIMEOUT : 屏幕超时,常见情况就是一段时间没有操作屏幕,手机处于灰暗状态。          处理行为:   
  29.     //     发送Action值为DELAYED_KEYGUARD_ACTION的广播,因为该类注册了该Intent广播,接受到时会调用doKeyguard()方法锁屏
  30.     // 3、OFF_BECAUSE_OF_PROX_SENSOR:接打电话时,距离感应太近导致暗屏,此时由于PowerManager那儿已经处理了暗屏,不需要做任何事
  31.     // 最后,如果以上逻辑都不成立,调用 doKeyguard()方法显示屏幕                       
  32.     public void onScreenTurnedOff(int why) {
  33.        ...
  34.     }
  35.     /**
  36.      * Let's us know the screen was turned on.
  37.      */
  38.     public void onScreenTurnedOn() {
  39.         synchronized (this) {
  40.             ...
  41.             notifyScreenOnLocked();  //通知亮屏
  42.         }
  43.     }
  44.     /** Enable the keyguard if the settings are appropriate. */
  45.     private void doKeyguard() {
  46.         synchronized (this) {
  47.             ...
  48.             showLocked();//显示锁屏界面
  49.         }
  50.     }
  51.     //该方法的调用时机就是当按下POWER键时,系统会回调该方法 keyCode值一般为 26
  52.     public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode) {
  53.         //操作按键是否能唤醒屏幕
  54.         if (isWakeKeyWhenKeyguardShowing(keyCode)) {
  55.             // give the keyguard view manager a chance to adjust the state of the
  56.             // keyguard based on the key that woke the device before poking
  57.             // the wake lock
  58.             wakeWhenReadyLocked(keyCode);//开始唤醒屏幕咯
  59.             return true;
  60.         } else {
  61.             return false;
  62.         }
  63.     }
  64.     /** [/font][url=mailto:%7B@inheritDoc][font=微软雅黑]{@inheritDoc[/font][/url][font=微软雅黑]} */  //在一定时间内保存屏幕为亮屏状态
  65.     public void pokeWakelock(int holdMs) {
  66.         ...
  67.     }
  68.     //表示成功得分完成了解锁操作
  69.     public void keyguardDone(boolean authenticated, boolean wakeup) {
  70.         synchronized (this) {
  71.             //发送给Handler 进行异步处理
  72.             Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
  73.             msg.arg1 = wakeup ? 1 : 0;
  74.             mHandler.sendMessage(msg);
  75.             if (authenticated) {
  76.                 mUpdateMonitor.clearFailedAttempts(); //清除错误登录次数
  77.             }
  78.             ...
  79.         }
  80.     }
  81.     //Handler对象 , 异步处理
  82.     private Handler mHandler = new Handler() {
  83.         @Override
  84.         public void handleMessage(Message msg) {
  85.             switch (msg.what) {
  86.               ...  //异步处理
  87.             }
  88.         }
  89.     };
  90.     //异步处理完成开锁成功
  91.     private void handleKeyguardDone(boolean wakeup) {
  92.         handleHide(); //释放该Keyguard对应的窗口
  93.         mWakeLock.release();
  94.         mContext.sendBroadcast(mUserPresentIntent); //解锁成功,发送Intent信息
  95.     }
  96.     //显示锁屏界面
  97.     private void handleShow() {
  98.         synchronized (KeyguardViewMediator.this) {
  99.             ...
  100.             mKeyguardViewManager.show();
  101.             mShowing = true;
  102.             ...
  103.         }
  104.     }
  105.     private void handleHide() {
  106.         synchronized (KeyguardViewMediator.this) {
  107.             //去除锁屏界面对应的窗口
  108.             mKeyguardViewManager.hide();
  109.             mShowing = false;
  110.            ...
  111.         }
  112.     }
  113.     //设置状态栏enable状态 , 例如:能否被下拉等
  114.     private void adjustStatusBarLocked() {
  115.             ...
  116.             // if the keyguard is shown, allow the status bar to open
  117.             // only if the keyguard is insecure and is covered by another window
  118.             boolean enable = !mShowing || (mHidden && !isSecure());
  119.             mStatusBarManager.disable(enable ?StatusBarManager.DISABLE_NONE : StatusBarManager.DISABLE_EXPAND);
  120.         }
  121.     }
  122. }

复制代码
该类的很多方法都是由PhoneWindowManager调用访问的。

  基本上把一些重要的类及其相关的方法给走了一遍吧,对看源码的还是很有帮助的。因为我的理解还不是很深入,可能有偏颇的
  地方。希望以后能够组件完善 起来。 阿门 !

问题:如何在框架中, 解除锁屏 ?

引入:该问题是在CSDN论坛上回答一位网友引发的,最开始由于我也只是简单看了下,因此也就事论事回答了一个小问题。
  随着看的越来越深入,慢慢的也在心里长生了涟漪。经过尝试、烧鸡验证,发现如下办法行的通,而且效果还比较好。风险应该
  比较小吧。  希望正在在框架修改的同学,慎重行事。

基本思路:毫无疑问,我的想法就是每次需要显示Keyguard---锁屏界面时,我们并不真正的去锁屏,而只是提供了一个空的
  方法去给系统调用,让系统觉得我们“锁屏”了,同样也不去真正的隐藏“锁屏”界面,提供一个空壳给系统调用。由于可能涉及
  到其它问题,例如:能否下拉状态栏,按下POWER键后,屏幕很快休眠等。Come on ,我们需要统一做处理。

所有步骤函数都发生在KeyguardViewMediator 类中,注释部分为我们所添加的。
Step  1、  取消  真正的去锁屏实现

  1. //该方法会显示锁屏界面,我们使其成为一个空壳子
  2. private void handleShow() {
  3.     synchronized (KeyguardViewMediator.this) {
  4.         if (DEBUG) Log.d(TAG, "handleShow");
  5.         if (!mSystemReady) return;[/font][/size][/align][align=left][size=16px][font=微软雅黑]        playSounds(true);
  6.         //Begin : Modifid by qinjuning     
  7.         
  8.         //mKeyguardViewManager.show();  //   
  9.         //mShowing = true;              //
  10.         //adjustUserActivityLocked();   //
  11.         //adjustStatusBarLocked();     //取消对状态栏的控制
  12.         
  13.         //End
  14.         try {
  15.             ActivityManagerNative.getDefault().closeSystemDialogs("lock");
  16.         } catch (RemoteException e) {
  17.         }
  18.         mShowKeyguardWakeLock.release();
  19.     }
  20. }

复制代码
Step  2、  取消  真正的去隐藏锁屏实现

  1. //真正的隐藏屏幕实现
  2. private void handleHide() {
  3.     synchronized (KeyguardViewMediator.this) {
  4.         if (DEBUG) Log.d(TAG, "handleHide");
  5.         if (mWakeAndHandOff.isHeld()) {
  6.             Log.w(TAG, "attempt to hide the keyguard while waking, ignored");
  7.             return;
  8.         }
  9.         // only play "unlock" noises if not on a call (since the incall UI
  10.         // disables the keyguard)
  11.         if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
  12.             playSounds(false);
  13.         }
  14.         //Begin : Modifid by qinjuning  
  15.         
  16.         //mKeyguardViewManager.hide();
  17.         //mShowing = false;
  18.         //adjustUserActivityLocked();      
  19.         //adjustStatusBarLocked();         //取消对状态栏的控制
  20.         
  21.         //End
  22.     }
  23. }

复制代码
以上两步行动后,存在一个Bug(问题),就是唤醒屏幕后,会在指定的时间内屏幕由亮变暗,我们还需要做如下修改

Step 3、按下POWER键时,  解除屏幕由亮变暗的Bug

  1. private void handleWakeWhenReady(int keyCode) {
  2.     synchronized (KeyguardViewMediator.this) {
  3.         if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")");[/font][/size][/align][align=left][size=16px][font=微软雅黑]        // this should result in a call to 'poke wakelock' which will set a timeout
  4.         // on releasing the wakelock
  5.         if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) {
  6.             // poke wakelock ourselves if keyguard is no longer active
  7.             Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves");
  8.             //Begin : Modifid by qinjuning  
  9.             //pokeWakelock();  //按下POWER键时, 解除屏幕由亮变暗的Bug   
  10.             //End
  11.         }
  12.         /**
  13.          * Now that the keyguard is ready and has poked the wake lock, we can
  14.          * release the handoff wakelock
  15.          */
  16.         mWakeAndHandOff.release();[/font][/size][/align][align=left][size=16px][font=微软雅黑]        if (!mWakeLock.isHeld()) {
  17.             Log.w(TAG, "mWakeLock not held in mKeyguardViewManager.wakeWhenReadyTq");
  18.         }
  19.     }
  20. }

复制代码
经过真机测试是通过的,但其他风险并不清楚。  这个方法只是提供了一个学习的途径吧。大家慎重行事。

    上面Step 1、以及Step 2可以由如下方法代替:
  将属性
mExternallyEnabled 设置为 false,  接下来需要显示界面时都不会继续走下去,如下函数:

  1. /**
  2. * Enable the keyguard if the settings are appropriate.
  3. */  //显示界面
  4. private void doKeyguard() {
  5.     synchronized (this) {
  6.         // if another app is disabling us, don't show
  7.         if (!mExternallyEnabled) {   //mExternallyEnabled 为false
  8.             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");[/font][/size][/align][align=left][size=16px][font=微软雅黑]            // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
  9.             // for an occasional ugly flicker in this situation:
  10.             // 1) receive a call with the screen on (no keyguard) or make a call
  11.             // 2) screen times out
  12.             // 3) user hits key to turn screen back on
  13.             // instead, we reenable the keyguard when we know the screen is off and the call
  14.             // ends (see the broadcast receiver below)
  15.             // TODO: clean this up when we have better support at the window manager level
  16.             // for apps that wish to be on top of the keyguard
  17.             return;
  18.         }
  19.         ...
  20.     }
  21. }

复制代码
该方法的一个缺点就是,假如存在重新调用了setKeyguardEnabled()设置该值,一切都是白搭( 但从源码看,这点不可能 现,因为存 在另一个判断依据:变量 mNeedToReshowWhenReenabled ,  其初始值为false,只有成功禁止锁屏之后才置为( true )。 此,我们可以 仿照这个方法,主动添加一个 私有变量,禁止显示锁屏界面,即禁止doKeyguard()方法继续走下去。

OK ,本文到此为止。讲的比较抽象。  大家看代码时多加理解才是王道 。

显然易见,手机厂商,基于框架只需要修改LockScreen这个自定义ViewGroup即可,其他的一套Google已经为我们
   封装 好了。

在框架层修改肯定不是最好的,对于第三方的App而言,实现不了该功能。还好,SDK为我们提供了接口类去处理隐藏锁屏接口
的方法,该类是KeyguardManager类,关于该类的简介请参考该 KeyguardManager简介

     我们可以通过KeyguardManager类实例获得一个KeyguardManager.KeyguardLock对象,进而调用相应方法去取消锁屏界面
示锁屏界面。
KeyguardManager.KeyguardLock的两个方法说明如下:


public void disableKeyguard  ()
功能:取消锁屏界面显示,同时禁止显示锁屏界面。除非你显示调用了reenableKeyguard()方法使能显示锁屏界面。

public void reenableKeyguard  ()功能:  使能显示锁屏界面,如果你之前调用了disableKeyguard()方法取消锁屏界面,那么会马上显示锁屏界面。

这两个方法最终都会调用到KeyguardViewMediator类的setKeyguardEnabled(boolean  enable)方法。
            参数说明: enable = false  对应于disableKeyguard()方法,
enable = true  对应于reenableKeyguard()方法。

   该方法原型为:  位于KeyguardViewMediator类中

  1. /**
  2. * Same semantics as [url=mailto:%7B@link]{@link[/url] WindowManagerPolicy#enableKeyguard}; provide
  3. * a way for external stuff to override normal keyguard behavior.  For instance
  4. * the phone app disables the keyguard when it receives incoming calls.
  5. */
  6. public void setKeyguardEnabled(boolean enabled) {
  7.     synchronized (this) {
  8.         mExternallyEnabled = enabled;  //保存值,该值会在doKeyguard()时用到,如果为false ,则不进行锁屏[/font][/size][/align][align=left][size=16px][font=微软雅黑]        if (!enabled && mShowing) {
  9.             if (mExitSecureCallback != null) {//该判断为false
  10.                 ...
  11.                 return ;
  12.             }
  13.             mNeedToReshowWhenReenabled = true;  //置为真,以便下次调用
  14.             hideLocked(); //已经显示了锁屏界面,则取消隐藏界面
  15.         } else if (enabled && mNeedToReshowWhenReenabled) { //重新显示锁屏界面
  16.             mNeedToReshowWhenReenabled = false;[/font][/size][/align][align=left][size=16px][font=微软雅黑]            if (mExitSecureCallback != null) {//该判断为false
  17.               
  18.             } else {
  19.                 showLocked(); //显示隐藏界面
  20.                 ...
  21.             }
  22.         }
  23.     }
  24. }

复制代码
使用这两个方法时,记得加上如下权限android.permission.DISABLE_KEYGUARD

为了在亮屏时,达到取消显示界面的效果,我们还需要知道  一下两个广播:

    屏幕变暗以及屏幕点亮的广播


android.intent.action.SCREEN_ON  --- 屏幕变亮
android.intent.action.SCREEN_OFF ---- 屏幕点暗


        关于这两个广播的说明请参考: android 自定义锁屏

于是在监听到屏幕变暗/变亮时,通过KeyguardManager 类实现即可。对与用户而言,就相当于解除了锁屏界面了。
   可能代码如下:

  1. //屏幕变暗/变亮的广播 , 我们要调用KeyguardManager类相应方法去解除屏幕锁定
  2.         private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver(){
  3.                 @Override
  4.                 public void onReceive(Context context , Intent intent) {
  5.                         String action = intent.getAction() ;
  6.                         
  7.                     Log.i(TAG, intent.toString());
  8.                     
  9.                         if(action.equals("android.intent.action.SCREEN_OFF")
  10.                                         || action.equals("android.intent.action.SCREEN_ON") ){
  11.                                 mKeyguardManager = (KeyguardManager)context.getSystemService(Context.KEYGUARD_SERVICE);
  12.                                 mKeyguardLock = mKeyguardManager.newKeyguardLock("zdLock 1");
  13.                                 mKeyguardLock.disableKeyguard();
  14.                                 startActivity(zdLockIntent);
  15.                         }
  16.                 }
  17.                
  18.         };

复制代码
最后,可能有些同学在做App时,可能想获取系统的登录次数等,例如:登录失败次数等 ; Android系统已经 为我们提供好了框架去处理,具体对应类是DevicePolicyManager类,关于该类的具体使用请参见该:
利用DevicePolicyManager执行屏幕锁定

你可能感兴趣的:(Android)