利用手机距离感应器来切换声音听筒播放或声筒播放

一直不擅于来写文章,有时候写的东西,阅读起来,一点都不流畅,但不管如何,任何事情总有一个从0到1的过程。先写,后改。慢慢增进吧。

几年前曾写一篇文章 ,是关于利用手机距离传感器来切换听筒或声筒播放声音的问题。点击打开链接 , 当时在2.x版本中可以解决问题。但技术总在变化。如今,安卓5.x,6.x系统层出不穷,尤其是进入5.x的系统后,在系统UI、权限等多方面都有了变化。谷歌对于安卓的掌控权也在慢慢集中,毕竟在如今的大陆,安卓碎片化着实太严重了一些。

有点扯远了。

今天述说下自己在安卓5.x版本及之后的版本中,关于利用声筒和听筒切换时会存在有时候听筒没有声音的问题。

虽然网上也有很多文章给出了相应的方法,有些可以,有些不可以。自己也在不断的摸索,及填坑。经过一些时日的测试和摸索,粗略的算是解决了问题。现在将自己的处理方法记录下来,以便自己他日查阅。

1、首先申请权限。5.X及之后很多权限需要动态申请

   //传感器权限
  //录音权限 

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(); 
				} 
			}); 
		}
      //--------------------------------------------- 
   }
 }


大致的代码就这些。写得比较杂乱且啰嗦,我自己也是在不断的摸索中才把问题解决。说实在的,简单的应用层问题好解决,涉及到硬件的问题,有时候挺折腾人的。

希望看到这篇文章的你,多一份耐心,多一些测试,不断的调试,问题终将解决的。祝你好运!

关于声音听筒或声筒模式切换的问题,我所知不多,恕我无法解决你后续的其它问题。


你可能感兴趣的:(android)