Sound recording and playback is really simple using the MediaRecorder and MediaPlayer classes .. see the example below ..
Sample App
-
First some layout .. a button to start/stop recording and a button to play the recorded stuff (main.xml):
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/output" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="" /> <Button android:text="@+string/record" android:id="@+id/btRecord" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="@+string/play" android:id="@+id/btPlay" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout>
-
Adjusting the externalized strings in the strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Soundrecorder Tutorial</string> <string name="record">Record!</string> <string name="play">Play</string> </resources>
-
Set permissions needed in the AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.hascode.android" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".RecorderActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> </manifest>
-
Now the activity to bring in some action .. RecorderActivity.java
package com.hascode.android; import java.io.File; import java.io.IOException; import android.app.Activity; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class RecorderActivity extends Activity { private static final String APP_TAG = "com.hascode.android.soundrecorder"; private MediaRecorder recorder = new MediaRecorder(); private MediaPlayer player = new MediaPlayer(); private Button btRecord; private Button btPlay; private TextView resultView; private boolean recording = false; private boolean playing = false; private File outfile = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); resultView = (TextView) findViewById(R.id.output); try { // the soundfile File storageDir = new File(Environment .getExternalStorageDirectory(), "com.hascode.recorder"); storageDir.mkdir(); Log.d(APP_TAG, "Storage directory set to " + storageDir); outfile = File.createTempFile("hascode", ".3gp", storageDir); // init recorder recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); recorder.setOutputFile(outfile.getAbsolutePath()); // init player player.setDataSource(outfile.getAbsolutePath()); } catch (IOException e) { Log.w(APP_TAG, "File not accessible ", e); } catch (IllegalArgumentException e) { Log.w(APP_TAG, "Illegal argument ", e); } catch (IllegalStateException e) { Log.w(APP_TAG, "Illegal state, call reset/restore", e); } btRecord = (Button) findViewById(R.id.btRecord); btRecord.setOnClickListener(handleRecordClick); btPlay = (Button) findViewById(R.id.btPlay); btPlay.setOnClickListener(handlePlayClick); } private final OnClickListener handleRecordClick = new OnClickListener() { @Override public void onClick(View view) { if (!recording) { startRecord(); } else { stopRecord(); } } }; private final OnClickListener handlePlayClick = new OnClickListener() { @Override public void onClick(View view) { if (!playing) { startPlay(); } else { stopPlay(); } } }; private void startRecord() { Log.d(APP_TAG, "start recording.."); printResult("start recording.."); try { recorder.prepare(); recorder.start(); recording = true; } catch (IllegalStateException e) { Log .w(APP_TAG, "Invalid recorder state .. reset/release should have been called"); } catch (IOException e) { Log.w(APP_TAG, "Could not write to sd card"); } } private void stopRecord() { Log.d(APP_TAG, "stop recording.."); printResult("stop recording.."); recorder.stop(); recorder.reset(); recorder.release(); recording = false; } private void startPlay() { Log.d(APP_TAG, "starting playback.."); printResult("start playing.."); try { playing = true; player.prepare(); player.start(); } catch (IllegalStateException e) { Log.w(APP_TAG, "illegal state .. player should be reset"); } catch (IOException e) { Log.w(APP_TAG, "Could not write to sd card"); } } private void stopPlay() { Log.d(APP_TAG, "stopping playback.."); printResult("stop playing.."); player.stop(); player.reset(); player.release(); playing = false; } private void printResult(String result) { resultView.setText(result); } }
-
Finally the app looks like this on my emulator
The Application in the Android Emulator -
Now play around with the recorder
How to connect a virtual sdcard to the emulator
-
A SD Card is created using the android tool or the mksdcard tool
android create avd -n <youravd> -t <targetID> -c <size>[K|M] or: mksdcard <size> <file>
-
Start the emulator with the param -sdcard /path/to/sdcard.img
-
More information is available at the Android Developers Website
Troubleshooting
-
In general use the logcat tool from the Android Debugging Bridge to look for debugging messages, exceptions, strack traces ..
# adb -s emulator-5554 shell logcat I/ActivityManager( 52): Displayed activity com.hascode.android/.RecorderActivity: I/ARMAssembler( 52): generated scanline__00000077:03545404_00000A04_00000000 [ 29 I/ARMAssembler( 52): generated scanline__00000177:03515104_00001A01_00000000 [ 73 D/com.hascode.android.soundrecorder( 198): start recording.. W/com.hascode.android.soundrecorder( 198): Could not write to sd card
-
W/com.hascode.android.soundrecorder(209): File not accessible – Check the permissions set for the directory you are trying to save the files to – more information is available at the Android Developers Website – also take a look in your AndroidManifest.xml and check if the permission WRITE_EXTERNAL_STORAGE is set:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
-
Using the Android Debugging Bridge it is possible to check the user permissions set in the emulator
adb -s emulator-5554 shell # ls -l sdcard d---rwxr-x system sdcard_rw 2010-05-02 14:50 LOST.DIR # ls -l sdcard/com.hascode.recorder ----rwxr-x system sdcard_rw 0 2010-05-02 15:33 hascode44433.3gp
-
If you need a GUI – try the the Dalvik Debug Monitor Service by running ddms – screenshots below:
Figure 1. Debugging in DDMSFigure 2. File System
Resources
Article Updates
-
2015-03-03: Table of contents and image captions added.