媒體和相機:媒體錄音
Android多媒體框架包括支援捕捉和編碼各種常見的音訊和視訊格式。 如果裝置硬體支援,您可以使用MediaRecorder API。
本文件介紹如何使用MediaRecorder編寫從裝置麥克風捕獲音訊的應用程式,儲存音訊並播放(使用MediaPlayer)。 要錄製視訊,您需要使用裝置的相機和MediaRecorder。 這在攝像機指南中有所描述。
注意:Android Emulator無法錄製音訊。 確保在可以記錄的真實裝置上測試您的程式碼。
一、請求錄製音訊的許可權
為了能夠記錄,您的應用程式必須告訴使用者它將訪問裝置的音訊輸入。 您必須在應用的清單檔案中包含此許可權標籤:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
RECORD_AUDIO被認為是“危險的”許可,因為它可能會對使用者的隱私造成風險。 從Android 6.0(API級別23)開始,使用危險許可的應用程式必須在執行時請求使用者批准。 使用者授予許可權後,該應用程式應該記住並不再詢問。 下面的示例程式碼顯示瞭如何使用ActivityCompat.requestPermissions()實現此行為。
二、使用MediaRecorder
使用以下呼叫初始化MediaRecorder的新例項:
1、使用setAudioSource()設定音訊源。 你可能會使用MIC。
注意:大多數音訊源(包括DEFAULT)會對音訊訊號進行處理。 錄製原始音訊選擇UNPROCESSED。 某些裝置不支援未處理的輸入。 首先呼叫AudioManager.getProperty(“PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED”)以驗證它是否可用。 如果不是,請嘗試使用VOICE_RECOGNITION,而不使用AGC或噪聲抑制。 即使不支援該屬性,也可以使用UNPROCESSED作為音訊源,但在這種情況下不能保證訊號是否未被處理。
2、使用setOutputFormat()設定輸出檔案格式。
3、使用setOutputFile()設定輸出檔名。
4、使用setAudioEncoder()設定音訊編碼器。
5、通過呼叫prepare()完成初始化。
通過呼叫start()和stop()分別啟動和停止錄音機。
完成MediaRecorder例項後,儘快通過呼叫release()釋放其資源。
三、示例程式碼
下面的示例活動顯示如何使用MediaRecorder錄製音訊檔案。 它還使用MediaPlayer播放音訊。
package com.android.audiorecordtest; import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import java.io.IOException; public class AudioRecordTest extends AppCompatActivity { private static final String LOG_TAG = "AudioRecordTest"; private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200; private static String mFileName = null; private RecordButton mRecordButton = null; private MediaRecorder mRecorder = null; private PlayButton mPlayButton = null; private MediaPlayer mPlayer = null; // Requesting permission to RECORD_AUDIO private boolean permissionToRecordAccepted = false; private String [] permissions = {Manifest.permission.RECORD_AUDIO}; @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode){ case REQUEST_RECORD_AUDIO_PERMISSION: permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; break; } if (!permissionToRecordAccepted ) finish(); } private void onRecord(boolean start) { if (start) { startRecording(); } else { stopRecording(); } } private void onPlay(boolean start) { if (start) { startPlaying(); } else { stopPlaying(); } } private void startPlaying() { mPlayer = new MediaPlayer(); try { mPlayer.setDataSource(mFileName); mPlayer.prepare(); mPlayer.start(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } } private void stopPlaying() { mPlayer.release(); mPlayer = null; } private void startRecording() { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setOutputFile(mFileName); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { mRecorder.prepare(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } mRecorder.start(); } private void stopRecording() { mRecorder.stop(); mRecorder.release(); mRecorder = null; } class RecordButton extends Button { boolean mStartRecording = true; OnClickListener clicker = new OnClickListener() { public void onClick(View v) { onRecord(mStartRecording); if (mStartRecording) { setText("Stop recording"); } else { setText("Start recording"); } mStartRecording = !mStartRecording; } }; public RecordButton(Context ctx) { super(ctx); setText("Start recording"); setOnClickListener(clicker); } } class PlayButton extends Button { boolean mStartPlaying = true; OnClickListener clicker = new OnClickListener() { public void onClick(View v) { onPlay(mStartPlaying); if (mStartPlaying) { setText("Stop playing"); } else { setText("Start playing"); } mStartPlaying = !mStartPlaying; } }; public PlayButton(Context ctx) { super(ctx); setText("Start playing"); setOnClickListener(clicker); } } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); // Record to the external cache directory for visibility mFileName = getExternalCacheDir().getAbsolutePath(); mFileName += "/audiorecordtest.3gp"; ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION); LinearLayout ll = new LinearLayout(this); mRecordButton = new RecordButton(this); ll.addView(mRecordButton, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0)); mPlayButton = new PlayButton(this); ll.addView(mPlayButton, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0)); setContentView(ll); } @Override public void onStop() { super.onStop(); if (mRecorder != null) { mRecorder.release(); mRecorder = null; } if (mPlayer != null) { mPlayer.release(); mPlayer = null; } } }