Record sound in Android and read Amplitude

巧了我就是萌 提交于 2019-12-13 11:34:41

问题


I'm trying to make an app that records sound for a second and then reads the maximum amplitude from the recorded sound. This is what I have so far but my app crashes and I can't figure out why.

This is my second activity, which I'm calling from my first after I press a "Record" button. The app crashes on my emulator and on my phone.

package radu.soundSampler;

import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import android.media.MediaRecorder;

public class DisplayMessageActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //Intent intent = getIntent();
    //String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

    MediaRecorder rec = new MediaRecorder();
    rec.setAudioSource(MediaRecorder.AudioSource.MIC);
    rec.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
    rec.setOutputFile("/newRecording");
    rec.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

    try {
        rec.prepare();
    } catch (IllegalStateException e) {

    } catch (IOException o) {

    }
    rec.start();
            for(int i=0;i<100000;i++);
    rec.stop();
    int rezultat = rec.getMaxAmplitude();

    TextView textView = new TextView(this);
    textView.setTextSize(40);

    textView.setText(Integer.toString(rezultat));

    setContentView(textView);
}

}

The (updated) error log on my computer says:

08-18 13:30:07.968: E/MediaRecorder(687): start called in an invalid state: 4
08-18 13:30:07.968: D/AndroidRuntime(687): Shutting down VM
08-18 13:30:07.968: W/dalvikvm(687): threadid=1: thread exiting with uncaught exception (group=0x40015560)
08-18 13:30:07.978: E/AndroidRuntime(687): FATAL EXCEPTION: main
08-18 13:30:07.978: E/AndroidRuntime(687): java.lang.RuntimeException: Unable to start activity ComponentInfo{radu.soundSampler/radu.soundSampler.DisplayMessageActivity}: java.lang.IllegalStateException
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.os.Handler.dispatchMessage(Handler.java:99)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.os.Looper.loop(Looper.java:123)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.app.ActivityThread.main(ActivityThread.java:3683)
08-18 13:30:07.978: E/AndroidRuntime(687):  at java.lang.reflect.Method.invokeNative(Native Method)
08-18 13:30:07.978: E/AndroidRuntime(687):  at java.lang.reflect.Method.invoke(Method.java:507)
08-18 13:30:07.978: E/AndroidRuntime(687):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-18 13:30:07.978: E/AndroidRuntime(687):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-18 13:30:07.978: E/AndroidRuntime(687):  at dalvik.system.NativeStart.main(Native Method)
08-18 13:30:07.978: E/AndroidRuntime(687): Caused by: java.lang.IllegalStateException
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.media.MediaRecorder.start(Native Method)
08-18 13:30:07.978: E/AndroidRuntime(687):  at radu.soundSampler.DisplayMessageActivity.onCreate(DisplayMessageActivity.java:29)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-18 13:30:07.978: E/AndroidRuntime(687):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-18 13:30:07.978: E/AndroidRuntime(687):  ... 11 more

so I've thought maybe the emulator can't "run" a microphone, so I installed the .apk on my phone but it crashed there too. I don't know what could be the problem, so could you please help me, and/or give me any hints?

Thanks a lot in advance!

One more stack trace, the one you requested. I used in the catch statements o.printStackTrace() and e.printStackTrace(), I hope it's what you requested me to do:

08-18 14:06:11.908: W/System.err(811): java.io.FileNotFoundException: /newRecording (Read-only file system)
08-18 14:06:11.908: W/System.err(811):  at org.apache.harmony.luni.platform.OSFileSystem.open(Native Method)
08-18 14:06:11.908: W/System.err(811):  at dalvik.system.BlockGuard$WrappedFileSystem.open(BlockGuard.java:232)
08-18 14:06:11.918: W/System.err(811):  at java.io.FileOutputStream.<init>(FileOutputStream.java:94)
08-18 14:06:11.918: W/System.err(811):  at java.io.FileOutputStream.<init>(FileOutputStream.java:165)
08-18 14:06:11.918: W/System.err(811):  at java.io.FileOutputStream.<init>(FileOutputStream.java:144)
08-18 14:06:11.918: W/System.err(811):  at android.media.MediaRecorder.prepare(MediaRecorder.java:533)
08-18 14:06:11.918: W/System.err(811):  at radu.soundSampler.DisplayMessageActivity.onCreate(DisplayMessageActivity.java:23)
08-18 14:06:11.918: W/System.err(811):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-18 14:06:11.918: W/System.err(811):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-18 14:06:11.918: W/System.err(811):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-18 14:06:11.918: W/System.err(811):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-18 14:06:11.918: W/System.err(811):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
08-18 14:06:11.918: W/System.err(811):  at android.os.Handler.dispatchMessage(Handler.java:99)
08-18 14:06:11.918: W/System.err(811):  at android.os.Looper.loop(Looper.java:123)
08-18 14:06:11.918: W/System.err(811):  at android.app.ActivityThread.main(ActivityThread.java:3683)
08-18 14:06:11.918: W/System.err(811):  at java.lang.reflect.Method.invokeNative(Native Method)
08-18 14:06:11.928: W/System.err(811):  at java.lang.reflect.Method.invoke(Method.java:507)
08-18 14:06:11.928: W/System.err(811):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-18 14:06:11.928: W/System.err(811):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-18 14:06:11.928: W/System.err(811):  at dalvik.system.NativeStart.main(Native Method)
08-18 14:06:11.928: E/MediaRecorder(811): start called in an invalid state: 4
08-18 14:06:11.928: D/AndroidRuntime(811): Shutting down VM
08-18 14:06:11.928: W/dalvikvm(811): threadid=1: thread exiting with uncaught exception (group=0x40015560)
08-18 14:06:11.948: E/AndroidRuntime(811): FATAL EXCEPTION: main
08-18 14:06:11.948: E/AndroidRuntime(811): java.lang.RuntimeException: Unable to start activity ComponentInfo{radu.soundSampler/radu.soundSampler.DisplayMessageActivity}: java.lang.IllegalStateException
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.os.Handler.dispatchMessage(Handler.java:99)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.os.Looper.loop(Looper.java:123)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.app.ActivityThread.main(ActivityThread.java:3683)
08-18 14:06:11.948: E/AndroidRuntime(811):  at java.lang.reflect.Method.invokeNative(Native Method)
08-18 14:06:11.948: E/AndroidRuntime(811):  at java.lang.reflect.Method.invoke(Method.java:507)
08-18 14:06:11.948: E/AndroidRuntime(811):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-18 14:06:11.948: E/AndroidRuntime(811):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-18 14:06:11.948: E/AndroidRuntime(811):  at dalvik.system.NativeStart.main(Native Method)
08-18 14:06:11.948: E/AndroidRuntime(811): Caused by: java.lang.IllegalStateException
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.media.MediaRecorder.start(Native Method)
08-18 14:06:11.948: E/AndroidRuntime(811):  at radu.soundSampler.DisplayMessageActivity.onCreate(DisplayMessageActivity.java:30)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-18 14:06:11.948: E/AndroidRuntime(811):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-18 14:06:11.948: E/AndroidRuntime(811):  ... 11 more
08-18 14:06:14.181: I/Process(811): Sending signal. PID: 811 SIG: 9

