分享

Android系统亮屏、锁屏、屏幕解锁事件(解决部分手机亮屏后未解锁即进入resume状态)

 tracyf 2015-03-13


有一部分三星的手机关闭屏幕以后,刚打开屏幕,前台的activity就会resume状态,因为我们使用cocos2d-x引擎,默认resume和activity的resume事件是一致的,我们在resume里把关闭的声音重新打开,所以导致,用户点亮屏幕以后(尚未解锁),就会听到游戏内的声音(如果在关闭屏幕时我们游戏处于前台)。


为了解决这个问题,我们需要修改我们resume触发的时机。确保在解锁以后才进入我们游戏的resume状态。
那么我们游戏应该在什么时机进入resume状态呢?
  1. 系统activity进入resume状态时刻,并且屏幕是亮的,屏幕未锁定
  2. 屏幕刚刚亮起,并且屏幕 未锁定,系统activity已经进入resume状态
  3. 屏幕 解锁,这是屏幕肯定是亮的,并且activity已经进入resume状态

那么有了上面的三点相信逻辑代码不难写,下面介绍一下如何坚挺系统屏幕灭,屏幕亮,解锁屏幕 的事件,以及如何判断当前屏幕 是否是解锁状态(因为用户可以设置关闭屏幕后是否锁定屏幕 ,所以解锁屏幕 事件可能根本就不会被触发,那么我们就不能通过跟踪事件来确定其状态)

要坚挺屏幕亮、屏幕灭、屏幕 解锁三个事件我们需要在代码中注册监听ACTION_SCREEN_ONACTION_SCREEN_OFFACTION_USER_PRESENT三个Action,具体的写法如下:

  1. /** 
  2.  * screen状态广播接收者 
  3.  */  
  4. private class ScreenBroadcastReceiver extends BroadcastReceiver{  
  5.     @Override  
  6.     public void onReceive(Context context, Intent intent) {  
  7.         if(Intent.ACTION_SCREEN_ON.equals(intent.getAction())){               
  8.             mScreenStateListener.onScreenOn();  
  9.         }else if(Intent.ACTION_SCREEN_OFF.equals(intent.getAction())){  
  10.             mScreenStateListener.onScreenOff();  
  11.         }else if(Intent.ACTION_USER_PRESENT.equals(intent.getAction())){  
  12.             mScreenStateListener.onUserPresent();  
  13.         }  
  14.     }  
  15. }  

  1. /** 
  2.  * 停止screen状态更新 
  3.  */  
  4. public void stopScreenStateUpdate() {  
  5.     mContext.unregisterReceiver(mScreenReceiver);  
  6. }  
  7.   
  8. /** 
  9.  * 启动screen状态广播接收器 
  10.  */  
  11. private void startScreenBroadcastReceiver() {  
  12.     IntentFilter filter = new IntentFilter();  
  13.     filter.addAction(Intent.ACTION_SCREEN_ON);  
  14.     filter.addAction(Intent.ACTION_SCREEN_OFF);  
  15.     filter.addAction(Intent.ACTION_USER_PRESENT);  
  16.     mContext.registerReceiver(mScreenReceiver, filter);  
  17. }  


因为屏幕在灭了以后是否锁定可以由用户设置,所以我们不能通过跟踪解锁事件来判断其状态,需要一个可以时时获取状态的函数:
  1. //判断屏幕是否被锁定  
  2. public final static boolean isScreenLocked(Context c) {  
  3.     android.app.KeyguardManager mKeyguardManager = (KeyguardManager) c.getSystemService(c.KEYGUARD_SERVICE);  
  4.     return mKeyguardManager.inKeyguardRestrictedInputMode();  
  5. }  

需要注意的是,大部分事件都可以在AndroidManifest.xml中注册,但是ACTION_SCREEN_ON、ACTION_SCREEN_OFF、ACTION_USER_PRESENT这几个事件在PowerManager那边做了限制,必须像上面那样在代码中注册,才能监听到,所以大家不要踩到坑哦~~~

