【问题标题】:java.lang.RuntimeException: start failedjava.lang.RuntimeException:启动失败
【发布时间】:2014-11-17 12:59:47
【问题描述】:

我正在尝试使用 MediaRecorder 在我的一项活动中录制音频。部分代码如下所示。

File file = new File(AppConstants.MSGS_DIR, filename);
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(AudioSource.MIC);
recorder.setOutputFormat(OutputFormat.THREE_GPP);
recorder.setAudioEncoder(AudioEncoder.AMR_WB);
recorder.setOutputFile(file.getAbsolutePath());
try {
    recorder.prepare();
    recorder.start();
} catch (IOException e) {
    System.out.println("Exception: " + e.getMessage());
}

我在清单文件中授予了以下权限。

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

但在 recorder.start() 行我得到了运行时异常。 Logcat 显示以下错误消息。

09-23 15:47:54.462: E/AndroidRuntime(8697): FATAL EXCEPTION: main
09-23 15:47:54.462: E/AndroidRuntime(8697): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mypackage/com.mypackage.RecordingActivity}: java.lang.RuntimeException: start failed.
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2250)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2300)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.ActivityThread.access$600(ActivityThread.java:144)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1295)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.os.Looper.loop(Looper.java:150)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.ActivityThread.main(ActivityThread.java:5162)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at java.lang.reflect.Method.invokeNative(Native Method)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at java.lang.reflect.Method.invoke(Method.java:525)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:744)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at dalvik.system.NativeStart.main(Native Method)
09-23 15:47:54.462: E/AndroidRuntime(8697): Caused by: java.lang.RuntimeException: start failed.
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.media.MediaRecorder.start(Native Method)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at com.mypackage.RecordingActivity.startRecording(RecordingActivity.java:169)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at com.mypackage.RecordingActivity.onCreate(RecordingActivity.java:107)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.Activity.performCreate(Activity.java:5288)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
09-23 15:47:54.462: E/AndroidRuntime(8697):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2214)

尝试了与 stackoverflow 中的错误相对应的问题,但无法从中得出有效的答案。请检查这个并帮助我在代码中出了什么问题。

仅供参考>这段代码仅在特定设备中失败。我是否缺少任何其他权限?

【问题讨论】:

  • @MysticMagic 我正在寻找与宽度和高度无关的录音。您提出的答案是用于视频录制:)
  • 这段代码仅在特定设备中失败 - 您可能希望包含有关这些设备的更多详细信息。比如,它们的平台版本是什么? AudioEncoder.AMR_WB 仅适用于 API10。
  • @shoerat:代码在设备中不起作用: 索尼爱立信 4.0.3 版,华硕 Genfone 4.3 版。代码在 Moto-g 4.4.4 中运行良好,操作系统版本 4.4.2 的注 2。
  • @shoerat AppConstants.MSGS_DIR = Environment.getExternalStorageDirectory().getPath() + "/MYAppFolder/";文件名是一些随机字符串。我能够创建文件夹和文件(该文件夹中的 fileName0 成功但无法向其中写入任何数据。

标签: android android-permissions forceclose android-mediarecorder


【解决方案1】:

很少有设备不支持,因为它们不支持 3GP 格式以及 AudioEncoder.AMR_WB 编码。点击here查看支持的格式。

请使用下面的代码来支持最大数量的设备。

recorder.setOutputFormat(OutputFormat.MPEG_4);
recorder.setAudioEncoder(AudioEncoder.AAC);

【讨论】:

  • 安卓2.2怎么样?
  • 安卓M怎么样??
  • 是否会使其默认适用于所有设备?像下面的 recorder.setOutputFormat(OutputFormat.DEFAULT); recorder.setAudioEncoder(AudioEncoder.DEFAULT);
【解决方案2】:

如果您使用的是 Api 23,请先授予权限,然后开始录制

     private boolean checkAndRequestPermissions() {
            int permissionSendMessage = ContextCompat.checkSelfPermission(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE);
            int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
            List<String> listPermissionsNeeded = new ArrayList<>();
            if (locationPermission != PackageManager.PERMISSION_GRANTED) {
                listPermissionsNeeded.add(Manifest.permission.RECORD_AUDIO);
            }
            if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
                listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            }
            if (!listPermissionsNeeded.isEmpty()) {
                ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
                return false;
            }
            return true;
        }
      @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        Log.d("TAG", "Permission callback called-------");
        switch (requestCode) {
            case REQUEST_ID_MULTIPLE_PERMISSIONS: {

                Map<String, Integer> perms = new HashMap<>();
                // Initialize the map with both permissions
                perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
                perms.put(Manifest.permission.RECORD_AUDIO, PackageManager.PERMISSION_GRANTED);
                // Fill with actual results from user
                if (grantResults.length > 0) {
                    for (int i = 0; i < permissions.length; i++)
                        perms.put(permissions[i], grantResults[i]);
                    // Check for both permissions
                    if (perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
                        Log.d("TAG", "sms & location services permission granted");
                        // process the normal flow

                        pager = (ViewPager) findViewById(R.id.pager);
                        pager.setAdapter(new MyAdapter(getSupportFragmentManager()));
                        tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
                        tabs.setViewPager(pager);
                        //else any one or both the permissions are not granted
                    } else {
                        Log.d("TAG", "Some permissions are not granted ask again ");
                        //permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
//                        // shouldShowRequestPermissionRationale will return true
                        //show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
                        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
                                ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
                            showDialogOK("SMS and Location Services Permission required for this app",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            switch (which) {
                                                case DialogInterface.BUTTON_POSITIVE:
                                                    checkAndRequestPermissions();
                                                    break;
                                                case DialogInterface.BUTTON_NEGATIVE:
                                                    // proceed with logic by disabling the related features or quit the app.
                                                    break;
                                            }
                                        }
                                    });
                        }
                        //permission is denied (and never ask again is  checked)
                        //shouldShowRequestPermissionRationale will return false
                        else {
                            Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
                                    .show();
                            //                            //proceed with logic by disabling the related features or quit the app.
                        }
                    }
                }
            }
        }

    }

    private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", okListener)
                .create()
                .show();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 2016-11-23
    • 2014-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多