> 锁屏听音乐(音频),没有锁屏看视频
Android系统亮屏、锁屏、屏幕解锁事件(解决部分手机亮屏后未解锁即进入resume状态)-
Android 实现锁屏的较完美方案-
https:///android/platform_frameworks_policies_base/blob/master/phone/com/android/internal/policy/impl/KeyguardViewManager.java Android QQ音乐/酷狗音乐锁屏控制实现原理,酷狗锁屏-
Android 监听屏幕锁屏,用户解锁-
  最近在做视频播放器的时候,遇到一个问题,在用户播放视频然后锁屏之后,视频播放器仍然在继续播放,遇到类似手机系统状态改变的问题的时候,首先想到了广播(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音频焦点详解(上)-
Android音频焦点详解(下)源码详解-  
Android AudioManager处理两个播放器同时有声音-
博客Demo- https:///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)-
Android音频焦点处理-
  从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);
        }
    }
}