下面是包装屏幕事件的一个类代码,仅供参考:
  1. package com.example.myfirstapp;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import android.app.Activity;  
  6. import android.app.KeyguardManager;  
  7. import android.content.BroadcastReceiver;  
  8. import android.content.Context;  
  9. import android.content.Intent;  
  10. import android.content.IntentFilter;  
  11. import android.os.PowerManager;  
  12. import android.util.Log;  
  13.   
  14. /** 
  15.  * 监听屏幕ON和OFF PRESENT状态 
  16.  *  
  17.  * @author 
  18.  * @2014 
  19.  *  
  20.  */  
  21. public class ScreenObserver {  
  22.     private static String TAG = "ScreenObserver";  
  23.     private Context mContext;  
  24.     private ScreenBroadcastReceiver mScreenReceiver;  
  25.     private ScreenStateListener mScreenStateListener;  
  26.     private static Method mReflectScreenState;  
  27.   
  28.     public ScreenObserver(Context context) {  
  29.         mContext = context;  
  30.         mScreenReceiver = new ScreenBroadcastReceiver();  
  31.         try {  
  32.             mReflectScreenState = PowerManager.class.getMethod("isScreenOn",  
  33.                     new Class[] {});  
  34.         } catch (Exception nsme) {  
  35.             Log.d(TAG, "API < 7," + nsme);  
  36.         }  
  37.     }  
  38.   
  39.     /** 
  40.      * screen状态广播接收者 
  41.      */  
  42.     private class ScreenBroadcastReceiver extends BroadcastReceiver {  
  43.         @Override  
  44.         public void onReceive(Context context, Intent intent) {  
  45.             if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {  
  46.                 mScreenStateListener.onScreenOn();  
  47.             } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {  
  48.                 mScreenStateListener.onScreenOff();  
  49.             } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {  
  50.                 mScreenStateListener.onUserPresent();  
  51.             }  
  52.         }  
  53.     }  
  54.   
  55.     /** 
  56.      * 请求screen状态更新 
  57.      */  
  58.     public void requestScreenStateUpdate(ScreenStateListener listener) {  
  59.         mScreenStateListener = listener;  
  60.         startScreenBroadcastReceiver();  
  61.         firstGetScreenState();  
  62.     }  
  63.   
  64.     /** 
  65.      * 第一次请求screen状态 
  66.      */  
  67.     private void firstGetScreenState() {  
  68.         PowerManager manager = (PowerManager) mContext  
  69.                 .getSystemService(Activity.POWER_SERVICE);  
  70.         if (isScreenOn(manager)) {  
  71.             if (mScreenStateListener != null) {  
  72.                 mScreenStateListener.onScreenOn();  
  73.             }  
  74.         } else {  
  75.             if (mScreenStateListener != null) {  
  76.                 mScreenStateListener.onScreenOff();  
  77.             }  
  78.         }  
  79.     }  
  80.   
  81.     /** 
  82.      * 停止screen状态更新 
  83.      */  
  84.     public void stopScreenStateUpdate() {  
  85.         mContext.unregisterReceiver(mScreenReceiver);  
  86.     }  
  87.   
  88.     /** 
  89.      * 启动screen状态广播接收器 
  90.      */  
  91.     private void startScreenBroadcastReceiver() {  
  92.         IntentFilter filter = new IntentFilter();  
  93.         filter.addAction(Intent.ACTION_SCREEN_ON);  
  94.         filter.addAction(Intent.ACTION_SCREEN_OFF);  
  95.         filter.addAction(Intent.ACTION_USER_PRESENT);  
  96.         mContext.registerReceiver(mScreenReceiver, filter);  
  97.     }  
  98.   
  99.     /** 
  100.      * screen是否打开状态 
  101.      */  
  102.     private static boolean isScreenOn(PowerManager pm) {  
  103.         boolean screenState;  
  104.         try {  
  105.             screenState = (Boolean) mReflectScreenState.invoke(pm);  
  106.         } catch (Exception e) {  
  107.             screenState = false;  
  108.         }  
  109.         return screenState;  
  110.     }  
  111.   
  112.     // 外部调用接口  
  113.     public interface ScreenStateListener {  
  114.         public void onScreenOn();  
  115.   
  116.         public void onScreenOff();  
  117.   
  118.         public void onUserPresent();  
  119.     }  
  120.   
  121.     public final static boolean isScreenLocked(Context c) {  
  122.         android.app.KeyguardManager mKeyguardManager = (KeyguardManager) c  
  123.                 .getSystemService(c.KEYGUARD_SERVICE);  
  124.         return mKeyguardManager.inKeyguardRestrictedInputMode();  
  125.     }  
  126. }  


上面代码参考:http://blog.csdn.net/m_changgong/article/details/7608911,特此注明。


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多