2014-07-16 139 views
0

我正嘗試從與Android設備配對的藍牙耳機捕獲音頻。通過與Android設備配對的藍牙耳機捕獲音頻

以下是相關代碼:

Intent in=null; 
final int bufferSize=BufferElements2Rec*BytesPerElement; 

final BroadcastReceiver brr=new BroadcastReceiver() 
{ 
    @Override 
    public void onReceive(Context context,Intent intent) 
    { 
     int state=intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,-1); 
     Log.d(labelApp,"Audio SCO State = "+state); 
     if(AudioManager.SCO_AUDIO_STATE_CONNECTED==state) 
     { 
      Log.d(labelApp,"Entered and Starting Recording"); 
      //recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 
      //  RECORDER_SAMPLERATE, RECORDER_CHANNELS, 
      //  RECORDER_AUDIO_ENCODING, bufferSize); 
      recorder = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC, 
       RECORDER_SAMPLERATE, RECORDER_CHANNELS, 
       RECORDER_AUDIO_ENCODING, bufferSize); 
      if(recorder==null) 
      { 
       Log.d(labelApp,"null"); 
      } 
      else 
      { 
       Log.d(labelApp,"not null"); 
      } 
      recorder.startRecording(); 
      recordingThread=new Thread(new Runnable() 
      { 
       @Override 
       public void run() { 
        // TODO Auto-generated method stub 
        writeAudioDataToFile(); 
       } 

      },"AudioRecorder Thread"); 
      recordingThread.start(); 

      Log.d(labelApp,"Launched Recording Thread"); 
     } 
    } 
}; 

try 
{ 
    Log.d(labelApp,"Initializing BT"); 
    am = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
    //am.setMode(AudioManager.MODE_IN_CALL); 

    //in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); 
    //in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); 
    Log.d(labelApp,"Starting Bluetooth"); 
    am.setStreamSolo(AudioManager.MODE_IN_CALL, true); 
    am.setBluetoothScoOn(true); 
    am.setMode(AudioManager.MODE_IN_CALL); 
    am.startBluetoothSco(); 
    Log.d(labelApp,"Can BT record from mic? "+am.isBluetoothScoAvailableOffCall()); 
    //in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); 
    in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)); 
    // The following line makes the audio go to hell 
    //am.setMode(AudioManager.MODE_IN_CALL); 


    //am.setStreamSolo(AudioManager.MODE_IN_CALL, true); 
    Log.d(labelApp,"Everything initializated"); 
    Log.d(labelApp,"Recorder is..."); 
} 
catch(Exception e) 
{ 
    Log.e(labelApp,"exception",e); 
    writeStack(e); 
} 

try 
{ 
     Log.d(labelApp,"Initializing BT"); 
     am = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
     //am.setMode(AudioManager.MODE_IN_CALL); 

     //in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); 
     //in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); 
     Log.d(labelApp,"Starting Bluetooth"); 
     am.setStreamSolo(AudioManager.MODE_IN_CALL, true); 
     am.setBluetoothScoOn(true); 
     am.setMode(AudioManager.MODE_IN_CALL); 
     am.startBluetoothSco(); 
     Log.d(labelApp,"Can BT record from mic? "+am.isBluetoothScoAvailableOffCall()); 
     //in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); 
     in=registerReceiver(brr,new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)); 
     // The following line makes the audio go to hell 
     //am.setMode(AudioManager.MODE_IN_CALL); 


     //am.setStreamSolo(AudioManager.MODE_IN_CALL, true); 
     Log.d(labelApp,"Everything initializated"); 
     Log.d(labelApp,"Recorder is..."); 
} 
catch(Exception e) 
{ 
     Log.e(labelApp,"exception",e); 
     writeStack(e); 
} 

艙單問權限:

  • WRITE_EXTERNAL_STORAGE
  • RECORD_AUDIO
  • INTERNET
  • 許可權
  • BROADCAST_S TICKY
  • 藍牙
  • BLUETOOTH_ADMIN

每個應用程序的典型過濾logcat的輸出是:

  1. 初始化BT
  2. 啓動藍牙
  3. 可以從話筒BT記錄?真正
  4. 一切初始化
  5. Recorder是...
  6. 音頻SCO狀態= 2
  7. 音頻SCO狀態= 1
  8. 進入並開始記錄
  9. 沒有空
  10. 推出記錄線程

當am.startBluetoothSco();被調用,我可以聽到BT設備上的短暫噪音,但是該應用只是從Android設備的麥克風取代BT的音頻。

任何暗示我錯過/做錯了什麼?

預先感謝關注

+0

嗨,我在這麼長時間後也遇到過這個問題,你能告訴我如何解決它嗎?謝謝。 – mmm2006

回答

0

最重要的是,你需要設置
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

清單文件。沒有它,將不會有錯誤信息,但B/T狀態將拒絕更改爲已連接。

其他相關的權限包括:

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

編輯:除了評論,這裏是我以前使用的一些示例代碼:

am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 

brr(new BroadcastReceiver() { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); 
     Log.d(TAG, "Audio SCO state: " + state); 

     if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) { 
      /* 
      * Now the connection has been established to the bluetooth device. 
      * Record audio or whatever (on another thread).With AudioRecord you can record with an object created like this: 
      * new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, 
      * AudioFormat.ENCODING_PCM_16BIT, audioBufferSize); 
      * 
      * After finishing, don't forget to unregister this receiver and 
      * to stop the bluetooth connection with am.stopBluetoothSco(); 
      */ 
      unregisterReceiver(this); 
     } 

    } 
}, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); 

