Im running into a curious problem. My app allows the user to record a voice message which will be saved as an .amr file.
String fileName = getFilesDir().getAbsolutePath() + "/voiceMessage.amr";
MediaRecorder mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB);
mediaRecorder.setOutputFile(fileName);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);
After recording the user is able to play his recorded message, which works as expected:
MediaPlayer mediaPlayer = new MediaPlayer();
try {
fileName = getFilesDir().getAbsolutePath() + "/voiceMessage.amr";
Log.i(TAG, fileName);
mediaPlayer.setDataSource(fileName);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
}
Logcat prints /data/data/com.messages.android/files/voiceMessage.amr
for fileName
, which is fine. After saving the voice message, I'll upload it to my server and download it later for each user. The downloaded file is saved on the interal storage.
Now the part which throws an exception:
MediaPlayer mediaPlayer = new MediaPlayer();
File voiceMessage = user.getVoiceMessageFile(context);
if (voiceMessage.exists()) {
try {
Log.i(TAG, voiceMessage.getAbsolutePath());
mediaPlayer.setDataSource(voiceMessage.getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
}
}
Logcat prints /data/data/com.messages.android/files/c02bfe404359860eb582aff318afb1f41469514396529.amr
for voiceMessage.getAbsolutePath()
which is fine. So the file exists and is on internal storage. I do not modify the file on server side. Just saving and downloading.
Still receiving an exception for mediaPlayer.prepare()
:
> java.io.IOException: Prepare failed.: status=0x1 at
> android.media.MediaPlayer._prepare(Native Method) at
> android.media.MediaPlayer.prepare(MediaPlayer.java:1168) at
> com.messages.android.views.SeekBarLinearLayoutView.onClick(SeekBarLinearLayoutView.java:172)
> at android.view.View.performClick(View.java:4766) at
> android.view.View$PerformClick.run(View.java:19683) at
> android.os.Handler.handleCallback(Handler.java:739) at
> android.os.Handler.dispatchMessage(Handler.java:95) at
> android.os.Looper.loop(Looper.java:135) at
> android.app.ActivityThread.main(ActivityThread.java:5538) at
> java.lang.reflect.Method.invoke(Native Method) at
> java.lang.reflect.Method.invoke(Method.java:372) at
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
> at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
The exception only appears on our development phone Huawei ALE-L21. Two different Samsung phones and a different Huawei phone don't throw the exception.
Edit: I tried two different approaches, both didn't work out.
1.
FileInputStream fi = new FileInputStream(voiceMessage);
mediaPlayer.setDataSource(fi.getFD());
2.
voiceMessage.setReadable(true, false);
mediaPlayer.setDataSource(voiceMessage.getAbsolutePath());
Edit 3: So I tried something yesterday: I changed the file name of the voice message file from the broken device on the server side, so that the user on the broken device will download it's own voice message, which was previous uploaded to the server. Playing it's own voice message, even after downloading, works fine. So the problem should be the OutputFormat while recording, right? Is there an universal OutputFormat which works with Android 4.1+ for all devices?