This is my code:
RecordActivity.java
public class RecordActivity extends ActionBarActivity {
protected static final String TAG = "RecordActivity";
private ImageButton start_btn,pause_btn,stop_btn;
private MediaRecorder myrecorder = null;
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
Context mcontext;
private String mTargetRecordFileName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record);
mcontext = this;
start_btn = (ImageButton) findViewById(R.id.im_start_btn);
pause_btn = (ImageButton) findViewById(R.id.im_pause_btn);
stop_btn = (ImageButton) findViewById(R.id.im_stop_btn);
stop_btn.setVisibility(View.INVISIBLE);
pause_btn.setVisibility(View.INVISIBLE);
start_btn.setEnabled(true);
start_btn.setOnClickListener(new OnClickListener() {
@SuppressLint("InlinedApi")
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
start_btn.setVisibility(View.INVISIBLE);
pause_btn.setVisibility(View.VISIBLE);
stop_btn.setVisibility(View.VISIBLE);
start_btn.setEnabled(false);
pause_btn.setEnabled(true);
myrecorder = new MediaRecorder();
myrecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myrecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
myrecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myrecorder.setOutputFile(getTemporaryFileName());
start(v);
}
private void start(View v) {
// TODO Auto-generated method stub
try{
myrecorder.prepare();
myrecorder.start();
Log.i(TAG, getTemporaryFileName());
} catch(IllegalStateException e){
} catch(IOException e){
}
}
});
pause_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
appendToFile(mTargetRecordFileName, getTemporaryFileName());
myrecorder.stop();
myrecorder.reset();
myrecorder.release();
pause_btn.setVisibility(View.INVISIBLE);
start_btn.setVisibility(View.VISIBLE);
stop_btn.setVisibility(View.VISIBLE);
start_btn.setEnabled(true);
stop_btn.setEnabled(true);
}
});
stop_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
appendToFile(mTargetRecordFileName, getTemporaryFileName());
myrecorder.stop(); // stop recording
myrecorder.reset(); // set state to idle
myrecorder.release(); // release resources back to the system
myrecorder = null;
start_btn.setVisibility(View.VISIBLE);
pause_btn.setVisibility(View.INVISIBLE);
start_btn.setEnabled(true);
}
});
}
private String getTemporaryFileName() {
return mcontext.getCacheDir().getAbsolutePath() + File.separator + "tmprecord";
}
private void appendToFile(final String targetFileName,final String newFileName) {
Mp4ParserWrapper.append(targetFileName, newFileName);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.record, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Mp4ParserWrapper.java
public class Mp4ParserWrapper {
public static final int FILE_BUFFER_SIZE = 1024;
private static final String TAG = "Mp4ParserWrapper";
public static boolean append(String mainFileName, String anotherFileName){
boolean rvalue = false;
try{
File targetFile = new File(mainFileName);
File anotherFile = new File(anotherFileName);
if (targetFile.exists() && targetFile.length() > 0) {
String tmpFileName = mainFileName + ".tmp";
append(mainFileName, anotherFileName, tmpFileName);
copyFile(tmpFileName, mainFileName);
rvalue = anotherFile.delete() && new File(tmpFileName).delete();
} else if (targetFile.createNewFile()) {
copyFile(anotherFileName, mainFileName);
rvalue = anotherFile.delete();
}
} catch (IOException e) {
Log.e(TAG,"Append two mp4 files exception", e);
}
return rvalue;
}
public static void copyFile(final String from, final String destination)
throws IOException {
FileInputStream in = new FileInputStream(from);
FileOutputStream out = new FileOutputStream(destination);
copy(in, out);
in.close();
out.close();
}
public static void copy(FileInputStream in, FileOutputStream out) throws IOException {
byte[] buf = new byte[FILE_BUFFER_SIZE];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
public static void append(
final String firstFile,
final String secondFile,
final String newFile) throws IOException {
final Movie movieA = MovieCreator.build(new FileDataSourceImpl(secondFile));
final Movie movieB = MovieCreator.build(new FileDataSourceImpl(firstFile));
final Movie finalMovie = new Movie();
final List<Track> movieOneTracks = movieA.getTracks();
final List<Track> movieTwoTracks = movieB.getTracks();
for (int i = 0; i < movieOneTracks.size() || i < movieTwoTracks.size(); ++i) {
finalMovie.addTrack(new
AppendTrack(movieTwoTracks.get(i),
movieOneTracks.get(i)));
}
final Container container = new DefaultMp4Builder().build(finalMovie);
final FileOutputStream fos = new FileOutputStream(new File(String.format(newFile)));
final WritableByteChannel bb = Channels.newChannel(fos);
container.writeContainer(bb);
fos.close();
}
}
I am using isoparser1.0 RC-27.jar for merging audio files. But am getting the following errors:
07-21 14:02:15.230: I/RecordActivity(8748): /data/data/com.example.audiorecordertest/cache/tmprecord
07-21 14:02:19.433: D/AndroidRuntime(8748): Shutting down VM
07-21 14:02:19.433: W/dalvikvm(8748): threadid=1: thread exiting with uncaught exception (group=0x41635d40)
07-21 14:02:19.437: E/AndroidRuntime(8748): FATAL EXCEPTION: main
07-21 14:02:19.437: E/AndroidRuntime(8748): Process: com.example.audiorecordertest, PID: 8748
07-21 14:02:19.437: E/AndroidRuntime(8748): java.lang.NullPointerException
07-21 14:02:19.437: E/AndroidRuntime(8748): at java.io.File.fixSlashes(File.java:185)
07-21 14:02:19.437: E/AndroidRuntime(8748): at java.io.File.<init>(File.java:134)
07-21 14:02:19.437: E/AndroidRuntime(8748): at com.example.audiorecordertest.Mp4ParserWrapper.append(Mp4ParserWrapper.java:37)
07-21 14:02:19.437: E/AndroidRuntime(8748): at com.example.audiorecordertest.RecordActivity.appendToFile(RecordActivity.java:195)
07-21 14:02:19.437: E/AndroidRuntime(8748): at com.example.audiorecordertest.RecordActivity.access$7(RecordActivity.java:194)
07-21 14:02:19.437: E/AndroidRuntime(8748): at com.example.audiorecordertest.RecordActivity$2.onClick(RecordActivity.java:98)
07-21 14:02:19.437: E/AndroidRuntime(8748): at android.view.View.performClick(View.java:4456)
07-21 14:02:19.437: E/AndroidRuntime(8748): at android.view.View$PerformClick.run(View.java:18465)
07-21 14:02:19.437: E/AndroidRuntime(8748): at android.os.Handler.handleCallback(Handler.java:733)
07-21 14:02:19.437: E/AndroidRuntime(8748): at android.os.Handler.dispatchMessage(Handler.java:95)
07-21 14:02:19.437: E/AndroidRuntime(8748): at android.os.Looper.loop(Looper.java:136)
07-21 14:02:19.437: E/AndroidRuntime(8748): at android.app.ActivityThread.main(ActivityThread.java:5086)
07-21 14:02:19.437: E/AndroidRuntime(8748): at java.lang.reflect.Method.invokeNative(Native Method)
07-21 14:02:19.437: E/AndroidRuntime(8748): at java.lang.reflect.Method.invoke(Method.java:515)
07-21 14:02:19.437: E/AndroidRuntime(8748): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
07-21 14:02:19.437: E/AndroidRuntime(8748): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
07-21 14:02:19.437: E/AndroidRuntime(8748): at dalvik.system.NativeStart.main(Native Method)
It would be good to know what is the container which i've used and how to move audio files from container to sd card.
The following line is causing the problem:
appendToFile(mTargetRecordFileName, getTemporaryFileName());
You've declared mTargetRecordFileName
, but not initialized it anywhere, so it's trying to perform a file operation using a null
filename.
The following method will return a filename for a file in the root external storage that you can assign to mTargetRecordFileName
:
private String getOutputFile()
{
return Environment.getExternalStorageDirectory() +
File.separator + "media_file_name.mp4";
}
Also, make sure you've got the following permission in the manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />