简体   繁体   中英

Android MediaRecorder is not working and crashes on stop() method

I'm learning android development and i'm using MediaRecorder class for recording audio. And the logcat says that the app crashes in the stop() method and it throws IllegalStateException. I don't understand why it crashes, and i call the method stop before start.

public class MainActivity extends AppCompatActivity {

private MediaRecorder grabacion;
private String archivoSalida = null;
private Button btn_recorder;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btn_recorder = (Button)findViewById(R.id.btn_rec);

    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO,}, 1000);
    }
}

public void Recorder(View view){
    if(grabacion == null){
        archivoSalida = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Grabacion.mp3";
        grabacion = new MediaRecorder();
        grabacion.setAudioSource(MediaRecorder.AudioSource.MIC);
        grabacion.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        grabacion.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
        grabacion.setOutputFile(archivoSalida);

        try{
            grabacion.prepare();
            grabacion.start();
        } catch (IOException e){
        }

        btn_recorder.setBackgroundResource(R.drawable.rec);
        Toast.makeText(getApplicationContext(), "Grabando...", Toast.LENGTH_SHORT).show();
    } else if(grabacion != null){
        grabacion.stop();
        grabacion.release();
        grabacion = null;
        btn_recorder.setBackgroundResource(R.drawable.stop_rec);
        Toast.makeText(getApplicationContext(), "Grabación finalizada", Toast.LENGTH_SHORT).show();
    }
}

public void reproducir(View view) {

    MediaPlayer mediaPlayer = new MediaPlayer();
    try {
        mediaPlayer.setDataSource(archivoSalida);
        mediaPlayer.prepare();
    } catch (IOException e){
    }

    mediaPlayer.start();
    Toast.makeText(getApplicationContext(), "Reproduciendo audio", Toast.LENGTH_SHORT).show();
}}

This is the manifest file:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
And what logcat says:
 E/MediaRecorder: stop called in an invalid state: 4 D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.recorder, PID: 5386 java.lang.IllegalStateException: Could not execute method for android:onClick at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:414) at android.view.View.performClick(View.java:7870) at android.widget.TextView.performClick(TextView.java:14970) at android.view.View.performClickInternal(View.java:7839) at android.view.View.access$3600(View.java:886) at android.view.View$PerformClick.run(View.java:29363) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:237) at android.app.ActivityThread.main(ActivityThread.java:7948) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409) at android.view.View.performClick(View.java:7870)  at android.widget.TextView.performClick(TextView.java:14970)  at android.view.View.performClickInternal(View.java:7839)  at android.view.View.access$3600(View.java:886)  at android.view.View$PerformClick.run(View.java:29363)  at android.os.Handler.handleCallback(Handler.java:883)  at android.os.Handler.dispatchMessage(Handler.java:100)  at android.os.Looper.loop(Looper.java:237)  at android.app.ActivityThread.main(ActivityThread.java:7948)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)  Caused by: java.lang.IllegalStateException at android.media.MediaRecorder._stop(Native Method) at android.media.MediaRecorder.stop(MediaRecorder.java:1440) at com.example.recorder.MainActivity.Recorder(MainActivity.java:55) at java.lang.reflect.Method.invoke(Native Method)  at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)  at android.view.View.performClick(View.java:7870)  at android.widget.TextView.performClick(TextView.java:14970)  at android.view.View.performClickInternal(View.java:7839)  at android.view.View.access$3600(View.java:886)  at android.view.View$PerformClick.run(View.java:29363)  at android.os.Handler.handleCallback(Handler.java:883)  at android.os.Handler.dispatchMessage(Handler.java:100)  at android.os.Looper.loop(Looper.java:237)  at android.app.ActivityThread.main(ActivityThread.java:7948)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)  I/Process: Sending signal. PID: 5386 SIG: 9

Thanks!

The documentation for the stop() method states that it will throw an IllegalStateException

if it is called before start()

Since this seems to be the only time this error will be thrown this is most likely what's happening in your case as well.

Take a look at your Recorder() method. The only time stop() will be called is when your variable is not null. This means that your instance got initialized correctly. However, since the exception is thrown it means that even though your variable is referencing an instance of MediaRecorder , it wasn't started.

To find out why, take a look at the code that's supposed to start your MediaRecorder :

    try {
        grabacion.prepare();
        grabacion.start();
    } catch (IOException e){
    }

While it is placed inside a try-catch construct, the catch block doesn't actually contain any code, causing any errors to simply be ignored. Therefore, the problem you're having is a result of either grabacion.prepare(); or grabacion.start(); not succeeding which causes the recorder to not be started.

Given that start() only throws an IllegalStateException as per its documentation , the call to prepare() should be the cause of the problem. This also matches my own experience, since there's a lot that can go wrong when calling prepare() . Here's what it does based on its description in the docs :

Prepares the recorder to begin capturing and encoding data. This method must be called after setting up the desired audio and video sources, encoders, file format, etc., but before start().

So, as you can tell, it's not easy to pinpoint the exact cause for me right now. However, something I may add is that you used Environment.getExternalStorageDirectory() which is deprecated as of API 29 to improve user privacy. While this might be the issue in your case, I can't confirm it with complete certainty.

To find out precisely what's causing the error you should make use of that IOException you're getting in that try-catch. You could, for example log its stack trace to find out more about the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM