Android Audio Recording Tutorial
03/11/2009
After many hours of trying to record audio on my Google Android device, I’ve finally arrived at a workable solution.Β There were a few bumps along the way besides the horribly out of date MediaRecorder documentation, which was sorely lacking details.Β For one, I could only get audio to record to the SD card.Β Additionally, the directory being recorded to must already exist before attempting to record to it. Without further ado, here is a complete example for recording audio on the Android via the MediaRecorder API:
package com.benmccann.android.hello;
import java.io.File;
import java.io.IOException;
import android.media.MediaRecorder;
import android.os.Environment;
/**
* @author <a href="http://www.benmccann.com">Ben McCann</a>
*/
public class AudioRecorder {
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public AudioRecorder(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
Hello, I’m a new comer to Android and I am a bit poor in Java.
I want to record a sound in my Android Emulator, so I copied your code(change the package name a bit) and Run. But it says “The Application Android, Application(process AndroidTest.package) has stopped unexpectedly. Please try again”. “Android, Application” is my app name and “AndroidTest.package” is my package name.
Can u tell me why it can’t be run? I’ve tried to change the code to make it run, but I can’t. Please help me! I must be able to get a audio stream into Android to test with my other urgent end year project.
Thanks in advanced π
hi Ben, I encountered the same problem on G1 as dragonksn’s when using your code . βThe application audiorecorder(process com.david.android.audiorecorder) has stopped unexpectedly. Please try againβ.
My audiorecoder class looks like as:
import android.app.Activity;
import android.os.Bundle;
//importing yours
…
public class audiorecorder extends Activity {
//then following your codes
…
}
Below is the Logcat info:
D/AndroidRuntime( 815): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
D/AndroidRuntime( 815): CheckJNI is ON
D/AndroidRuntime( 815): — registering native functions —
I/jdwp ( 815): received file descriptor 25 from ADB
I/ActivityManager( 56): Starting activity: Intent { flags=0x10000000 comp={com.david.android.audiorecorder/com.david.android.audiorecorder.audiorecorder} }
I/ActivityManager( 56): Start proc com.david.android.audiorecorder for activity com.david.android.audiorecorder/.audiorecorder: pid=824 uid=10040 gids={}
D/AndroidRuntime( 815): Shutting down VM
D/dalvikvm( 815): DestroyJavaVM waiting for non-daemon threads to exit
D/dalvikvm( 815): DestroyJavaVM shutting VM down
D/dalvikvm( 815): HeapWorker thread shutting down
D/dalvikvm( 815): HeapWorker thread has shut down
D/jdwp ( 815): JDWP shutting down net…
D/jdwp ( 815): +++ peer disconnected
I/dalvikvm( 815): Debugger has detached; object registry had 1 entries
D/dalvikvm( 815): VM cleaning up
D/dalvikvm( 815): LinearAlloc 0x0 used 594756 of 4194304 (14%)
I/jdwp ( 824): received file descriptor 10 from ADB
D/dalvikvm( 824): newInstance failed: no ()
D/AndroidRuntime( 824): Shutting down VM
W/dalvikvm( 824): threadid=3: thread exiting with uncaught exception (group=0x4000fe68)
E/AndroidRuntime( 824): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 824): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.david.android.audiorecorder/com.david.android.audiorecorder.audiorecorder}: java.lang.InstantiationException: com.david.android.audiorecorder.audiorecorder
E/AndroidRuntime( 824): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2082)
E/AndroidRuntime( 824): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2172)
E/AndroidRuntime( 824): at android.app.ActivityThread.access$1800(ActivityThread.java:112)
E/AndroidRuntime( 824): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1586)
E/AndroidRuntime( 824): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 824): at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 824): at android.app.ActivityThread.main(ActivityThread.java:3790)
E/AndroidRuntime( 824): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 824): at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 824): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
E/AndroidRuntime( 824): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:503)
E/AndroidRuntime( 824): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 824): Caused by: java.lang.InstantiationException: com.david.android.audiorecorder.audiorecorder
E/AndroidRuntime( 824): at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime( 824): at java.lang.Class.newInstance(Class.java:1458)
E/AndroidRuntime( 824): at android.app.Instrumentation.newActivity(Instrumentation.java:1097)
E/AndroidRuntime( 824): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
E/AndroidRuntime( 824): … 11 more
I/Process ( 56): Sending signal. PID: 824 SIG: 3
I/dalvikvm( 824): threadid=7: reacting to signal 3
I/dalvikvm( 824): Wrote stack trace to ‘/data/anr/traces.txt’
W/InputManagerService( 56): Starting input on non-focused client android.view.inputmethod.InputMethodManager$1@43704540 (uid=1000 pid=56)
W/InputManagerService( 56): Ignoring focus gain of: android.view.inputmethod.InputMethodManager$1@43704540
W/ActivityManager( 56): Launch timeout has expired, giving up wake lock!
W/ActivityManager( 56): Activity idle timeout for HistoryRecord{43852e68 {com.david.android.audiorecorder/com.david.android.audiorecorder.audiorecorder}}
D/dalvikvm( 100): GC freed 1763 objects / 93784 bytes in 135ms
I/Process ( 824): Sending signal. PID: 824 SIG: 9
I/ActivityManager( 56): Process com.david.android.audiorecorder (pid 824) has died.
D/InputManagerService( 56): hide the small icon for the input method
V/ActivityThread( 100): Resuming ActivityRecord{436cc620 token=android.os.BinderProxy@436cc0b0 {com.android.launcher/com.android.launcher.Launcher}} with isForward=false
I’m sorry for the mess. Could your please help me figure out what’s the reason caused this issue? Thanks a lot.
david
it works, thanks π
btw. did you try to call stop() and then start() again? I did and application gets closed without a word (e.g. no exception) :-((
dragonksn, david:
Hi, the cause is that the source above is not an android *application*, just a helper class. So it just can’t run by itself.
You have to do something like this:
public class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final AudioRecorder recorder = new AudioRecorder(“/audiometer/temp”);
recorder.start();
//….wait a while
recorder.stop();
}
}
krtek, my stop method calls release, which is why you can’t call stop and then start again. I believe if you take out the call to release you will be able to call start again.
Great! Now it works. Thanks to krtek & ben, you’re all good-heart men -_-
david
Thanks for help krtek, but still I have problem π
Sorry first that ask simple question but really I can’t find solution for that. I’m fool now :(.
I continue with your code
final AudioRecorder recorder = new AudioRecorder(β/audiometer/tempβ);
but it says the constructor is undefined (at the part) even I have already create a new classe of AudioRecorder(copied your code). When I mouse over audiometer, it says “audiometer can not be resolved”. And when I mouse over temp, it says “The method temp() is undefined for the type AndroidName”.
I tried with my SDCARD image folder “/media/Storage/Datas/I5_2008_2009/stage/MICA/support/Software/Android/Android_sdk/android-sdk-linux_x86-1.0_r2/tools/myandroid/sdcard.img” and the same thing happens(the same error messeges).
I also tried to insert sleep(6000); to waiting phase. Then it ask for sleep method. Can u tell why it ask for sleep method, as I saw that sleep method is already a public method, can’t I use it directely?
Thanks in advanced for help π
I now found the problem with
final AudioRecorder recorder = new AudioRecorder(β/audiometer/tempβ);
It has problem because the double quoat is not standard(the correct one), just rewrite it, then it work π
But now I want to ask u one more question:
I use the code to record but there isn’t any file created in my SDCARD image. So is my path incorrect?
(my SDCARD what I used in “run configuration”, where it already work with camera and my music files)
Can anyone help me please?
*I ask so often because I want to solve the problem as quick as possible, sorry in advanced π I try my best to solve the problem before asking π
Hi, Can anyone help me to play audio stream directly from Microphone in real time? I want this because I want to do voice synthesis in real time.
Thanks in advanced, π
dragonksn
Android does not currently support streaming of audio directly. You could probably tail the file as it’s being written though.
Hi Ben,
I’ve tried many ways for many days to tail the stream but I can’t do that. Can u give me some idea or help me with it?
Thanks for your kind help π
dragonksn
I haven’t actually tailed the stream myself, but saw someone mentioning it on the Android developer’s list. You might want to do a search there. I personally am just going to wait until the 1.5 SDK comes out since it sounds like it will have better support for that type of thing.
In addition, I think there might be problem with the mounting of the SDCARD as the new recorded file can be played only when I rerun the emulator. If not, there is no way to see the new recorded file. So is there anymeans to play the newly recorded file or is there other way to tail that file? Or is there any temp file for the recording file so that I can play without restarting the emulator??? (as I’ve tested many time, I think there is temp file but I can’t find where it is and i don’t know if I can play it)
Thx π
dragonksn
You can used adb (the Android Debug Bridge) to copy files off the emulator: http://developer.android.com/guide/developing/tools/adb.html
What about the temp file of the Android emulator, is there any as what I thought? And where it is?
But copying file to local machine is not really a good idea for me. Cause my app must work directly in the android individually. Can u tell me where does the temp file of android is (if there is as what I’ve thought)? And is it possible to play that???
Thx u so much for help π
dragonksn
I have a working app for streaming audio that work with android sdk 1.5 but the quality is very poor and there is a 5-10 second delay. If anyone is interested let me know.
sure, I’m very interested in your work. Can u let me know how you do it in detail?
Thx,
dragon
I am also interested. Please let me know.
hi, the emulator has comes to screen and display “Hello World, Audio Recorder!”, but i am not able to seen any recording device and no audio file has created in hard disk. should create the “temp” folder or what is the problem? Thanks in advance
Hi, Its working perfect in my phone , Great work.
Please send me the audio recording code for android simulator. I tried the above code. Its not working. Please send me the code for audio recording.
Can you provide similar example for Video record/capture too?
Wow thanks man! works perfect!
Hello,
i try this application, but it’s not playing.
I think my path is not good… but i don’t know how i have to change!
Here is my code..it’s a little bit long, because i also use Button. I can’t playing what i have recording!
package com.swyx.AudioRecording2;
import java.io.IOException;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class Record extends Activity {
//Wahrscheinlich ist den angegebenen Pfad nicht richtig! Nur wie gebe ich richtig ein?
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
//System.out.print(“bis hier geht”);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/*Erstelle ein neues Objekt von Typ Button,
das aktiviert wird sobald es geklickt wird*/
Button btn1 = (Button)findViewById(R.id.record);
btn1.setOnClickListener(btnListener1);
Button btn2 = (Button)findViewById(R.id.stop);
btn2.setOnClickListener(btnListener2);
Button btn3 = (Button)findViewById(R.id.play);
btn3.setOnClickListener(btnListener3);
}
//folgendes passiert, wenn auf btn1 geklickt wird
private OnClickListener btnListener1 = new OnClickListener()
{
public void onClick(View v)
{
final AudioRecorder2 recorder = new AudioRecorder2(“C:/Bochum”);
try {
recorder.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//β¦.wait a while
try {
recorder.stop();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
//folgendes passiert, wenn auf btn2 geklickt wird
private OnClickListener btnListener2 = new OnClickListener()
{
public void onClick(View v)
{
MediaPlayer mp = new MediaPlayer();
Toast.makeText(getBaseContext(),
“Hello, please stop!” + mp.isPlaying(),
Toast.LENGTH_LONG).show();
/*
try {
recorder.stop();
} catch (IOException e) {
}*/
}
};
//folgendes passiert, wenn auf btn3 geklickt wird
private OnClickListener btnListener3 = new OnClickListener()
{
public void onClick(View v)
{
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(“C:/Bochum”);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
Toast.makeText(getBaseContext(),
“Hello, please play!” +” is playing?: “+ mp.isPlaying(),
Toast.LENGTH_LONG).show();
}
};
}
Thanks for your help! I’m desesperate!
Sisi
PS: I have also copy your Class in the same Project!
Sisi,
You can’t record to C:\ because that’s a Windows path. Android uses Linux type paths. Try recording to something like “test/tmp.3gp” instead.
Thank you Ben!
Can i also record or play .mp3?
It’s difficult for me because i never use android bevor.
Thanks a lot for your help
Sisi
It works! i have a file .3gp.
I now want to try, if i can play what i have record with my microphone!
I use also emulator terminal to see which file or directory i have!
yes it works! i can also play .mp3! .3gp is only for video, isn’t it?
Sisi,
.3gp is also the format for Android audio. It’s a bit confusing, but 3gp is a container, which means that it holds the true format inside of it. In the case of Android audio, it’s actually an AMR-NB file inside of a 3gp container.
Hi, Benn,
can we able to record the audio using aac encoding? if so how? if not is there any way to do like that?
Hi Manoj,
Android currently only supports recording in AMR-NB in a 3gp container. The Android kernel would have to be patched in native C code to support recording in AAC.
hey all
anybody know how to add the phone numbers that takes a part in the call and the date of the call into the recording name?
for example a call between phone number 0541111111 and phone number 054222222 that happaend in 2.3.2009
will be save like this 0541111111_054222222_2.3.2009.3gp
Hello Ben,
Could you help me manage audio latency. I use AudioRecorder and when I measure latency using System.currentTimeMillis() and get record + playback = 50 ms
but when I measure the same using PC mic + PC speaker with test signal I got 320ms
Could you suggest the solution or even explain what is the problem
Thanks
Oleksandr
Hi Oleksandr,
Not sure I quite understand the problem. You are upset Android is too fast? :o) When you say using the PC is that directly on the PC or is that the Android emulator?
Hi Ben
can answer my question that i ask…. (:
Thanks Itay
Thanks a lot for these writings.
It is going to help me a lot in realising my voice solution.
Hi Ben,
I am using the above code to record the audio in sdcard. i can get the file named temp in sdcard with the recorded content. How can i play it in android emulator.. I am trying to play it through MediaPlayer when i click a button. But it shows the following error in logcat .
ERROR/PlayerDriver(554): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
ERROR/MediaPlayer(19985): error (1, -4)
WARN/System.err(19985): java.io.IOException: Prepare failed.: status=0x1
I don know why i am getting like this.. How to rectify this problem.. Can you please provide the solution for this..?
thanks in advance,
Senthil.M
You guys are not able to record sound in emulator because the android emulator doesn’t support it yet. This code should only work on the phone.
Ben,
Thanks for the heads up. This got it working for me. Why don’t they state the file needs to be there before recording? Sheesh.
-Dave
hi, im new to this android application but i need to port sound recorder application on beagle board .. if anybody can provide me the link for where i can download its .apk …
Hello Everyone,
I am new in Android development and using SDK 1.5. I have tried this code to record audio. But I found “W/ServiceManager( 35): Permission failure: android.permission.RECORD_AUDIO” in logcat.
How can I overcome this problem?
Thanks in advance
Hello everyone
The problem is solved with the change in the permission of the manifest file….
Thanks Ben for the nice code.
Hi!
I am more of a perl coder than a java nut, so I’m a bit stumped on how to compile all this.
Is there any chance that you or one of your readers could provide a precompiled .apk for this functionality?
I’ve searched around, and couldn’t find any other app that works….
Cheers,
M.
Hi Moritz,
This really isn’t a complete application, but only an example of how to create one. I hope it helps someone out there create a better sound recording app, but I’m afraid this alone isn’t going to be much help for you.
Hello everyone,
Again thanks for the great effort here.
I am trying to capture the raw sound data from the microphone of the device rather than saving it as .amr file. So that I can process it further by applying the FFT. is there any way to record the raw data using MediaRecorder class?
need some information about the it?
thanks in advance
Hello Ben,
Would please also help me to record the audio on PCM format directly from the MIC of the device. I am getting problem in the thread. Actually, I want to run a service in background to record audio continuously then it can be processed on other thread.
Thanks in advance.
Mahbub
Hi,
i am trying to record and save video.My code is not working, i am definately making some mistake.can some please give me sample code to record and save video. i tried the above example.
hey,Ben
can you please help in recording Video with Android….