Basic recording example
This example shows the simplest way to record audio with AMRAudioRecorder.// Set up the recording directory
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String recordingDirectory = sdcardPath + "/recordings/";
File dir = new File(recordingDirectory);
if (!dir.exists()) {
dir.mkdirs();
}
// Create recorder and start recording
AMRAudioRecorder recorder = new AMRAudioRecorder(recordingDirectory);
recorder.start();
// ... record audio ...
// Stop and get the file path
recorder.stop();
String audioPath = recorder.getAudioFilePath();
Complete recording activity
This example demonstrates a full Android activity with record, pause, resume, and discard functionality, based on the library’s sample app.public class MainActivity extends AppCompatActivity {
private AMRAudioRecorder mRecorder;
private TextView mRecordingTime;
private int mRecordTimeInterval;
private EasyTimer mAudioTimeLabelUpdater;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecordingTime = findViewById(R.id.recordingTime);
}
public void onToggleRecordClick(View view) {
if (mRecorder == null) {
// Start new recording
startRecording(view);
} else {
// Toggle pause/resume
if (mRecorder.isRecording()) {
pauseRecording(view);
} else {
resumeRecording(view);
}
}
}
private void startRecording(View view) {
resetRecording();
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String recordingDirectory = sdcardPath + "/wtrecorder/";
File dir = new File(recordingDirectory);
if (!dir.exists()) {
dir.mkdirs();
}
mRecorder = new AMRAudioRecorder(recordingDirectory);
mRecorder.start();
((ImageButton) view).setImageResource(R.drawable.ic_pause);
// Start timer to update recording time label
mAudioTimeLabelUpdater = new EasyTimer(1000, new EasyTimer.CallBack() {
@Override
public void execute() {
int time = mRecordTimeInterval;
int min = time / 60, sec = time % 60;
String minStr = min < 10 ? "0" + min : "" + min;
String secStr = sec < 10 ? "0" + sec : "" + sec;
mRecordingTime.setText(minStr + ":" + secStr);
mRecordTimeInterval++;
}
});
}
private void pauseRecording(View view) {
((ImageButton) view).setImageResource(R.drawable.ic_play);
mAudioTimeLabelUpdater.stop();
mRecorder.pause();
}
private void resumeRecording(View view) {
((ImageButton) view).setImageResource(R.drawable.ic_pause);
mRecorder.resume();
mAudioTimeLabelUpdater.restart();
}
public void onDoneClick(View view) {
if (mRecorder == null) {
return;
}
mRecorder.stop();
// Navigate to playback screen
Intent intent = new Intent(this, PlaybackActivity.class);
intent.putExtra("audioFilePath", mRecorder.getAudioFilePath());
startActivity(intent);
mRecorder = null;
resetRecording();
}
public void onTrashClick(View view) {
if (mRecorder == null) {
return;
}
mRecorder.clear();
mRecorder = null;
resetRecording();
}
private void resetRecording() {
if (mAudioTimeLabelUpdater != null) {
mAudioTimeLabelUpdater.stop();
mAudioTimeLabelUpdater = null;
}
mRecordTimeInterval = 0;
mRecordingTime.setText("00:00");
ImageButton toggleButton = findViewById(R.id.toggleRecord);
toggleButton.setImageResource(R.drawable.ic_play);
}
}
Handling permissions (Android 6.0+)
For Android Marshmallow (API 23) and above, you must request permissions at runtime.private static final int PERMISSION_REQUEST_CODE = 100;
private String[] permissionsList = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 23) {
if (!hasPermissions()) {
requestPermissions(permissionsList, PERMISSION_REQUEST_CODE);
}
}
}
private boolean hasPermissions() {
for (String permission : permissionsList) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
boolean allGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false;
break;
}
}
if (!allGranted) {
Toast.makeText(this, "Permissions required for recording", Toast.LENGTH_LONG).show();
finish();
}
}
}
Error handling
Handle potential errors when working with AMRAudioRecorder.try {
AMRAudioRecorder recorder = new AMRAudioRecorder(recordingDirectory);
boolean started = recorder.start();
if (!started) {
// MediaRecorder failed to prepare
Toast.makeText(this, "Failed to start recording", Toast.LENGTH_SHORT).show();
return;
}
// Recording in progress...
if (recorder.isRecording()) {
try {
recorder.pause();
} catch (IllegalStateException e) {
Log.e("Recorder", "Cannot pause: not recording", e);
}
}
// Resume after pause
if (!recorder.isRecording()) {
try {
recorder.resume();
} catch (IllegalStateException e) {
Log.e("Recorder", "Cannot resume: already recording", e);
}
}
boolean stopped = recorder.stop();
if (!stopped) {
Toast.makeText(this, "Failed to merge recordings", Toast.LENGTH_SHORT).show();
}
} catch (IllegalArgumentException e) {
// Invalid directory provided
Log.e("Recorder", "Invalid recording directory", e);
Toast.makeText(this, "Recording directory not found", Toast.LENGTH_SHORT).show();
}
State management pattern
Manage recorder state throughout the activity lifecycle.public class RecordingActivity extends AppCompatActivity {
private AMRAudioRecorder recorder;
private RecordingState state = RecordingState.IDLE;
enum RecordingState {
IDLE,
RECORDING,
PAUSED
}
private void updateRecordingState() {
if (recorder == null) {
state = RecordingState.IDLE;
} else if (recorder.isRecording()) {
state = RecordingState.RECORDING;
} else {
state = RecordingState.PAUSED;
}
updateUI();
}
private void updateUI() {
switch (state) {
case IDLE:
recordButton.setImageResource(R.drawable.ic_record);
recordButton.setEnabled(true);
doneButton.setEnabled(false);
break;
case RECORDING:
recordButton.setImageResource(R.drawable.ic_pause);
recordButton.setEnabled(true);
doneButton.setEnabled(true);
break;
case PAUSED:
recordButton.setImageResource(R.drawable.ic_resume);
recordButton.setEnabled(true);
doneButton.setEnabled(true);
break;
}
}
}
Recording with custom storage location
Use app-specific storage for better compatibility with Android 10+ scoped storage.// Use app-specific external storage (no permissions needed on Android 10+)
File recordingDir = new File(getExternalFilesDir(null), "recordings");
if (!recordingDir.exists()) {
recordingDir.mkdirs();
}
AMRAudioRecorder recorder = new AMRAudioRecorder(recordingDir.getAbsolutePath());
recorder.start();
// Later, get the file
recorder.stop();
String audioPath = recorder.getAudioFilePath();
File audioFile = new File(audioPath);
// Share or process the file
if (audioFile.exists()) {
long fileSizeInBytes = audioFile.length();
Log.d("Recording", "Saved " + fileSizeInBytes + " bytes to " + audioPath);
}