将audio路由到Android上的蓝牙耳机(非A2DP)

我有一个非A2DP单耳耳机BT耳机(Plantronics 510),并希望与我的Android HTC Magic一起使用,以收听低质量的audio,如播客/有声读物。

经过大量的search,我发现只有电话audio可以路由到非A2DP蓝牙耳机。 (我想知道如果你已经find了一个现成的解决scheme,将各种audio路由到非A2DP BT耳机)

所以我想通过编程方式,我可以将audio传输到携带电话audio的stream。 这样我就会骗过手机将我的mp3audio传送到我的BT耳机。 我写了以下简单的代码。

import android.content.*; import android.app.Activity; import android.os.Bundle; import android.media.*; import java.io.*; import android.util.Log; public class BTAudioActivity extends Activity { private static final String TAG = "BTAudioActivity"; private MediaPlayer mPlayer = null; private AudioManager amanager = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); amanager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); amanager.setBluetoothScoOn(true); amanager.setMode(AudioManager.MODE_IN_CALL); mPlayer = new MediaPlayer(); try { mPlayer.setDataSource(new FileInputStream( "/sdcard/sample.mp3").getFD()); mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); mPlayer.prepare(); mPlayer.start(); } catch(Exception e) { Log.e(TAG, e.toString()); } } @Override public void onDestroy() { mPlayer.stop(); amanager.setMode(AudioManager.MODE_NORMAL); amanager.setBluetoothScoOn(false); super.onDestroy(); } } 

正如你所看到的,我尝试了各种方法的组合,我认为会骗过手机相信我的audio是一个电话:

  • 使用MediaPlayer的setAudioStreamType(STREAM_VOICE_CALL)
  • 使用AudioManager的setBluetoothScoOn(true)
  • 使用AudioManager的setMode(MODE_IN_CALL)

但以上都没有奏效。 如果我在上面的代码中删除了AudioManager调用,则audio将从扬声器播放,如果我按照上图所示更换audio,则audio会停止来自扬声器,但不会通过BT耳机传送。 所以这可能是一个部分的成功。

我已经检查过,BT耳机可以通过电话正常工作。

Android不支持这个必须有一个原因。 但我不能放弃以编程方式重新路由audio的感觉。 有任何想法吗?

以上PS代码需要以下权限

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

这个线程可能已经很长时间了,但是对于那些可能会尝试相同的东西的人来说,AudioManager文档中的一些注释可能是有用的。 它看起来像缺less的元素是startBluetoothSco()命令,但对这个通道的使用有限制。 从Android Dev网站:

public void startBluetoothSco()从以下版本开始:API Level 8启动蓝牙SCOaudio连接。

需要权限:MODIFY_AUDIO_SETTINGS。

这种方法可以被希望在蓝牙SCO耳机上发送和接收audio的应用程序使用,而电话不在通话中。

由于SCO连接build立可能需要几秒钟的时间,应用程序不应该依赖连接在方法返回时可用,而是注册接收意图ACTION_SCO_AUDIO_STATE_CHANGED并等待状态为SCO_AUDIO_STATE_CONNECTED。

由于连接不能保证成功,应用程序必须等待此意图超时。

当完成SCO连接或build立超时时,应用程序必须调用stopBluetoothSco()来清除请求并closures蓝牙连接。

即使build立了SCO连接,以下限制也适用于audio输出stream,以便将它们路由到SCO耳机: – streamtypes必须为STREAM_VOICE_CALL – 格式必须为单声道 – 采样必须为16kHz或8kHz

以下限制适用于inputstream: – 格式必须为单声道 – 采样必须为8kHz

请注意,电话应用程序始终优先使用电话的SCO连接。 如果在手机通话过程中调用这个方法,它将被忽略。 同样,如果在应用程序正在使用SCO连接时收到或发送了一个呼叫,则该连接将在应用程序中丢失,并且在呼叫结束时不会自动返回。

另请参阅stopBluetoothSco()ACTION_SCO_AUDIO_STATE_CHANGED

请注意,我没有testing过这个,我只是在研究一个类似的项目时find了一个领导。 我认为Jayesh已经接近了解决scheme,上面的限制可能是阻止它的工作。

打开:

  localAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); localAudioManager.setMode(0); localAudioManager.setBluetoothScoOn(true); localAudioManager.startBluetoothSco(); localAudioManager.setMode(AudioManager.MODE_IN_CALL); 

把关掉:

  localAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); localAudioManager.setBluetoothScoOn(false); localAudioManager.stopBluetoothSco(); localAudioManager.setMode(AudioManager.MODE_NORMAL); 

我从这里拿走了

伟大的工作它对我来说工作得很好,请在代码中进行修改,即可完美工作

 mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); to mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 

应该为媒体播放器configurationALSApathpath,以便它可以打开不同的audiopath,然后将audio路由到BT耳机。

无法看到一个清晰的接受工作的应用程序,所以把一个新的答案 此应用程序将音乐和audio路由到非A2dp耳机。 试试我的应用程序,并在github中查找源代码以获取参考代码。 https://github.com/sauravpradhan/AnySound2BT