在Android上将音频路由到蓝牙耳机(非A2DP)

时间:2010-01-27 05:04:54

标签: android audio bluetooth

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

经过大量谷歌搜索后,我发现只有电话呼叫音频可以路由到非A2DP BT耳机。 (我想知道您是否找到了将各种音频路由到非A2DP BT耳机的现成解决方案)

所以我想,不知何故,我可以通过某种方式将音频引导到携带电话音频的流。这样我就会欺骗手机将我的mp3音频传输到我的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();
    }
}

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

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

但以上都没有奏效。如果我删除上述代码中的AudioManager呼叫,音频将从扬声器播放,如果我如上所示更换它们,则音频将停止来自扬声器,但它不会通过BT耳机传输。所以这可能是部分成功。

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

Android必须有理由不支持此功能。但是我不能放弃不可能以编程方式重新路由音频的感觉。有什么想法吗?

P.S。以上代码需要以下许可

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

5 个答案:

答案 0 :(得分:14)

这个帖子可能已经很久了但是对于那些可能尝试同样事情的人来说,AudioManager文档中的一些注释可能会有用。看起来缺少的元素是startBluetoothSco()命令,但是对此通道的使用存在限制。来自Android开发者网站here

  
    

public void startBluetoothSco()从:API Level 8启动蓝牙SCO     音频连接。

  
     

需要许可:   许可权。

     

此方法可以使用   想要发送和的应用程序   从蓝牙SCO接收音频   手机不在时耳机   呼叫。

     

作为SCO连接建立   应用可能需要几秒钟   不应该依赖于连接   方法返回时可用   而是注册接收   意图ACTION_SCO_AUDIO_STATE_CHANGED   并等待状态   SCO_AUDIO_STATE_CONNECTED。

     

由于无法保证连接   成功,应用程序必须等待   这个意图超时了。

     

完成SCO连接后   或者如果企业超时,那么   申请必须打电话   stopBluetoothSco()来清除   请求并关闭蓝牙   连接。

     

即使是SCO连接也是如此   成立,以下   限制适用于音频输出   流,以便它们可以路由到   SCO耳机: - 必须是流类型   STREAM_VOICE_CALL - 格式必须是   单声道 - 采样必须是16kHz或   8kHz

     

以下限制适用于   输入流: - 格式必须   mono - 采样必须为8kHz

     

请注意手机应用程序始终   优先考虑使用   用于电话的SCO连接。如果这   手机进入时调用方法   打电话会被忽略。同样,如果   在收到电话时收到或发送电话   应用程序正在使用SCO   连接,连接将是   丢失了申请而不是   通话时自动返回   结束。

     

另见stopBluetoothSco()   ACTION_SCO_AUDIO_STATE_CHANGED

请注意,我没有对此进行过测试,我只是传递了我在研究类似项目时发现的一条线索。我认为Jayesh接近解决方案,上面的限制可能是阻止它工作的原因。

答案 1 :(得分:6)

开启:

 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);

I took it from here

答案 2 :(得分:2)

应为媒体播放器配置ALSA路径路径,以便它可以打开不同的音频路径,然后将音频路由到BT耳机。

答案 3 :(得分:2)

很棒的工作它对我来说很好用,请在你的代码中做一点修改,它会完美地工作,即

mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); 

to 

mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

答案 4 :(得分:0)

看不到明确的已接受的工作申请,所以提出新答案。此应用程序将音乐和音频路由到非A2dp耳机。尝试我的应用程序,并在github中找到源代码以获取参考代码。 https://github.com/sauravpradhan/AnySound2BT