Android 监听屏幕锁屏(听音频,看视频),音视频播放焦点及暂停,音频焦点

> 锁屏听音乐(音频),没有锁屏看视频
Android系统亮屏、锁屏、屏幕解锁事件(解决部分手机亮屏后未解锁即进入resume状态)- http://blog.csdn.net/oracleot/article/details/20378453
Android 实现锁屏的较完美方案- https://segmentfault.com/a/1190000003075989
https://github.com/android/platform_frameworks_policies_base/blob/master/phone/com/android/internal/policy/impl/KeyguardViewManager.java
Android QQ音乐/酷狗音乐锁屏控制实现原理,酷狗锁屏- https://blog.csdn.net/yangxi_pekin/article/details/50456763
Android 监听屏幕锁屏,用户解锁- http://blog.csdn.net/mengweiqi33/article/details/18094221
  最近在做视频播放器的时候,遇到一个问题,在用户播放视频然后锁屏之后,视频播放器仍然在继续播放,遇到类似手机系统状态改变的问题的时候,首先想到了广播(don't call me,i will call you);在网上搜罗了一个方法,做个总结;
public class ScreenListener {
    private Context mContext;
    private ScreenBroadcastReceiver mScreenReceiver;
    private ScreenStateListener mScreenStateListener;

    public ScreenListener(Context context) {
        mContext = context;
        mScreenReceiver = new ScreenBroadcastReceiver();
    }

    /**
     * screen状态广播接收者
     */
    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)) { // 解锁
                mScreenStateListener.onUserPresent();
            }
        }
    }

    /**
     * 开始监听screen状态
     * 
     * @param listener
     */
    public void begin(ScreenStateListener listener) {
        mScreenStateListener = listener;
        registerListener();
        getScreenState();
    }

    /**
     * 获取screen状态
     */
    private void getScreenState() {
        PowerManager manager = (PowerManager) mContext
                .getSystemService(Context.POWER_SERVICE);
        if (manager.isScreenOn()) {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOn();
            }
        } else {
            if (mScreenStateListener != null) {
                mScreenStateListener.onScreenOff();
            }
        }
    }

    /**
     * 停止screen状态监听
     */
    public void unregisterListener() {
        mContext.unregisterReceiver(mScreenReceiver);
    }

    /**
     * 启动screen状态广播接收器
     */
    private void registerListener() {
        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 interface ScreenStateListener {// 返回给调用者屏幕状态信息
        public void onScreenOn();
        public void onScreenOff();
        public void onUserPresent();
    }
}
在上面的代码中,用到了动态注册广播,在需要监听屏幕状态的activity中,当不需要监听的时候,如activity finish的时候,使用unregisterListener解除广播监听; 
下面是在Activity中调用;
ScreenListener l = new ScreenListener(this);
        l.begin(new ScreenStateListener() {
            @Override
            public void onUserPresent() {
                Log.e("onUserPresent", "onUserPresent");
            }

            @Override
            public void onScreenOn() {
                Log.e("onScreenOn", "onScreenOn");
            }

            @Override
            public void onScreenOff() {
                Log.e("onScreenOff", "onScreenOff");
            }
        });
通过以上步骤即实现了对屏幕状态的监听.

> 音视频播放焦点及暂停
MediaPlayer声音自动停止、恢复,一键静音等功能。
--  音频焦点
Android音频焦点详解(上)- http://blog.csdn.net/wangjihuanghun/article/details/54957459
Android音频焦点详解(下)源码详解-  http://blog.csdn.net/wangjihuanghun/article/details/56069283
Android AudioManager处理两个播放器同时有声音- http://blog.csdn.net/shuaicike/article/details/39930823
博客Demo- https://github.com/landptf/BlogDemo

