Записать звук в Android и прочитать амплитуду
Я пытаюсь сделать приложение, которое записывает звук на секунду, а затем считывает максимальную амплитуду из записанного звука. Это то, что у меня есть, но мое приложение падает, и я не могу понять, почему.
Это мое второе занятие, которому я звоню с первого после нажатия кнопки "Запись". Приложение вылетает на моем эмуляторе и на моем телефоне.
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);
}
}
(Обновленный) журнал ошибок на моем компьютере говорит:
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
поэтому я подумал, что эмулятор не может "запустить" микрофон, поэтому я установил .apk
на моем телефоне, но он тоже там разбился. Я не знаю, в чем может быть проблема, поэтому не могли бы вы помочь мне и / или дать мне какие-нибудь советы?
Заранее большое спасибо!
Еще одна трассировка стека, та, которую вы запросили. Я использовал в операторах catch o.printStackTrace()
а также e.printStackTrace()
Надеюсь, это то, что вы просили меня сделать:
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
7 ответов
Использование setOutoutFile(getExternalFilesDir().getAbsolutePath() + "/newRecording")
Убедитесь, что у вас есть это разрешение в вашем манифесте
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Не делайте цикл занятого ожидания. Используйте таймер.
Не игнорируйте исключения в подготовке.
Если вы просто хотите записать "громкость" микрофона, вы можете перенаправить вывод на null
, как это:
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();
Кроме того, вы не должны делать ложную задержку внутри onCreate
, Вместо этого используйте обработчик:
public void onCreate(Bundle savedInstanceState) {
// ...
handler = new Handler();
handler.postDelayed(this, 1000);
}
public void run() {
int value = recorder.getMaxAmplitude();
recorder.stop();
// etc
}
Попробуйте это так.....
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();
Во-первых, вы должны поместить свою запись в место, где вам разрешено писать.
File parent = getContext().getFilesDir();
File recordFile = new File(parent, "newRecording");
это правильное начало. (Есть и другие)
Вы не можете создать файл в корневой файловой системе, как вы пытаетесь с помощью rec.setOutputFile("/newRecording")
, Создайте временный файл и запишите его там. Возможно, вы захотите проверить методы, чтобы получить частный каталог файлов getFilesDir() и связанный с ним.
Исключение, которое вы получили, говорит вам именно это: FileNotFoundException
происходит и показывает вам, что prepare()
звонок не удался. И, таким образом, вы MediaRecoder
не подготовлен, и вы не сможете start()
как это не в том состоянии.
Еще один комментарий: чтобы подождать секунду, прежде чем остановить запись, используйте Thread.sleep()
и не for
Подсчет петель к чему угодно. Во-вторых, пожалуйста, сделайте это в фоновом потоке, поскольку блокировка потока пользовательского интерфейса может каким-либо образом замедлить ваш пользовательский интерфейс, а в худшем случае Android может убить ваше приложение с исключением ANR.
Салют!
Возможно, проблема в том, что вы не используете правильный каталог на Android. Как я вижу, вы используете \
который является корневым каталогом и, конечно, доступен только для чтения.
Чтобы решить эту проблему, вы можете добавить путь к внешнему хранилищу в ваш файл следующим образом:
String externalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
// Your code here
rec.setOutputFile(externalStoragePath + "newRecording");
Это должно решить проблему. Пожалуйста, оставьте комментарий, если он не работает.
PS Поставьте точку останова на вершине onCreate()
и отладить ваше приложение, чтобы увидеть, где именно оно не работает.
Ваша активность падает, потому что в методе onCreate() создается исключение. Вы должны абсолютно избежать этой ситуации. Вызовите метод prepare() (или любой метод, который не связан исключительно с инициализацией действия) из отдельного потока и всегда отображайте сообщение отладки в блоках перехвата.
Как правило: никогда не пишите пустой блок catch {}. Вы всегда будете сожалеть об этом потом (поверьте мне)