一直不擅于来写文章,有时候写的东西,阅读起来,一点都不流畅,但不管如何,任何事情总有一个从0到1的过程。先写,后改。慢慢增进吧。
几年前曾写一篇文章 ,是关于利用手机距离传感器来切换听筒或声筒播放声音的问题。点击打开链接 , 当时在2.x版本中可以解决问题。但技术总在变化。如今,安卓5.x,6.x系统层出不穷,尤其是进入5.x的系统后,在系统UI、权限等多方面都有了变化。谷歌对于安卓的掌控权也在慢慢集中,毕竟在如今的大陆,安卓碎片化着实太严重了一些。
有点扯远了。
今天述说下自己在安卓5.x版本及之后的版本中,关于利用声筒和听筒切换时会存在有时候听筒没有声音的问题。
虽然网上也有很多文章给出了相应的方法,有些可以,有些不可以。自己也在不断的摸索,及填坑。经过一些时日的测试和摸索,粗略的算是解决了问题。现在将自己的处理方法记录下来,以便自己他日查阅。
1、首先申请权限。5.X及之后很多权限需要动态申请
<uses-permission android:name="android.permission.BODY_SENSORS" /> //传感器权限
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> //录音权限
2、注册传感器及传感器监听
public class XXXActivity(替换成你的Activity或者Fragment) implements SensorEventListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//电源管理器,用于控制屏幕亮或暗的。获取系统服务POWER_SERVICE,返回一个PowerManager对象
localPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
//获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag
//第一个参数为电源锁级别,第二个是日志tag
localWakeLock = this.localPowerManager.newWakeLock(32, "MyPower");
//声音管理器
audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
//距离传感器
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
//这行代码的作用是,在耳麦听筒模式下,华为的手机会出现录音会失效的问题,所以,在每次进来时,先将声音播放模式切换到扩音模式下,
//当声音播放完后,也需要将声音切换回到扩音模式下。
changeAdapterType(true);
}
//注册传感器监听需要实现的两个方法
@Override
public void onSensorChanged(SensorEvent event) {
try {
float mProximiny = event.values[0];
boolean flag = false;
if (mProximiny >= sensor.getMaximumRange()) {
flag = true;
changeAdapterType(flag);
} else {
flag = false;
changeAdapterType(flag);
}
if (localWakeLock.isHeld()) return;
//电源锁用于控制屏亮屏黑,请及时释放,并捕获异常。
if (flag) {
localWakeLock.setReferenceCounted(false);
// 释放设备电源锁
localWakeLock.release();
} else {
// 申请设备电源锁
localWakeLock.acquire();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { }
//切换声筒或听筒
private void changeAdapterType(boolean on) {
setVolumeControlStream(AudioManager.STREAM_SYSTEM);
if (on) {
//扩音声筒
audioManager.setMicrophoneMute(false);
audioManager.setSpeakerphoneOn(true);
audioManager.setMode(AudioManager.MODE_NORMAL);
// LogUtil.debug(getClass(), "当前为扩音模式");
} else {
//耳麦听筒
audioManager.setSpeakerphoneOn(false);
audioManager.setMicrophoneMute(true);
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
//LogUtil.debug(getClass(),"当前为听筒模式");
//以下几行代码是仿QQ切换时,声音往后延迟1.5秒,以方便将声音连接起来,
//因为有些手机在切换时,会导致中间有约两秒左右的空白,按自己的需要来定。
//微信的模式和QQ不同,微信是在扩音切换到听筒时,会重新把语音播放一次。QQ的则是将时间往后退约两秒左右播放。//按自己的需要来定
//-------------------------------------
int cur = MediaManager.current();
if (cur < 1500) {
cur = 0;
} else {
cur = cur - 1500;
}
MediaManager.playSound(filePathStr, cur, new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mAdapter.stopPlay();
}
}, new MediaManager.OnErrorPlayListener() {
@Override
public void onError(String msg) {
mAdapter.stopPlay();
}
});
}
//---------------------------------------------
}
}
大致的代码就这些。写得比较杂乱且啰嗦,我自己也是在不断的摸索中才把问题解决。说实在的,简单的应用层问题好解决,涉及到硬件的问题,有时候挺折腾人的。
希望看到这篇文章的你,多一份耐心,多一些测试,不断的调试,问题终将解决的。祝你好运!
关于声音听筒或声筒模式切换的问题,我所知不多,恕我无法解决你后续的其它问题。