共用方式為


Android 音訊

Android OS 提供廣泛的多媒體支援,包括音訊和視訊。 本指南著重於 Android 中的音訊,並涵蓋使用內建音訊播放機和錄製程序類別以及低階音訊 API 播放和錄製音訊。 它也涵蓋使用其他應用程式廣播的音訊事件,讓開發人員可以建置行為良好的應用程式。

概觀

現代行動裝置採用的功能,以前需要專用設備 –相機、音樂播放機和錄影機。 因此,多媒體架構已成為行動 API 中的一流功能。

Android 提供廣泛的多媒體支援。 本文會檢查在Android中使用音訊,並涵蓋下列主題

  1. 使用 MediaPlayer 播放音訊 – 使用內 MediaPlayer 建類別播放音訊,包括本機音訊檔案和具有 類別的 AudioTrack 串流音訊檔案。

  2. 錄製音訊 – 使用內 MediaRecorder 建類別錄製音訊。

  3. 使用音訊通知 – 使用音訊通知 來建立行為良好的應用程式,藉由暫停或取消其音訊輸出,正確回應事件(例如來電)。

  4. 使用低階音訊 – 直接寫入記憶體緩衝區, AudioTrack 使用 類別播放音訊。 使用 類別錄製音訊, AudioRecord 並直接從記憶體緩衝區讀取。

需求

本指南需要Android 2.0 (API層級5) 或更高版本。 請注意,Android 上的音訊偵錯必須在裝置上完成。

您必須在 AndroidManifest.XML要求RECORD_AUDIO權限:

已啟用RECORD_AUDIO的 Android 指令清單的必要許可權區段

使用 MediaPlayer 類別播放音訊

在Android中播放音訊最簡單的方式是使用內 建的 MediaPlayer 類別。 MediaPlayer 可以藉由傳入檔案路徑來播放本機或遠端檔案。 不過, MediaPlayer 會非常區分狀態,而且呼叫其其中一個處於錯誤狀態的方法會導致擲回例外狀況。 請務必按照以下所述的順序與 MediaPlayer 互動,以避免發生錯誤。

初始化和播放

使用 播放音訊 MediaPlayer 需要下列順序:

  1. 具現化新的 MediaPlayer 物件。

  2. 將檔案設定為透過 SetDataSource 方法播放。

  3. 呼叫 Prepare 方法以初始化播放機。

  4. 呼叫 Start 方法以啟動音訊播放。

下列程式代碼範例說明此用法:

protected MediaPlayer player;
public void StartPlayer(String  filePath)
{
  if (player == null) {
    player = new MediaPlayer();
  } else {
    player.Reset();
    player.SetDataSource(filePath);
    player.Prepare();
    player.Start();
  }
}

暫停和繼續播放

通叫 Pause 方法可以暫停播放:

player.Pause();

若要繼續暫停播放,請呼叫 Start 方法。 這會從播放中的暫停位置繼續:

player.Start();

在播放程式上呼叫 Stop 方法會結束進行中的播放:

player.Stop();

不再需要播放程式時,必須藉由呼叫 Release 方法來釋放資源:

player.Release();

使用 MediaRecorder 類別錄製音訊

在 Android 中錄製音訊的必然結果是 MediaPlayer MediaRecorder 類別。 MediaPlayer和一樣,它會區分狀態,並透過數個狀態轉換,以到達可以開始錄製的位置。 若要錄製音訊, RECORD_AUDIO 必須設定許可權。 如需如何設定應用程式許可權的指示,請參閱 使用AndroidManifest.xml

初始化和錄製

使用 MediaRecorder 錄製音訊需要下列步驟:

  1. 具現化新的 MediaRecorder 物件。

  2. 指定要用來透過 SetAudioSource 方法擷取音訊輸入的硬體裝置。

  3. 使用 SetOutputFormat 方法設定輸出檔音訊格式。 如需支援的音訊類型清單,請參閱 Android 支援的媒體格式

  4. 呼叫 SetAudioEncoder 方法來設定音訊編碼類型。

  5. 呼叫 SetOutputFile 方法,以指定音訊數據寫入的輸出檔名稱。

  6. 呼叫 Prepare 方法以初始化錄製器。

  7. 呼叫 Start 方法來開始錄製。

下列程式代碼範例說明此順序:

