有一部分三星的手機關閉螢幕以後,剛開啟螢幕,前台的activity就會resume狀態,因為我們使用cocos2d-x引擎,預設resume和activity的resume事件是一致的,我們在resume裡把關閉的聲音重新開啟,所以導致,使用者點亮螢幕以後(尚未解鎖),就會聽到遊戲內的聲音(如果在關閉螢幕時我們遊戲處於前台)。
為瞭解決這個問題,我們需要修改我們resume觸發的時機。確保在解鎖以後才進入我們遊戲的resume狀態。那麼我們遊戲應該在什麼時機進入resume狀態呢?
系統activity進入resume狀態時刻,並且螢幕是亮的,螢幕未鎖定
螢幕剛剛亮起,並且螢幕 未鎖定,系統activity已經進入resume狀態
螢幕 解鎖,這是螢幕肯定是亮的,並且activity已經進入resume狀態
那麼有了上面的三點相信邏輯代碼不難寫,下面介紹一下如何堅挺系統螢幕滅,螢幕亮,解鎖螢幕 的事件,以及如何判斷當前螢幕 是否是解鎖狀態(因為使用者可以設定關閉螢幕後是否鎖定螢幕 ,所以解鎖螢幕 事件可能根本就不會被觸發,那麼我們就不能通過跟蹤事件來確定其狀態)
要堅挺螢幕亮、螢幕滅、螢幕 解鎖三個事件我們需要在代碼中註冊監聽ACTION_SCREEN_ON、ACTION_SCREEN_OFF、ACTION_USER_PRESENT三個Action,具體的寫法如下:
/** * screen狀態廣播接收者 */private class ScreenBroadcastReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {if(Intent.ACTION_SCREEN_ON.equals(intent.getAction())){mScreenStateListener.onScreenOn();}else if(Intent.ACTION_SCREEN_OFF.equals(intent.getAction())){mScreenStateListener.onScreenOff();}else if(Intent.ACTION_USER_PRESENT.equals(intent.getAction())){mScreenStateListener.onUserPresent();}}}
/** * 停止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);}
因為螢幕在滅了以後是否鎖定可以由使用者佈建,所以我們不能通過跟蹤解鎖事件來判斷其狀態,需要一個可以時時擷取狀態的函數:
//判斷螢幕是否被鎖定public final static boolean isScreenLocked(Context c) {android.app.KeyguardManager mKeyguardManager = (KeyguardManager) c.getSystemService(c.KEYGUARD_SERVICE);return mKeyguardManager.inKeyguardRestrictedInputMode();}
需要注意的是,大部分事件都可以在AndroidManifest.xml中註冊,但是ACTION_SCREEN_ON、ACTION_SCREEN_OFF、ACTION_USER_PRESENT這幾個事件在PowerManager那邊做了限制,必須像上面那樣在代碼中註冊,才能監聽到,所以大家不要踩到坑哦~~~
下面是封裝螢幕事件的一個類代碼,僅供參考:
package com.example.myfirstapp;import java.lang.reflect.Method;import android.app.Activity;import android.app.KeyguardManager;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.PowerManager;import android.util.Log;/** * 監聽螢幕ON和OFF PRESENT狀態 * * @author * @2014 * */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 (Exception nsme) {Log.d(TAG, "API < 7," + nsme);}}/** * screen狀態廣播接收者 */private class ScreenBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {mScreenStateListener.onScreenOn();} else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {mScreenStateListener.onScreenOff();} else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {mScreenStateListener.onUserPresent();}}}/** * 請求screen狀態更新 */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是否開啟狀態 */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();public void onUserPresent();}public final static boolean isScreenLocked(Context c) {android.app.KeyguardManager mKeyguardManager = (KeyguardManager) c.getSystemService(c.KEYGUARD_SERVICE);return mKeyguardManager.inKeyguardRestrictedInputMode();}}
上面代碼參考:http://blog.csdn.net/m_changgong/article/details/7608911,特此註明。