// 获取AudioManager实例
final AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
AudioManager.OnAudioFocusChangeListener l = new AudioManager.OnAudioFocusChangeListener() {
    @Override
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {// 焦点获取到了,那继续播放,并恢复音量。
            AudioTrack audioTrack = mAudioTrack;
            if (audioTrack != null) {
                audioTrack.setStereoVolume(1.0f, 1.0f);
                if (audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PAUSED) {
                    audioTrack.flush();
                    audioTrack.play();
                }
            }
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {// 焦点丢失了,暂停播放。
             AudioTrack audioTrack = mAudioTrack;
            if (audioTrack != null) {
                if (audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
                    audioTrack.pause();
                }
            }
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { // 焦点丢失了,但是允许在降低音量的前提下继续播放,那么降低声音。
            AudioTrack audioTrack = mAudioTrack;
            if (audioTrack != null) {
                audioTrack.setStereoVolume(0.5f, 0.5f);
            }
        }
    }
};

// 因为这里要获得的焦点无法预知时长,因此用AUDIOFOCUS_GAIN模式。
int requestCode = am.requestAudioFocus(l, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (requestCode == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
   // 成功获取到了焦点。那启动播放
   AudioTrack audioTrack = mAudioTrack;
    if (audioTrack != null) {
        audioTrack.setStereoVolume(1.0f, 1.0f);
        if (audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PAUSED) {
            audioTrack.flush();
            audioTrack.play();
        }
    }
}else{  // 没有获取到音频焦点。那不播放声音
    AudioTrack audioTrack = mAudioTrack;
    if (audioTrack != null) {
        if (audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
            audioTrack.pause();
        }
    }
}

> 音频焦点
Android 音频焦点(Audio Focus)- https://blog.csdn.net/suyimin2010/article/details/79479323
Android音频焦点处理- https://blog.csdn.net/zwlove5280/article/details/84881019
  从Android 8.0开始(API 26),请求音频焦点的方式以及系统对音频焦点变化的管理有些微妙的变化。首先,对音频焦点变化的管理的变化体现在两个方面,延迟获取焦点和自动降低音量。
-- 实例1
public class AudioFocusManager implements AudioManager.OnAudioFocusChangeListener {
    private AudioManager mAudioManager;
    private AudioFocusRequest mFocusRequest;
    private AudioAttributes mAudioAttributes;

    private onRequestFocusResultListener mOnRequestFocusResultListener;
    private OnAudioFocusChangeListener mAudioFocusChangeListener;

    public AudioFocusManager(Context context) {
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    /**
     * Request audio focus.
     */
    public void requestFocus() {
        int result;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (mFocusRequest == null) {
                if (mAudioAttributes == null) {
                    mAudioAttributes = new AudioAttributes.Builder()
                            .setUsage(AudioAttributes.USAGE_MEDIA)
                            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                            .build();
                }
                mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
                        .setAudioAttributes(mAudioAttributes)
                        .setWillPauseWhenDucked(true)
                        .setOnAudioFocusChangeListener(this)
                        .build();
            }
            result = mAudioManager.requestAudioFocus(mFocusRequest);
        } else {
            result = mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        }
        if (mOnRequestFocusResultListener != null) {
            mOnRequestFocusResultListener.onHandleResult(result);
        }
    }


    @Override
    public void onAudioFocusChange(int focusChange) {
        if (mAudioFocusChangeListener != null) {
            mAudioFocusChangeListener.onAudioFocusChange(focusChange);
        }
    }

    /**
     * Release audio focus.
     */
    public void releaseAudioFocus() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mAudioManager.abandonAudioFocusRequest(mFocusRequest);
        } else {
            mAudioManager.abandonAudioFocus(this);
        }
    }

    /**
     * Handle the result of audio focus.
     */
    public interface onRequestFocusResultListener {
        void onHandleResult(int result);
    }


    public void setOnHandleResultListener(onRequestFocusResultListener listener) {
        mOnRequestFocusResultListener = listener;
    }


    /**
     * Same as AudioManager.OnAudioFocusChangeListener.
     */
    public interface OnAudioFocusChangeListener {
        void onAudioFocusChange(int focusChange);
    }


    public void setOnAudioFocusChangeListener(OnAudioFocusChangeListener listener) {
        mAudioFocusChangeListener = listener;
    }

}

-- 实例2
public class AudioFocusUtils {
    private static AudioFocusUtils mInstance;
    private AudioManager mAudioManager;
    private AudioFocusRequest mFocusRequest;
    private AudioAttributes mAudioAttributes;

    private AudioFocusUtils() {}

    public static AudioFocusUtils getInstance() {
        if (mInstance == null) {
            synchronized (AudioFocusUtils.class) {
                mInstance = new AudioFocusUtils();
            }
        }
        return mInstance;
    }