protected MediaRecorder recorder;
void RecordAudio (String filePath)
{
  try {
    if (File.Exists (filePath)) {
      File.Delete (filePath);
    }
    if (recorder == null) {
      recorder = new MediaRecorder (); // Initial state.
    } else {
      recorder.Reset ();
      recorder.SetAudioSource (AudioSource.Mic);
      recorder.SetOutputFormat (OutputFormat.ThreeGpp);
      recorder.SetAudioEncoder (AudioEncoder.AmrNb);
      // Initialized state.
      recorder.SetOutputFile (filePath);
      // DataSourceConfigured state.
      recorder.Prepare (); // Prepared state
      recorder.Start (); // Recording state.
    }
  } catch (Exception ex) {
    Console.Out.WriteLine( ex.StackTrace);
  }
}

停止錄製

若要停止錄製,請在 上MediaRecorder呼叫 Stop 方法:

recorder.Stop();

清除

MediaRecorder停止之後,呼叫 Reset 方法將其放回其閑置狀態:

recorder.Reset();

MediaRecorder不再需要 時,必須藉由呼叫 Release 方法釋放其資源:

recorder.Release();

管理音訊通知

AudioManager 類別

AudioManager 類別可讓您存取音訊通知,讓應用程式知道何時發生音訊事件。 此服務也可存取其他音訊功能,例如音量和響鈴模式控制。 AudioManager允許應用程式處理音訊通知來控制音訊播放。

管理音訊焦點

裝置的音訊資源(內建播放機和錄製器)會由所有執行中的應用程式共用。

就概念而言,這與只有一個應用程式具有鍵盤焦點的桌面計算機上應用程式類似:在按兩下滑鼠來選取其中一個執行中的應用程式之後,鍵盤輸入只會移至該應用程式。

音訊焦點是類似的想法,並防止多個應用程式同時播放或錄製音訊。 它比鍵盤焦點更複雜,因為它是自願的 – 應用程式可以忽略這個事實,因為它目前沒有音訊焦點和播放 -- 因為有不同類型的音訊焦點可以要求。 例如,如果要求者只預期要播放音訊很短的時間,它可能會要求暫時性焦點。

音訊焦點可以立即授與,或最初拒絕並稍後授與。 例如,如果應用程式在通話期間要求音訊焦點,則會遭到拒絕,但一旦通話完成,可能會授與焦點。 在此情況下,會註冊接聽程式,以便在音訊焦點被取走時據以回應。 要求音訊焦點是用來判斷播放或錄製音訊是否正常。

如需音訊焦點的詳細資訊,請參閱 管理音訊焦點

註冊音訊焦點的回呼

註冊 的IOnAudioChangeListenerFocusChangeListener呼是取得和釋放音訊焦點的重要部分。 這是因為授與音訊焦點可能會延遲到稍後。 例如,應用程式可能會在有通話進行時要求播放音樂。 在通話完成之前,不會授與音訊焦點。

基於這個理由,回呼物件會當做參數傳遞至 GetAudioFocusAudioManager方法,而這是註冊回呼的這個呼叫。 如果音訊焦點一開始遭到拒絕,但稍後授與,應用程式會藉 OnAudioFocusChange 由叫用回呼來通知。 相同的方法是用來告訴應用程式,音訊焦點正在被取走。

當應用程式使用音訊資源完成時,它會呼叫 AbandonFocusAudioManager方法,並再次傳入回呼。 這會取消註冊回呼並釋放音訊資源,讓其他應用程式可以取得音訊焦點。

要求音訊焦點

要求裝置音訊資源所需的步驟如下:

  1. 取得系統服務的句柄 AudioManager

  2. 建立回呼類別的實例。

  3. 在上呼叫 RequestAudioFocus 方法,以要求裝置的 AudioManager 音訊資源。 參數是回呼物件、串流類型(音樂、語音呼叫、響鈴等)和所要求的訪問許可權類型(例如,音訊資源可以立即要求或無限期要求)。

  4. 如果授與要求,則會 playMusic 立即叫用 方法,而且音訊會開始播放。

  5. 如果要求遭到拒絕,則不會採取任何進一步的動作。 在此情況下,只有在稍後授與要求時,音訊才會播放。

下列程式代碼範例顯示下列步驟:

Boolean RequestAudioResources(INotificationReceiver parent)
{
  AudioManager audioMan = (AudioManager) GetSystemService(Context.AudioService);
  AudioManager.IOnAudioFocusChangeListener listener  = new MyAudioListener(this);
  var ret = audioMan.RequestAudioFocus (listener, Stream.Music, AudioFocus.Gain );
  if (ret == AudioFocusRequest.Granted) {
    playMusic();
    return (true);
  } else if (ret == AudioFocusRequest.Failed) {
    return (false);
  }
  return (false);
}

釋放音訊焦點

播放播放軌時, AbandonFocus 會叫用 上的 AudioManager 方法。 這可讓另一個應用程式取得裝置的音訊資源。 如果其他應用程式已註冊自己的接聽程式,則會收到此音訊焦點變更的通知。

