MediaRecorder在无效状态下调用start:4 || E/AudioRecording:prepare() 失败

huangapple go评论78阅读模式
英文:

MediaRecorder start called in invalid state: 4 || E/AudioRecording: prepare() failed

问题

public class MainActivity extends AppCompatActivity{
    // ... (other imports and variable declarations)
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recordbtn = (ImageButton)findViewById(R.id.record);
        stopbtn = (ImageButton)findViewById(R.id.stopRecord);
        playbtn = (ImageButton)findViewById(R.id.play);
        stopplay = (ImageButton)findViewById(R.id.stopplay);
        pausebtn = (ImageButton)findViewById(R.id.pause);
        // ... (other initialization code)
        
        recordbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ... (recording button click logic)
            }
        });
        
        stopbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ... (stop recording button click logic)
            }
        });
        
        playbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ... (play button click logic)
            }
        });
        
        pausebtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ... (pause button click logic)
            }
        });
        
        stopplay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ... (stop playback button click logic)
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        // ... (permission request result handling)
    }
    
    public boolean CheckPermissions() {
        // ... (permission check logic)
    }
    
    private void RequestPermissions() {
        // ... (permission request logic)
    }
}

Please note that I've removed the comments, URLs, and log information, and provided only the translated Java code related to your MainActivity.

英文:

I'm with a big problem in my Record Audio App, and I read every post related to it in this site, and tryied every solution suggested, but didn't solved my problem. My app works fine in all Android versions from AndroidQ 10.0(SDK29) and bellow, and this problems only appears at version 10.0+, specifically in SDK30. Does anyone knows how to solve it, or maybe, have any idea about what is causing this bug?
<br>
Here is a print of the log: https://imgur.com/a/xSATHSp<br>
The Manifest: https://imgur.com/a/T6eEGmb<br>
The Code(line76): https://imgur.com/a/lrmlB58<br>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------<br>
I also tryied other solutions from another foruns, like this one, in the section "What could go wrong?" at subtopic "java.lang.IllegalStateException": https://www.grokkingandroid.com/recording-audio-using-androids-mediarecorder-framework/<br><br>
------------------------------------------------------------------------------------------------------------------------------------------------------------------------<br><br>
My log exception:

E/AudioRecording: prepare() failed
E/MediaRecorder: start called in an invalid state: 4
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myfetus, PID: 17985
java.lang.IllegalStateException
at android.media.MediaRecorder.start(Native Method)
at com.example.myfetus.MainActivity$1.onClick(MainActivity.java:81)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

<br>My ActivityMain code:


public class MainActivity extends AppCompatActivity{
    private ImageButton recordbtn, stopbtn, playbtn, stopplay, pausebtn;
    private MediaRecorder mRecorder;
    private MediaPlayer mPlayer;
    private static final String LOG_TAG = &quot;AudioRecording&quot;;
    private static String mFileName = null;
    public static final int REQUEST_AUDIO_PERMISSION_CODE = 1;
    private int buttonState = 0;
    private EditText editsenha1;
    private TextView test1;
    private ImageView editImagem;
    private int i=0;
    Date createdTime = new Date();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recordbtn = (ImageButton)findViewById(R.id.record);
        stopbtn = (ImageButton)findViewById(R.id.stopRecord);
        playbtn = (ImageButton)findViewById(R.id.play);
        stopplay = (ImageButton)findViewById(R.id.stopplay);
        pausebtn = (ImageButton)findViewById(R.id.pause);
        stopbtn.setEnabled(false);
        playbtn.setEnabled(false);
        stopplay.setEnabled(false);

        mFileName = (Environment.getExternalStorageDirectory().getAbsolutePath() + &quot;/&quot; + &quot;MyFetus&quot; +createdTime + &quot;Audio.m4a&quot;).replaceAll(&quot; &quot;, &quot;_&quot;).replaceAll(&quot;:&quot;, &quot;-&quot;);
        test1 = findViewById(R.id.texto2);
         editImagem = findViewById(R.id.imageView4);

        recordbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                    if (CheckPermissions()) {
                        stopbtn.setEnabled(true);
                        recordbtn.setEnabled(false);
                        playbtn.setEnabled(false);
                        stopplay.setEnabled(false);
                        pausebtn.setEnabled(false);
                        mRecorder = new MediaRecorder();
                        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
                        mRecorder.setAudioEncodingBitRate(128000);
                        mRecorder.setAudioSamplingRate(44100);
                        mRecorder.setOutputFile(mFileName);
                        try {
                            mRecorder.prepare();

                        } catch (IOException e) {
                            Log.e(LOG_TAG, &quot;prepare() failed&quot;);
                        }
                        mRecorder.start();
                        Toast.makeText(getApplicationContext(), &quot;Recording Started&quot;, Toast.LENGTH_LONG).show();
                        test1.setText(&quot;Gravando...&quot;);
                        test1.setTextColor(Color.parseColor(&quot;#0af263&quot;));
                    } else {
                        RequestPermissions();
                    }
                    recordbtn.setVisibility(View.INVISIBLE);
                    stopbtn.setVisibility(View.VISIBLE);
                }


        });
        stopbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopbtn.setEnabled(false);
                recordbtn.setEnabled(true);
                playbtn.setEnabled(true);
                stopplay.setEnabled(true);
                pausebtn.setEnabled(true);
                mRecorder.stop();
                mRecorder.release();
                mRecorder = null;
                Toast.makeText(getApplicationContext(), &quot;Recording Stopped&quot;, Toast.LENGTH_LONG).show();
                test1.setText(&quot;Aperte para gravar&quot;);
                test1.setTextColor(Color.parseColor(&quot;#FADCEE&quot;));
                stopbtn.setVisibility(View.INVISIBLE);
                recordbtn.setVisibility(View.VISIBLE);
            }
        });
        playbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopbtn.setEnabled(false);
                recordbtn.setEnabled(true);
                playbtn.setEnabled(false);
                stopplay.setEnabled(true);
                pausebtn.setEnabled(true);
                mPlayer = new MediaPlayer();
                try {
                    mPlayer.setDataSource(mFileName);
                    mPlayer.prepare();
                    mPlayer.start();
                    Toast.makeText(getApplicationContext(), &quot;Recording Started Playing&quot;, Toast.LENGTH_LONG).show();
                } catch (IOException e) {
                    Log.e(LOG_TAG, &quot;prepare() failed&quot;);
                }
            }
        });
        pausebtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mPlayer!=null){
                mPlayer.pause();
                stopbtn.setEnabled(true);
                recordbtn.setEnabled(true);
                playbtn.setEnabled(true);
                stopplay.setEnabled(true);
                pausebtn.setEnabled(false);
                Toast.makeText(getApplicationContext(),&quot;Audio Paused&quot;, Toast.LENGTH_SHORT).show();}
            }
        });
        stopplay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPlayer.release();
                mPlayer = null;
                stopbtn.setEnabled(false);
                recordbtn.setEnabled(true);
                playbtn.setEnabled(true);
                stopplay.setEnabled(false);
                pausebtn.setEnabled(true);
                Toast.makeText(getApplicationContext(),&quot;Audio Stopped&quot;, Toast.LENGTH_SHORT).show();
            }
        });


    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_AUDIO_PERMISSION_CODE:
                if (grantResults.length&gt; 0) {
                    boolean permissionToRecord = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                    boolean permissionToStore = grantResults[1] ==  PackageManager.PERMISSION_GRANTED;
                    if (permissionToRecord &amp;&amp; permissionToStore) {
                        Toast.makeText(getApplicationContext(), &quot;Permission Granted&quot;, Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(getApplicationContext(),&quot;Permission Denied&quot;,Toast.LENGTH_LONG).show();
                    }
                }
                break;
        }
    }
    public boolean CheckPermissions() {
        int result = ContextCompat.checkSelfPermission(getApplicationContext(), WRITE_EXTERNAL_STORAGE);
        int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), RECORD_AUDIO);
        return result == PackageManager.PERMISSION_GRANTED &amp;&amp; result1 == PackageManager.PERMISSION_GRANTED;
    }
    private void RequestPermissions() {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{RECORD_AUDIO, WRITE_EXTERNAL_STORAGE}, REQUEST_AUDIO_PERMISSION_CODE);
    }
}

答案1

得分: 1

你在 Android 10 及更高版本上遇到的问题是,你无法再访问外部 SD 卡上的文件。你必须使用存储访问框架(Storage Access Framework)先创建一个文件,然后将其用作存储的基础,或者仅使用应用程序的私有存储空间。

或者,在我个人看来,更好的方法是使用 MediaStore 内容提供程序。有关如何向 MediaStore 添加文件的更多详细信息,请参阅官方文档中的如何向 MediaStore 添加文件

如果你使用 MediaStore,就不能再使用 setOutputFile() 了。请改为使用从 MediaStore 内容提供程序获取的 FileDescriptor,并使用 setOutputFileDescriptor()

英文:

The problem you are facing with Android 10 upwards is, that you cannot access files on the external SD card anymore. You have to use either the Storage Access Framework to create a file first and then use it as a base for storing, or you only use app private storage.

Or - IMHO better in this case - you use the MediaStore content provider. See the official docs for more details about how to add files to MediaStore.

If you use MediaStore you canot use setOutputfile() anymore. Use setOutputFileDescriptor()instead with the FileDescriptor you can get from the MediaStore content provider.

huangapple
  • 本文由 发表于 2020年10月19日 10:15:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/64420267.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定