6

我想使用MediaRecorder在我的一個活動中錄製音頻。部分代碼如下所示。java.lang.RuntimeException:啓動失敗

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中的錯誤的問題,但無法從中得出有效的答案。請檢查並幫助我在代碼中出錯。

FYI>這段代碼僅在特定設備中失效。我是否缺少任何額外的權限?

+0

http://stackoverflow.com/a/10497885/1777090 – 2014-09-23 10:59:52

+0

@MysticMagic我找錄音哪些我覺得寬度和高度都沒有關係。您提出的答案是視頻錄製:) – Jeeri 2014-09-23 11:13:46

+1

_這段代碼僅在特定設備中失敗_ - 您可能希望包含有關這些設備的更多詳細信息。比如,他們的平臺版本是什麼? 'AudioEncoder.AMR_WB'只能從API10獲得。 – ozbek 2014-09-23 11:54:31

回答

3

很少有設備不支持,因爲它們不支持3GP格式以及AudioEncoder.AMR_WB編碼。點擊here查看支持的格式。

請使用下面的代碼,它將支持最大數量的設備。

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

如何android 2.2? – 2014-12-14 11:24:34

+1

關於android m怎麼樣?? – 2016-01-20 07:43:39

+1

將使它的默認工作的每一個設備?像下面recorder.setOutputFormat(OutputFormat.DEFAULT) ; recorder.setAudioEncoder(AudioEncoder.DEFAULT); – SimpleCoder 2016-10-06 14:33:19

0

如果您使用的是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(); 
    }