回答1:


Use setOutoutFile(getExternalFilesDir().getAbsolutePath() + "/newRecording")

Make sure you have this permission in your manifest

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

Don't do the busy-wait loop. Use a timer.

Don't ignore exceptions in prepare.




回答2:


If you simply want to record the "volume" of the microphone, then you could redirect output to null, like this:

recorder = new MediaRecorder();
// following calls throw Illegal State Exceptions, but here we follow the proper order

recorder.setAudioSource(AudioSource.MIC);

// After set audio source
recorder.setOutputFormat(OutputFormat.THREE_GPP);

// After set output format
recorder.setAudioEncoder(AudioEncoder.AMR_NB);
recorder.setOutputFile("/dev/null");
// Before prepare

try {
    recorder.prepare();
} catch (IOException e) {
    System.err.println(e);
}
// After prepare
recorder.start();

// Call getMaxAmplitude() with a zero returned value, so you can recall later
recorder.getMaxAmplitude();

Also, you shouldn't make a fake delay inside onCreate. Use a handler, instead:

public void onCreate(Bundle savedInstanceState) {

    // ...

    handler = new Handler();
    handler.postDelayed(this, 1000);
}

public void run() {
    int value = recorder.getMaxAmplitude();
    recorder.stop();

    // etc
}



回答3:


Try it this way.....

    int rezultat = 0;   

try {
        rec.prepare();

        rec.start();

        TimeUnit.SECONDS.sleep(1);  

        rec.stop();

    } catch (IllegalStateException e) {

    } catch (IOException o) {

    } catch (InterruptedException e) {      

    }

     rezultat = rec.getMaxAmplitude();



回答4:


First, you need to put your record in a place where you are allowed to write.

File parent = getContext().getFilesDir();
File recordFile = new File(parent, "newRecording");

is a correct start. (there are other)




回答5:


You can't create a file in the root file system as you are trying by using rec.setOutputFile("/newRecording"). Create a temporary file and write it there. You might want to check the methods to get the private file directory getFilesDir() and related.

The exception you got tells you exactly this: The FileNotFoundException occurs and shows you that the prepare() call has failed. And thus you the MediaRecoder is not prepared and you won't be able to start() as it is in the wrong state.

Another comment: To wait a second before stopping recording, use Thread.sleep() and not a for loop counting to whatever. Second, please do it in a background thread as blocking the UI thread in any way might make your UI sluggish, and in the worst case, Android might kill your application with an ANR exception.




回答6:


Your activity crashes because an Exception is thrown in the onCreate() method. You should absolutely avoid this situation to happen. Call your prepare() method (or any method that is not purely related to the activity's initialization) from a separate thread, and always show debug message in catch blocks.

As a rule of the thumb : never write an empty catch {} block. You will always regret it afterwards (believe me)




回答7:


Salut!

You're problem might be because you're not using the correct directory on Android. As I can see, you are using \ which is the root directory and it is of course read-only.

To solve this, you can add the external storage path to your file like this:

String externalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;

// Your code here

rec.setOutputFile(externalStoragePath + "newRecording");

This should solve the problem. Please leave a comment if it doesn't work.

P.S. Put a break point at the top of onCreate() and debug your app to see exactly where it fails.



来源:https://stackoverflow.com/questions/12018794/record-sound-in-android-and-read-amplitude

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!