    /**
     * 获取音频焦点
     */
    public void requestAudioFocus(Context context) {
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (mAudioManager != null) {
//            mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
            int result;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                if (mFocusRequest == null) {
                    if (mAudioAttributes == null) {
                        mAudioAttributes = new AudioAttributes.Builder()
                                .setUsage(AudioAttributes.USAGE_MEDIA)
                                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                                .build();
                    }
                    mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
                            .setAudioAttributes(mAudioAttributes)
                            .setWillPauseWhenDucked(true)
                            .setOnAudioFocusChangeListener(mAudioFocusListener)
                            .build();
                }
                result = mAudioManager.requestAudioFocus(mFocusRequest);
            } else {
                result = mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
            }
        }
    }

    private int mLossTransientCount;
    /**
     * 音频焦点监听
     */
    public AudioManager.OnAudioFocusChangeListener mAudioFocusListener = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            switch(focusChange){
                case AudioManager.AUDIOFOCUS_LOSS:
                    Log.d("desaco", "AUDIOFOCUS_LOSS");
                    // 对应AUDIOFOCUS_GAIN
                    // 表示音频焦点请求者需要长期占有焦点,这里一般需要stop播放和释放
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    Log.d("desaco", "AUDIOFOCUS_LOSS_TRANSIENT");
                    // 对应AUDIOFOCUS_GAIN_TRANSIENT
                    // 表示音频焦点请求者需要短暂占有焦点,这里一般需要pause播放
                    mLossTransientCount ++;
//                    if (mLossTransientCount == 2) {
//                        Log.d("desaco", "mLossTransientCount == 2");
//                        VoiceMainController.getInstance().dismissVr();
//                    }
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    Log.d("desaco", "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
                    // 对应AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
                    // 表示音频焦点请求者需要占有焦点,但是我也可以继续播放,只是需要降低音量或音量置为0
                    break;
                case AudioManager.AUDIOFOCUS_GAIN:
                    Log.d("desaco", "AUDIOFOCUS_GAIN");
                    // 获得焦点,这里可以进行恢复播放
                    mLossTransientCount = 0;
                    break;
            }
        }
    };

    /**
     * 释放音频焦点及资源
     * @param context
     */
    public void abandonAudioFocus(Context context) {
        if (mAudioManager != null) {
            mAudioManager.abandonAudioFocus(mAudioFocusListener);
        }
    }
}

> 音频焦点

/**
 * 音频焦点处理
 */
public class AudioFocusUtils {

    private static AudioFocusUtils mInstance;

    private AudioFocusUtils() {}

    public static AudioFocusUtils getInstance() {
        if (mInstance == null) {
            synchronized (AudioFocusUtils.class) {
                mInstance = new AudioFocusUtils();
            }
        }
        return mInstance;
    }

    /**
     * 获取音频焦点
     */
    public void requestAudioFocus(Context context) {
        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (am != null) {
            am.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        }
    }

    /**
     * 音频焦点监听
     */
    public AudioManager.OnAudioFocusChangeListener mAudioFocusListener = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            switch(focusChange){
                case AudioManager.AUDIOFOCUS_LOSS:
                    Log.d("desaco", "AUDIOFOCUS_LOSS");
                    // 对应AUDIOFOCUS_GAIN
                    // 表示音频焦点请求者需要长期占有焦点,这里一般需要stop播放和释放
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    Log.d("desaco", "AUDIOFOCUS_LOSS_TRANSIENT");
                    // 对应AUDIOFOCUS_GAIN_TRANSIENT
                    // 表示音频焦点请求者需要短暂占有焦点,这里一般需要pause播放
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    Log.d("desaco", "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
                    // 对应AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
                    // 表示音频焦点请求者需要占有焦点,但是我也可以继续播放,只是需要降低音量或音量置为0
                    break;
                case AudioManager.AUDIOFOCUS_GAIN:
                    Log.d("desaco", "AUDIOFOCUS_GAIN");
                    // 获得焦点,这里可以进行恢复播放
                    break;
            }
        }
    };

    /**
     * 释放音频焦点及资源
     * @param context
     */
    public void abandonAudioFocus(Context context) {
        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (am != null) {
            am.abandonAudioFocus(mAudioFocusListener);
        }
    }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值