Android 音視訊 遇上鎖屏那些事

迷失no發表於2019-02-01

說明

最近做直播播放,核心用的是騰訊超級播放器。螢幕鎖屏與開啟時候遇到一些問題這裡進行陳述...為了提升播放體驗,我們總是 希望鎖屏暫停 開屏繼續播放的效果。

先上鎖屏類相關程式碼:

public class ScreenLockController {
    private Context mContext;
    private IntentFilter mScreenStatusFilter = null;
    private ScreenStatusListener mScreenStatusListener = null;

    public ScreenLockController(Context context) {
        mContext = context;
        mScreenStatusFilter = new IntentFilter();
        mScreenStatusFilter.addAction(Intent.ACTION_SCREEN_ON);
        mScreenStatusFilter.addAction(Intent.ACTION_SCREEN_OFF);
        mScreenStatusFilter.addAction(Intent.ACTION_USER_PRESENT);
    }

    private BroadcastReceiver mScreenStatusReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_SCREEN_ON.equals(action)) { // 開屏
                if (mScreenStatusListener != null) {
                    mScreenStatusListener.onScreenOn();
                }
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 鎖屏
                if (mScreenStatusListener != null) {
                    mScreenStatusListener.onScreenOff();
                }
            } else if (Intent.ACTION_USER_PRESENT.equals(action)) { //解鎖
                if (mScreenStatusListener != null) {
                    mScreenStatusListener.userPresent();
                }
            }
        }
    };

    //設定監聽
    public void setScreenStatusListener(ScreenStatusListener l) {
        mScreenStatusListener = l;
    }
    //開始監聽
    public void startListen() {
        if (mContext != null) {
            mContext.registerReceiver(mScreenStatusReceiver, mScreenStatusFilter);
        }
    }
    //結束監聽
    public void stopListener() {
        if (mContext != null) {
            mContext.unregisterReceiver(mScreenStatusReceiver);
        }
    }
    public interface ScreenStatusListener {
        void onScreenOn();
        void onScreenOff();
        void userPresent();
    }
}
複製程式碼

播放器中SuperPlayer中使用 :

 private ScreenLockController mScreenLockController;
//View init時候新增監聽 
    private void addScreenLockController(Context context) {
        mScreenLockController = new ScreenLockController(context);
        mScreenLockController.setScreenStatusListener(new ScreenLockController.ScreenStatusListener() {
            @Override
            public void onScreenOn() {
                Log.d(TAG, "onScreen on ");
//                onResume();
                this.userPresent();
            }

            @Override
            public void onScreenOff() {
                Log.d(TAG, "onScreen off ");
                onPause();
            }

            @Override
            public void userPresent() {
                //解鎖顯示view 之後
                //view 對於使用者可見性判斷
                if (isShown() && !screenOff()) {
                    onResume();
                }
            }
        });

        mScreenLockController.startListen();
    }
    //view 移除時候移除監聽
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mScreenLockController
                .stopListener();
    }
複製程式碼

void onScreenOn(); 開屏 void onScreenOff();鎖屏 void userPresent();解鎖

剛開始我直接userPresent 之後設定onResume播放,後來發現遇到幾種情況。

  1. 對於華為mate 9和小米8手機,發現鎖屏按鍵之後只是黑屏並不鎖屏,會遇到直播無法播放情況, 只會呼叫onScreenOn 函式。所以onScreenOn 和 userPresent 應該用同樣的播放邏輯。
  2. 大部分手機鎖屏按鍵解鎖顯示之後會呼叫 userPresent ,但是假如此刻處於類似微信分享介面而沒有分享,這時鎖屏開屏視訊會播放但是實際上視訊播放頁面對於使用者是不可見的。 所以加入了isShown 判斷使用者可見性。
  3. isShown 作為判斷之後,大部分手機功能都是正常的。 vivo全面屏 手機突然出現一種情況,解鎖螢幕亮之後userPresent 函式呼叫,視訊開始播放,但實際上手機上面鎖屏頁面並未移除,視訊對於使用者依然不可見,isShown 這裡返回true。 所以這裡我加入了 鎖屏頁面是否蓋在上面來解決這個問題,確保萬無一失,親測公司所有手機都體驗正常。

判斷螢幕是否時候解鎖。

    private boolean screenOff() {

        KeyguardManager mKeyguardManager = (KeyguardManager) getContext().getSystemService(KEYGUARD_SERVICE);

        if (mKeyguardManager.inKeyguardRestrictedInputMode()) {
            // keyguard on
            Log.d(TAG, "mKeyguardManager on  ");
            return true;
        }
        return false;
    }
複製程式碼

相關文章