I have a son who is turning fourteen in a few weeks. He is every bit as much into gadgets and in particular Android phones as me; however, we don’t always see eye to eye on what is “cool.” Take for instance the app Songify — my son loves it, and he cranks out half a dozen “songs” on the car ride from the house to the grocery. And he’s not alone in his obsession. The app currently touts over a million downloads in Google Play.
If you’re not familiar with the premise of the app, the tag line says it all: “turn speech into music.” Just don’t set your internal bar too high for the resulting “music.” It’s entertaining — let’s leave it at that. With the immense popularity in the last 30 days of Songify and similar apps, I’ve seen a new surge of questions in the Android forums related to recording voice, so I figured what better subject to tackle this week in my post. You can follow along step by step tutorial, or download and import the entire project.
1. Start a new Android project in Eclipse. Target Android 1.6 or higher. Be sure to change the startup activity name to Main.java.
2. Add a couple of permissions to the manifest. We require access to the SD file system, as well as the media recorder.
AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.authorwjf.voice_rec" android:versionCode="1" android:versionName="1.0" >
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".Main"
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>
</manifest>
3. Create a simple table layout in the /res/layout folder. The UI for our demo consists of two buttons and a label.
Main.xml
<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="*"> <TableRow> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Voice Recorder Demo" android:layout_span="2" android:layout_gravity="center" android:padding="12dip"/> </TableRow> <TableRow> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/record_button" android:text="record" android:layout_margin="12dip"/> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/play_back_button" android:text="play" android:layout_margin="12dip"/> </TableRow> </TableLayout>
4. We are ready for the /src/Main.java file. Let’s start by declaring some class level variables and wiring up our buttons in the on create override.
Main.java package com.authorwjf.voice_rec;
import android.app.Activity; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast;
public class Main extends Activity implements OnClickListener {
MediaRecorder mRecorder = new MediaRecorder(); MediaPlayer mPlayer = new MediaPlayer(); boolean isRecording = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.play_back_button).setOnClickListener(this);
findViewById(R.id.record_button).setOnClickListener(this);
}
}
5. We have come to the heart of our code — the on-click handler. This is where we will do the recording and the playback.
Main.java
@Override
public void onClick(View v) {
mPlayer.stop();
switch (v.getId()) {
case R.id.play_back_button:
if (!isRecording && !mPlayer.isPlaying()) {
try {
mPlayer.reset();
mPlayer.setDataSource("/sdcard/audio_demo.3gp");
mPlayer.prepare();
mPlayer.start();
} catch (Exception e) {
Toast.makeText(this, "Error playing back audio.",Toast.LENGTH_SHORT).show();
}
}
break;
case R.id.record_button:
if (isRecording) {
isRecording = false;
((Button)(findViewById(R.id.record_button))).setText("record");
mRecorder.reset();
} else {
try {
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile("/sdcard/audio_demo.3gp");
mRecorder.prepare();
mRecorder.start();
((Button)(findViewById(R.id.record_button))).setText("stop");
isRecording = true;
} catch (Exception e) {
Toast.makeText(this, "Error starting recorder.",Toast.LENGTH_SHORT).show();
}
} break; } }
6. We need to handle cleaning up our media recorder and playback objects when the activity gets destroyed — this keeps the app from crashing or leaking resources. Note: The app doesn’t attempt to continue recording through an orientation change.
Main.java
@Override
public void onDestroy() {
if (isRecording) {
Toast.makeText(this, "Recorder stopped.",Toast.LENGTH_SHORT).show();
mRecorder.stop();
}
mRecorder.release();
mPlayer.stop();
mPlayer.release();
super.onDestroy();
}
The app should be ready to take for a spin. Since voice recording isn’t supported on the emulator, you’ll need to run the demo on an actual device. Operation is self-evident: say something and then play it back (Figure A).
Figure A
Pretty easy, right? And best of all, I’m sure it will provide you with hours of entertainment. I’ve already recorded an a capella rendition of Bon Jovi’s “Dead or Alive” for our next family outing to the grocery.
Automatically sign up for TechRepublic's App Builder newsletter!


































