MediaRecorder stop()失败

问题描述 投票:0回答:1

我知道已经有一些在SO上了,但是它们中的任何一个都无法真正解决我的问题,但是当我运行代码并开始录制音频然后按我的停止按钮时,它总是会失败,因为它在错误的状态。我不确定如何解决此问题。

这是我的MainActivity.java代码:

    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;
    }
}

然后是发生错误时的日志:

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
java android android-mediaplayer android-mediarecorder
1个回答
0
投票

您尝试MediaRecorder时抛出stop(),因为它从未进入"recording"状态。实际上,它甚至从未进入“准备”状态,因为您对prepare()的调用未成功完成。

SOLUTION

  • 在返回prepare()调用之前(不引发),不允许调用start()。

  • 在返回start()调用之前(不允许抛出),不允许调用stop()。

  • 请确保您为输出文件选择了有效位置。尝试使用getExternalFilesDir( null )而不是getExternalFilesDir( null )。文件路径错误是Environment.getExternalStorageDirectory()调用当前失败并显示prepare()的原因。

如您所见,吞没异常而不解决其根本原因(即仅执行EACCESS并继续进行),即使在用于学习/实验的粗糙代码中,也可能迅速导致问题。如果要添加异常处理程序,最好提供真正的错误处理-始终确保您了解为什么会引发异常。

© www.soinside.com 2019 - 2024. All rights reserved.