解决 android audiorecord 蓝牙耳机 重启导致录音数据异常问题
2017-07-05 14:16
821 查看
解决 android audiorecord 蓝牙耳机 重启导致录音数据异常问题
蓝牙 两种同步链路(SCO)和异步链路(ACL)。A2DP(AdvancedAudio Distribution Profile 高级音频传输模型)是跑在ACL链路上去高品质音频协议。A2DP定义了ACL(Asynchronous
Connectionless 异步无连接)信道上传送单声道或立体声等高质量音A2DP 功能频信息的协议和过程。
蓝牙物理链路SCO(Synchronous Connection Oriented)主要用来传输对时间要求很高的数据通信,
另外的一种链路是ACL(Asynchronous Connectionless)。
SCO连接为对称连接,利用保留时隙传送数据包。连接建立后,主设备和从设备可以不被选中就发送SCO数据包。SCO数据包既可以传送话音,也可以传送数据,但在传送数据时,只用于重发被损坏的那部分的数据。
ACL链路就是定向发送数据包,它既支持对称连接,也支持不对称连接(既可以一对一,也可以一对多)。主设备负责控制链路带宽,并决定微微网中的每个从设备可以占用多少带宽和连接的对称性。从设备只有被选中时才能传送数据。ACL链路也支持接收主设备发给微微网中所有从设备的广播消息。
我们要选用的SCO模式,A2DP模式是默认链接的只进不出,蓝牙只能听到手机播放音乐不能录制声音
1.获取 AudioMannager
mAudioManager = ((AudioManager) getSystemService(Context.AUDIO_SERVICE));
2. 设置音频模式为交流模式
mAudioManager.setMode(mAudioManager.MODE_IN_COMMUNICATION);
3. 注册 蓝牙监控事件
mAudioManager.registerMediaButtonEventReceiver(new ComponentName( this, MusicIntentReceiver.class));
@SuppressLint("InlinedApi") public class MusicIntentReceiver extends BroadcastReceiver { private static final String LOG_TAG = "jni"; private Context mContext; private KeyService mKeyService; @Override public void onReceive(Context context, Intent intent) { mContext = context; mKeyService = new KeyService(mContext); if (intent.getAction().equals( android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { Toast.makeText(context, "Headphones disconnected.", Toast.LENGTH_SHORT).show(); Log.i(LOG_TAG, "Headphones disconnected.!"); // send an intent to our MusicService to telling it to pause the // audio // context.startService(new Intent(MusicService.ACTION_PAUSE)); } else if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) { Log.i(LOG_TAG, "ACTION_MEDIA_BUTTON!"); KeyEvent keyEvent = (KeyEvent) intent.getExtras().get( Intent.EXTRA_KEY_EVENT); if (keyEvent.getAction() != KeyEvent.ACTION_DOWN) return; switch (keyEvent.getKeyCode()) { case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: // context.startService(new // Intent(MusicService.ACTION_TOGGLE_PLAYBACK)); break; case KeyEvent.KEYCODE_MEDIA_PLAY: // context.startService(new Intent(MusicService.ACTION_PLAY)); break; case KeyEvent.KEYCODE_MEDIA_PAUSE: // context.startService(new Intent(MusicService.ACTION_PAUSE)); break; case KeyEvent.KEYCODE_MEDIA_STOP: // context.startService(new Intent(MusicService.ACTION_STOP)); break; case KeyEvent.KEYCODE_MEDIA_NEXT: // context.startService(new Intent(MusicService.ACTION_SKIP)); break; case KeyEvent.KEYCODE_MEDIA_PREVIOUS: // TODO: ensure that doing this in rapid succession actually // plays the // previous song // context.startService(new Intent(MusicService.ACTION_REWIND)); break; } } else if (intent.getAction().equals( BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { int state = intent.getIntExtra( BluetoothAdapter.EXTRA_CONNECTION_STATE, 0); if (state == BluetoothAdapter.STATE_CONNECTED ) { Log.i(LOG_TAG, "BluetoothAdapter.ACTION_CONNECTION_STATE_CONNECT"); } else if (state == BluetoothAdapter.STATE_DISCONNECTED){ Log.i(LOG_TAG, "BluetoothAdapter.ACTION_CONNECTION_STATE_DISCONNECTED"); } } else if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { Log.i(LOG_TAG, "Intent.ACTION_BOOT_COMPLETED"); } else if (intent.getAction().equals("android.intent.action.UPDATE_SUSPEND_TIME_BY_HAND")) { Log.i(LOG_TAG, "Intent.UPDATE_SUSPEND_TIME_BY_HAND"); } else { // Log.i(LOG_TAG, "other intent"); } }
4. 开启线程监控 控制录音
if (mKeyService.isBtConect()) { if (!is_record) { try { Thread.sleep(15000); } catch (InterruptedException e) { e.printStackTrace(); } mAudioManager.setMode(mAudioManager.MODE_IN_COMMUNICATION); mAudioManager.startBluetoothSco(); mAudioManager.setSpeakerphoneOn(false); mAudioManager.setBluetoothScoOn(true); Log.i(LOG_TAG, "bluetooth is connect at start activity = " + mAudioManager.isBluetoothScoOn() + mAudioManager.getMode()); record = new RecordPlayActivity(); record.playStart(); is_record = true; } } else { if (is_record == true) { // mAudioManager.stopBluetoothSco(); mAudioManager.setMode(mAudioManager.MODE_NORMAL); // mAudioManager.setBluetoothScoOn(false); // mAudioManager.stopBluetoothSco(); record.stopRecord(); record = null; is_record = false; } }注意红色字体,这个是解决蓝牙重新连接开始录音的关键,因为蓝牙重连接虽然广播收到了通知,但是蓝牙耳机自己还没准备好,所以当接收到蓝牙耳机连接好的通知,在延迟一定的时间,既可以完美解决了这个问题了。
相关文章推荐
- android -- 小功能 解决自动旋转导致activity重启问题
- Android:Consumer closed input channel or an error occurred. events=0x8异常导致程序异常终止问题解决方案
- Android 系统截屏与系统内置DVR录像冲突,导致SystemUI重启的问题解决与分享
- android设备连接蓝牙外设导致activity重启(recreate)的问题
- 解决android中service被kill后重启异常终止的问题
- Android 签名打包后的APP在后台运行时按icon导致程序重启的奇葩问题解决
- android中共享全局数据的方法(static导致的内存泄漏问题,但其实并未解决)
- [异常解决] 安卓6.0权限问题导致老蓝牙程序出现异常解决办法:Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission...
- Android应用第一次安装成功点击“打开”后Home键切出应用后再点击桌面图标返回导致应用重启问题的解决方法
- Androidの解决自动旋转导致activity重启问题
- Android中两个APP间跳转导致的异常问题及解决办法
- 安卓6.0权限问题导致老蓝牙程序出现异常解决办法:Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission...
- 解决android开发中无法trycatch到由唯一性约束导致的数据库insert不进数据erro的问题
- Androidの解决自动旋转导致activity重启问题
- 在编程时异常关闭电脑,重启android sdk avd不可启动问题解决
- 如何解决放到android /system/app 下的应用程序无限重启弹出“异常终止”的问题
- HttpWebResponse returns 404 error(解决异常后读取后续数据的问题)
- 提交代码到svn时服务器重启导致svn无法更新问题解决办法
- eclipse在异常关闭后,导致无法启动workspace问题的解决
- 因外键约束导致数据不能清空的问题解决