MediaRecorder stop()失败 [英] MediaRecorder stop() failed
问题描述
我知道SO上已经有一些,但是它们中的任何一个都不能真正解决我的问题,但是当我运行代码并开始录制音频然后按我的停止按钮时,它总是会失败,因为它在错误的状态.我不确定如何解决此问题.
I know there are a few of these on SO already but none of them really were able to help my issue, but when I am running the code and start recording audio and then press my stop button it always fails because it is in the wrong state. I am not sure how I would go about fixing my states for this.
这是我的MainActivity.java代码:
Here is my MainActivity.java code:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.RadioGroup;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.IOException;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
public class MainActivity extends AppCompatActivity {
Button buttonStartRecording, buttonStopRecording, buttonPlayLastRecordAudio,
buttonStopPlayingRecording;
String AudioSavePathInDevice = null;
MediaRecorder mediaRecorder;
public static final int RequestPermissionCode = 1;
MediaPlayer mediaPlayer;
AudioManager audioManager;
boolean isAudioPlayInSameDevice = true;
// AudioRouter audioRouter;
RadioGroup mRadioGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStartRecording = (Button) findViewById(R.id.start_recording);
buttonStopRecording = (Button) findViewById(R.id.stop_rec);
buttonPlayLastRecordAudio = (Button) findViewById(R.id.play_last_rec);
buttonStopPlayingRecording = (Button) findViewById(R.id.stop_playing_btn);
// mRadioGroup = (RadioGroup) findViewById(R.id.radioGroup);
buttonStopRecording.setEnabled(false);
buttonPlayLastRecordAudio.setEnabled(false);
buttonStopPlayingRecording.setEnabled(false);
buttonStartRecording.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onClick(View view) {
// Check audio permission
if (checkPermission()) {
AudioSavePathInDevice =
Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "AudioRecording.3gp";
// Start Media recorder
MediaRecorderReady();
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
buttonStartRecording.setEnabled(false);
buttonStopRecording.setEnabled(true);
Toast.makeText(MainActivity.this, "Recording started",
Toast.LENGTH_LONG).show();
} else {
requestPermission();
}
}
});
buttonStopRecording.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
buttonStopRecording.setEnabled(false);
buttonPlayLastRecordAudio.setEnabled(true);
buttonStartRecording.setEnabled(true);
buttonStopPlayingRecording.setEnabled(false);
// Stop Media recorder
mediaRecorder.stop();
Toast.makeText(MainActivity.this, "Recording Completed",
Toast.LENGTH_LONG).show();
}
});
buttonPlayLastRecordAudio.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) throws IllegalArgumentException,
SecurityException, IllegalStateException {
int selectedId = 1;
if (selectedId == 1) {
isAudioPlayInSameDevice = true;
} else {
isAudioPlayInSameDevice = false;
}
// if you want to play audio on your Mobile speaker then set isAudioPlayInSameDevice true
// and if you want to play audio to connected device then set isAudioPlayInSameDevice false.
if (isAudioPlayInSameDevice) {
audioManager.setMode(audioManager.STREAM_MUSIC);
audioManager.setSpeakerphoneOn(true);
} else {
audioManager.setSpeakerphoneOn(false);
audioManager.setMode(audioManager.MODE_NORMAL);
}
audioManager.setBluetoothScoOn(false);
audioManager.stopBluetoothSco();
buttonStopRecording.setEnabled(false);
buttonStartRecording.setEnabled(false);
buttonStopPlayingRecording.setEnabled(true);
mediaPlayer = new MediaPlayer();
try {
// Start media player
System.out.println("Recorded Audio Path-" + AudioSavePathInDevice);
mediaPlayer.setDataSource(AudioSavePathInDevice);
if (isAudioPlayInSameDevice) {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(MainActivity.this, "Recording Playing",
Toast.LENGTH_LONG).show();
}
});
buttonStopPlayingRecording.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
buttonStopRecording.setEnabled(false);
buttonStartRecording.setEnabled(true);
buttonStopPlayingRecording.setEnabled(false);
buttonPlayLastRecordAudio.setEnabled(true);
if (mediaPlayer != null) {
// Stop Media Player
mediaPlayer.stop();
mediaPlayer.release();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
MediaRecorderReady();
}
}
}
});
}
private BroadcastReceiver mBluetoothScoReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
System.out.println("ANDROID Audio SCO state: " + state);
if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
/*
* Now the connection has been established to the bluetooth device.
* Record audio or whatever (on another thread).With AudioRecord you can record with an object created like this:
* new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
* AudioFormat.ENCODING_PCM_16BIT, audioBufferSize);
*
* After finishing, don't forget to unregister this receiver and
* to stop the bluetooth connection with am.stopBluetoothSco();
*/
}
}
};
@RequiresApi(api = Build.VERSION_CODES.O)
public void MediaRecorderReady() {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
mediaRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder.setOutputFile(AudioSavePathInDevice);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
registerReceiver(mBluetoothScoReceiver, intentFilter);
audioManager = (AudioManager) getApplicationContext().getSystemService(getApplicationContext().AUDIO_SERVICE);
// Start Bluetooth SCO.
audioManager.setMode(audioManager.MODE_NORMAL);
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
// Stop Speaker.
audioManager.setSpeakerphoneOn(false);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBluetoothScoReceiver);
// Stop Bluetooth SCO.
audioManager.stopBluetoothSco();
audioManager.setMode(audioManager.MODE_NORMAL);
audioManager.setBluetoothScoOn(false);
// Start Speaker.
audioManager.setSpeakerphoneOn(true);
}
private void requestPermission() {
ActivityCompat.requestPermissions(MainActivity.this, new
String[]{WRITE_EXTERNAL_STORAGE, RECORD_AUDIO}, RequestPermissionCode);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case RequestPermissionCode:
if (grantResults.length > 0) {
boolean StoragePermission = grantResults[0] ==
PackageManager.PERMISSION_GRANTED;
boolean RecordPermission = grantResults[1] ==
PackageManager.PERMISSION_GRANTED;
// if (StoragePermission && RecordPermission) {
// Toast.makeText(BluetoothAudioRecorder.this, "Permission Granted",
// Toast.LENGTH_LONG).show();
// } else {
// Toast.makeText(BluetoothAudioRecorder.this,"Permission Denied",Toast.LENGTH_LONG).show();
// }
}
break;
}
}
public boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(getApplicationContext(),
WRITE_EXTERNAL_STORAGE);
int result1 = ContextCompat.checkSelfPermission(getApplicationContext(),
RECORD_AUDIO);
return result == PackageManager.PERMISSION_GRANTED &&
result1 == PackageManager.PERMISSION_GRANTED;
}
}
然后是发生错误的时间:
And then my logcat of when the error occurs:
2019-11-24 11:26:54.440 29627-29683/com.example.esense_application E/libc: Access denied finding property "vendor.gralloc.disable_ahardware_buffer"
2019-11-24 11:26:54.435 29627-29627/com.example.esense_application W/RenderThread: type=1400 audit(0.0:17779): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=24699 scontext=u:r:untrusted_app:s0:c7,c257,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
2019-11-24 11:26:54.487 29627-29627/com.example.esense_application I/System.out: ANDROID Audio SCO state: 1
2019-11-24 11:26:54.487 29627-29627/com.example.esense_application I/System.out: ANDROID Audio SCO state: 2
2019-11-24 11:26:54.868 29627-29627/com.example.esense_application I/System.out: ANDROID Audio SCO state: 1
2019-11-24 11:26:57.769 29627-29627/com.example.esense_application I/System.out: ANDROID Audio SCO state: 1
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: java.io.FileNotFoundException: /storage/emulated/0/AudioRecording.3gp: open failed: EACCES (Permission denied)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at libcore.io.IoBridge.open(IoBridge.java:496)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at java.io.RandomAccessFile.<init>(RandomAccessFile.java:289)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at java.io.RandomAccessFile.<init>(RandomAccessFile.java:152)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at android.media.MediaRecorder.prepare(MediaRecorder.java:1046)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at com.example.esense_application.MainActivity$1.onClick(MainActivity.java:67)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at android.view.View.performClick(View.java:7140)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at android.view.View.performClickInternal(View.java:7117)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at android.view.View.access$3500(View.java:801)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at android.view.View$PerformClick.run(View.java:27351)
2019-11-24 11:27:00.647 29627-29627/com.example.esense_application W/System.err: at android.os.Handler.handleCallback(Handler.java:883)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at android.os.Handler.dispatchMessage(Handler.java:100)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at android.os.Looper.loop(Looper.java:214)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7356)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at libcore.io.Linux.open(Native Method)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: at libcore.io.IoBridge.open(IoBridge.java:482)
2019-11-24 11:27:00.648 29627-29627/com.example.esense_application W/System.err: ... 15 more
2019-11-24 11:27:03.528 29627-29627/com.example.esense_application E/MediaRecorder: stop called in an invalid state: 4
2019-11-24 11:27:03.528 29627-29627/com.example.esense_application D/AndroidRuntime: Shutting down VM
2019-11-24 11:27:03.529 29627-29627/com.example.esense_application E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.esense_application, PID: 29627
java.lang.IllegalStateException
at android.media.MediaRecorder.stop(Native Method)
at com.example.esense_application.MainActivity$2.onClick(MainActivity.java:98)
at android.view.View.performClick(View.java:7140)
at android.view.View.performClickInternal(View.java:7117)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27351)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2019-11-24 11:27:03.540 29627-29627/com.example.esense_application I/Process: Sending signal. PID: 29627 SIG: 9
推荐答案
当您尝试 stop()
时,您的 MediaRecorder
正在抛出,因为它从未进入<一个href ="https://developer.android.com/reference/android/media/MediaRecorder.html" rel ="nofollow noreferrer">正在录制" 状态.实际上,它甚至从未进入准备"状态,因为对 prepare()
的调用未成功完成.
Your MediaRecorder
is throwing when you try to stop()
it because it has never entered the "recording" state. In fact, it never even entered the "prepared" state, because your call to prepare()
did not complete successfully.
解决方案
-
在返回
prepare()
调用(无抛出)之前,不允许调用start().
Do not allow a call to start() until the
prepare()
call has returned (without throwing).
在 start()
调用返回(无抛出)之前,不允许调用stop().
Do not allow a call to stop() until the start()
call has returned (without throwing).
确保为输出文件选择了有效位置.尝试使用 getExternalFilesDir(null)
而不是 Environment.getExternalStorageDirectory()
.错误的文件路径是您的 prepare()
调用当前以 EACCESS
失败的原因.
Make sure you have chosen a valid location for your output file. Try using getExternalFilesDir( null )
instead of Environment.getExternalStorageDirectory()
. The bad file path is the reason your prepare()
call is currently failing with an EACCESS
.
如您所见,吞没异常而没有解决其根本原因(即仅执行 e.printStackTrace()
并继续进行),即使在所使用的粗糙代码中,也可能迅速导致问题.用于学习/实验.如果要添加异常处理程序,最好提供真正的错误处理-始终确保您了解为什么会引发异常.
As you can see, swallowing exceptions without addressing their root cause (i.e., just doing a e.printStackTrace()
and carrying on), can rapidly lead to problems -- even in rough code used for learning/experimentation. If you are going to add an exception handler, it is better to provide real error handling -- and always make sure you understand why an exception is being thrown.
这篇关于MediaRecorder stop()失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!