低階音訊 API

低階音訊 API 可讓您更充分掌控音訊播放和錄製,因為它們會直接與記憶體緩衝區互動,而不是使用檔案 URI。 在某些情況下,這個方法是較佳的。 此類場景包括:

  1. 從加密的音訊檔案播放時。

  2. 播放連續短剪輯時。

  3. 音訊串流。

AudioTrack 類別

AudioTrack 類別會使用低階音訊 API 進行錄製,而且是 類別的MediaPlayer低階對等專案。

初始化和播放

若要播放音訊,必須具現化 的新 實例 AudioTrack 。 傳入建構函式的自變數清單會指定如何播放緩衝區中包含的音訊範例。 自變數為:

  1. 串流類型 – 語音、鈴聲、音樂、系統或警示。

  2. Frequency – 以 Hz 表示的取樣率。

  3. 通道組態 – 單聲道或立體聲。

  4. 音訊格式 – 8 位或 16 位編碼。

  5. 緩衝區大小 – 以位元組為單位。

  6. 緩衝區模式 – 串流或靜態。

建構之後,會叫用 的 AudioTrack Play 方法,將其設定為開始播放。 將音訊緩衝區寫入至 AudioTrack 開始播放:

void PlayAudioTrack(byte[] audioBuffer)
{
  AudioTrack audioTrack = new AudioTrack(
    // Stream type
    Stream.Music,
    // Frequency
    11025,
    // Mono or stereo
    ChannelOut.Mono,
    // Audio encoding
    Android.Media.Encoding.Pcm16bit,
    // Length of the audio clip.
    audioBuffer.Length,
    // Mode. Stream or static.
    AudioTrackMode.Stream);

    audioTrack.Play();
    audioTrack.Write(audioBuffer, 0, audioBuffer.Length);
}

暫停和停止播放

呼叫 Pause 方法以暫停播放:

audioTrack.Pause();

呼叫 Stop 方法將會永久終止播放:

audioTrack.Stop();

清理

AudioTrack不再需要 時,必須藉由呼叫 Release 來釋放其資源:

audioTrack.Release();

AudioRecord 類別

AudioRecord 類別相當於AudioTrack錄製端的 。 如同 AudioTrack,它會直接使用記憶體緩衝區來取代檔案和 URI。 它要求 RECORD_AUDIO 在指令清單中設定許可權。

初始化和錄製

第一個步驟是建構新的 AudioRecord 物件。 傳入建構函式的自變數清單會提供錄製所需的所有資訊。 不同於 中的 AudioTrack,其中自變數主要是列舉,中的 AudioRecord 對等自變數是整數。 包括:

  1. 硬體音訊輸入來源,例如麥克風。

  2. 串流類型 – 語音、鈴聲、音樂、系統或警示。

  3. Frequency – 以 Hz 表示的取樣率。

  4. 通道組態 – 單聲道或立體聲。

  5. 音訊格式 – 8 位或 16 位編碼。

  6. 緩衝區大小位元組

AudioRecord建構 之後,會叫用其 StartRecording 方法。 現在已準備好開始錄製。 會 AudioRecord 持續讀取輸入的音訊緩衝區,並將此輸入寫入音訊檔案。

void RecordAudio()
{
  byte[] audioBuffer = new byte[100000];
  var audRecorder = new AudioRecord(
    // Hardware source of recording.
    AudioSource.Mic,
    // Frequency
    11025,
    // Mono or stereo
    ChannelIn.Mono,
    // Audio encoding
    Android.Media.Encoding.Pcm16bit,
    // Length of the audio clip.
    audioBuffer.Length
  );
  audRecorder.StartRecording();
  while (true) {
    try
    {
      // Keep reading the buffer while there is audio input.
      audRecorder.Read(audioBuffer, 0, audioBuffer.Length);
      // Write out the audio file.
    } catch (Exception ex) {
      Console.Out.WriteLine(ex.Message);
      break;
    }
  }
}

停止錄製

呼叫 Stop 方法會終止錄製:

audRecorder.Stop();

清理

AudioRecord當不再需要 物件時,呼叫其 Release 方法會釋放與其相關聯的所有資源:

audRecorder.Release();

摘要

Android OS 提供功能強大的架構,可用來播放、錄製和管理音訊。 本文涵蓋如何使用高階 MediaPlayer 和類別播放和 MediaRecorder 錄製音訊。 接下來,它探索如何使用音訊通知,在不同的應用程式之間共用裝置的音訊資源。 最後,它會處理如何使用低階 API 來播放和錄製音訊,而該 API 會直接與記憶體緩衝區互動。