什么场景适合?
如果你的app有长时间(大于一两秒)使用到音频,比如音乐视频的播放,录音,或者网络软件通话。这些场景在音频被占用时,你是需要做适当处理 或暂停,或退出,或降低音量;在音频被其他软件释放时,再及时恢复app状态。
本文章的bug:部分手机可以监听音频被占用的情况,但是监听不到释放的情况,导致恢复app状态的动作不能执行(在这样的手机上发现其他app也无法恢复状态—>疑是系统释放了)。
下面的案例没有正儿八经使用音频,具体使用只需要实现最底下的四个方法即可。
其实对音频的控制只做app占用的情况还不够全面,应该加上对电话状态的监听才全面,请看最下面一段代码
注意点:
1.有版本的区别
2.type最好使用music,这是恢复播放比较好的一种类型了
public class SoftCallListenerActivity extends AppCompatActivity implements AudioManager.OnAudioFocusChangeListener {
public static final String TAG = "SoftCallListenerActivity";
AppCompatTextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_solf_call_listener);
textView = findViewById(R.id.atv);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
audioListener();
} else {
audioListenerD26();
}
}
AudioManager audioManager;
AudioAttributes playbackAttributes;
AudioFocusRequest focusRequest;
final Object focusLock = new Object();
private void audioListenerD26() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
playbackNow();
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void audioListener() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
playbackAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(playbackAttributes)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(this, handler)
.build();
request();
}
@Override
protected void onResume() {
super.onResume();
Logs.w(TAG, "onResume: request" );
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
request();
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void request(){
int res = audioManager.requestAudioFocus(focusRequest);
synchronized (focusLock) {
if (res == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
playbackNowAuthorized = false;
} else if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
playbackNowAuthorized = true;
playbackNow();
} else if (res == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
playbackDelayed = true;
playbackNowAuthorized = false;
}
}
}
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
Logs.w(TAG, "handleMessage:" + msg.what);
}
};
boolean playbackDelayed = false;
boolean playbackNowAuthorized = false;
boolean resumeOnFocusGain = false;
@Override
public void onAudioFocusChange(int focusChange) {
Logs.w(TAG, "onAudioFocusChange:" + focusChange);
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (playbackDelayed || resumeOnFocusGain) {
synchronized (focusLock) {
playbackDelayed = false;
resumeOnFocusGain = false;
}
playbackNow();
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
synchronized (focusLock) {
resumeOnFocusGain = false;
playbackDelayed = false;
}
pausePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
synchronized (focusLock) {
resumeOnFocusGain = true;
playbackDelayed = false;
}
pausePlayback();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
playDependsYourDear();
break;
}
}
private void playDependsYourDear() {
Logs.w(TAG, "playDependsYourDear");
}
private void playbackNow() {
Logs.w(TAG, "playbackNow");
}
private void pausePlayback() {
Logs.w(TAG, "pausePlayback");
}
/**
*当app的音频使用完毕,应该主动释放,这样其他app才能及时响应
*/
private void playComplete() {
Logs.w(TAG, "playComplete");
audioManager.abandonAudioFocus(this);
}
}
private void telephony() {
if (mTelephonyManager == null)
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mPanelBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
try {
JSONObject jsonObject = new JSONObject();
int state = mTelephonyManager.getCallState();
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:// 电话挂断
Logs.w(TAG, "电话挂断...");
break;
case TelephonyManager.CALL_STATE_OFFHOOK: //电话通话的状态
Logs.w(TAG, "正在通话...");
break;
case TelephonyManager.CALL_STATE_RINGING: //电话响铃的状态
Logs.w(TAG, "电话响铃...");
break;
}
sendMessage(jsonObject.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
};
IntentFilter panelFilter = new IntentFilter();
panelFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
panelFilter.setPriority(Integer.MAX_VALUE);
mContext.registerReceiver(mPanelBroadcastReceiver, panelFilter, null, null);
}