MediaRecorder stop()失败 [英] MediaRecorder stop() failed

查看:179
本文介绍了MediaRecorder stop()失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