Log.d(TAG, "starting bluetooth"); 
am.startBluetoothSco(); 

學分這個碼進入用戶Stephan

+0

這些權限已設置,它們在我的文章的結尾(與BLUETOOTH,BLUETOOTH_ADMIN,INTERNET,WRITE_EXTERNAL_STORAGE一起)中報告。搜索我原來的帖子「The Manifest要求權限:」,謝謝你的有趣,雖然 – user3845389

+1

@ user3845389哦,對不起,我錯過了。閱讀下面關於你的日誌包含的內容。我也有一些B/T錄音的示例代碼,我會將其作爲編輯發佈。 – Wolfish

+0

感謝您的摘錄,它看起來非常類似於我的文章。不幸的是,一切看起來都很好(Intent被調用並且連接已打開,否則我們不會看到引用AudioRecord錄音機的「not null」消息),但該應用只會從設備自己的麥克風中捕獲音頻而不是來自BT配對的設備......不知道爲什麼!用我使用AudioRecord錄音機的方式看起來有很多問題? – user3845389

0

從藍牙耳機錄音的代碼

public class Recording { 

static int count = 0; 
static String Shared; 
static String bFlag; 
public static int TIMEOUT = 5000; 
public static int COUNTDOWN_INTERVAL = 1000; 
static Context context; 

public static void checkAndRecord(Context context, 
     OnBluetoothRecording BluetoothRecording, boolean resume) { 

    // Check bluetooth flag And Bluetooth is ON or OFF 
    if (getBluetoothFlag(context) && isBluetoothON()) { 

     // Check for bluetooth and Record 
     startBluetoothRecording(BluetoothRecording, resume, context); 

    } else { 

     // If Bluetooth is OFF Show Toast else Dont Show 
     if (getBluetoothFlag(context) && !isBluetoothON()) { 
      // false because recording not started 
      Toast.makeText(context, 
        "Bluetooth is OFF. Recording from Phone MIC.", 
        Toast.LENGTH_SHORT).show(); 
      BluetoothRecording.onStartRecording(resume, false); 
     } else { 
      // false because recording not started 
      BluetoothRecording.onStartRecording(resume, false); 
     } 
    } 

} 

private static void startBluetoothRecording(
     final OnBluetoothRecording BluetoothRecording, 
     final boolean resume, Context context) { 
    // TODO Auto-generated method stub 

    final int MAX_ATTEPTS_TO_CONNECT = 3; 
    final AudioManager audioManager = (AudioManager) context 
      .getSystemService(Context.AUDIO_SERVICE); 

    final CountDownTimer timer = getTimer(BluetoothRecording, audioManager, 
      resume); 

    context.registerReceiver(new BroadcastReceiver() { 

     @Override 
     public void onReceive(Context context, Intent intent) { 

      int state = intent.getIntExtra(
        AudioManager.EXTRA_SCO_AUDIO_STATE, -1); 
      if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) { 
       // cancel Timer 
       timer.cancel(); 
       context.unregisterReceiver(this); 

       // pass through and true because 
       // recording from bluetooth so set 8000kHz 

       BluetoothRecording.onStartRecording(resume, true); 

      } else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state) { 
       if (count > MAX_ATTEPTS_TO_CONNECT) { 
        context.unregisterReceiver(this); 
        // Stop BluetoothSCO 
        audioManager.stopBluetoothSco(); 
        // reset Counter 
        count = 0; 
        // stop timer 
        timer.cancel(); 
        // false because still recording not started 
        BluetoothRecording.onStartRecording(resume, false); 
       } else { 
        // Increment Disconnect state Count 
        count++; 

       } 
      } 

     } 
    }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)); 

    // Start the timer 
    timer.start(); 
    audioManager.startBluetoothSco(); 

} 

// set the Timeout 
private static CountDownTimer getTimer(
     final OnBluetoothRecording BluetoothRecording, 
     final AudioManager audioManager, final boolean resume) { 
    // TODO Auto-generated method stub 
    return new CountDownTimer(TIMEOUT, COUNTDOWN_INTERVAL) { 

     @Override 
     public void onTick(long millisUntilFinished) { 
      // Do Nothing 

     } 

     @Override 
     public void onFinish() { 

      // stopBluetoothSCO() and start Normal Recording 
      audioManager.stopBluetoothSco(); 

      // false because recording button is already clicked but still 
      // not recording. 
      BluetoothRecording.onStartRecording(resume, false); 
     } 
    }; 
} 

// Return's the bluetooth state 
private static boolean isBluetoothON() { 

    BluetoothAdapter bluetoothAdapter = BluetoothAdapter 
      .getDefaultAdapter(); 
    return bluetoothAdapter.isEnabled(); 
} 

// Return's the bluetoothFlag state 
private static boolean getBluetoothFlag(Context context) { 

    // shared pref 
    SharedPreferences sp = context.getSharedPreferences(Shared, 
      Context.MODE_PRIVATE); 
    return sp.getBoolean(bFlag, false); 

} 

}