2010-12-19 23 views
12

Mój problem jest prosty do wyjaśnienia - Próbuję utworzyć obiekt AudioRecord, ale nie uda się go zainicjować (tj. Po konstruktorze getState zwraca 0, sygnalizując niepowodzenie). Używam tego od Eclipse na MotoDroid 1 z systemem OS 2.2.1. Moja AndroidManifest.xml jest AFAIK, stosując odpowiednią zgodę, RECORD_AUDIO (nie wiem jak to potwierdzić):Inicjalizacja Android AudioRecord kończy się niepowodzeniem za każdym razem

<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true"> 
    <uses-permission android:name="android.permission.RECORD_AUDIO"/> 
    <activity android:name=".SphinxMic" 
       android:label="@string/app_name"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
</application> 

I wykonaj następujące czynności, aby utworzyć AudioRecord:

bufferSize = AudioRecord.getMinBufferSize(8000, CHANNEL_IN_MONO, ENCODING_PCM_8BIT); 
audioRecorder = new AudioRecord(AudioSource.MIC, 8000, CHANNEL_IN_MONO, ENCODING_PCM_8BIT, 50*bufferSize); 
if (audioRecorder.getState() != AudioRecord.STATE_INITIALIZED) 
    throw new Exception("AudioRecord init failed"); 

audioRecorder .getState() zwraca 0 (tj. STATE_UNINITIALIZED)

Nie znalazłem żadnych pełnych przykładów użycia tego API i jestem bardzo początkującym Androidem, więc rozwiązanie może być czymś prostym. Co mogę zrobić, aby dowiedzieć się, dlaczego się nie udaje?

Kilka osób zadało podobne pytania, ale musiały one mieć inne problemy niż ja, ponieważ poprawki, które zatwierdzili, nie pomogły mi. Przede wszystkim this. Ale zatwierdzone rozwiązanie jest kłopotliwe i i tak nie zadziałało. Próbowałem także różnych przepływności (8000, 16000, 11025, 44100), zarówno mono, jak i stereo oraz 8 i 16 bitów. Po pomyślnym zainicjowaniu nie powraca żadna kombinacja.

+1

co mówi logcat? również próbować przenosić uses-permission z aplikacji. afaik powinien siedzieć w zamiarze. – techiServices

+1

Z jakiegoś powodu program LogCat przestał wyświetlać większość informacji dziennika po kilku uruchomieniach - ale jest to zupełnie inny problem. Chciałbym oznaczyć twój komentarz dotyczący uprawnień do użytkowania jako odpowiedź ... jeśli to był jeden (ponieważ zadziałało!) – Dave

Odpowiedz

36

Spędziłem kilka godzin rozwiązywania tego problemu, i okazało się, że przejście

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

zewnątrz blok aplikacji faktycznie go rozwiązał!

... 
    </application> 

    <uses-permission android:name="android.permission.RECORD_AUDIO" /> 
</manifest> 
+0

Przeniesienie węzła uprawnień użytkownika na zewnątrz rozwiązuje go. Dzięki! –

1

Spróbuj 16bit. To, co działa dla mnie:

try { 
     // Create a new AudioRecord object to record the audio. 
     bufferSize = AudioRecord.getMinBufferSize(frequency,channelConfiguration,audioEncoding); 

     audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 
                frequency, channelConfiguration, 
                audioEncoding, bufferSize); 
    } catch (Throwable t) { 
     Log.e("AudioRecord","Recording Failed"); 
    } 

i mam następujące zmienne ustawione:

int frequency = 8000; 
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; 
+1

Pracowałem z tym dzisiaj i stwierdziłem, że robi wielką różnicę, jeśli wywołasz audioRecord.release() na końcu. Podobno obiekt nie zostanie zwolniony, dopóki tego nie zrobisz. Z jakiegoś powodu, nawet jeśli funkcja audioRecord.release() zostanie wywołana na końcu jakiegoś kodu, to będzie działać przy pierwszej próbie, kiedy zostanie wprowadzona. Eksperymentowałem i nie rozumiem tego, ale odkryłem, że pomaga wielki czas z inicjalizacją. – chaimp

+0

Jeśli pobierzesz aplikację Audalyzer i spróbujesz ją uruchomić i jest ona zamrożona, prawdopodobnie zasoby związane z AudioRecord zostaną powiązane. Ponowne uruchomienie telefonu to naprawia. – chaimp

5

Inny możliwy problem:

miałem RECORD_AUDIO pozwolenie aktywowany w moim manifestu, ale na poziomie API 23 Musiałem też zwrócić się o pozwolenie na starcie.

+0

w jaki sposób zażądałeś pozwolenia w czasie wykonywania? – Fer

0

Jeśli ktoś musi ręcznie zażądać uprawnień do dysku dla interfejsu API 23+, oto jedna z zastosowanych przeze mnie metod. Po prostu zamień na permission.RECORD_AUDIO w odpowiednich bitach. Logika metody zależy od kilku bitów, które są zewnętrzne (na przykład strings.xml, ActivityCompat, Snackbar), ale sądzą, że może i tak komuś pomóc.

/** 
* Requests the Storage permissions. 
* If the permission has been denied previously, 
* a SnackBar will prompt the user to grant the 
* permission, otherwise it is requested directly. 
*/ 
private void requestStoragePermissions() { 

    // Newer versions Android 18+ 
    if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) { 
     /** 
     * Permissions required to read and write storage. 
     */ 
     final String[] PERMISSIONS_STORAGE = { 
       permission.READ_EXTERNAL_STORAGE, 
       permission.WRITE_EXTERNAL_STORAGE, 
     }; 

     final boolean readResult = 
       ActivityCompat.shouldShowRequestPermissionRationale(
         this, permission.READ_EXTERNAL_STORAGE); 
     final boolean writeResult = 
       ActivityCompat.shouldShowRequestPermissionRationale(
         this, permission.WRITE_EXTERNAL_STORAGE); 

     if (readResult || writeResult) { 

      // Provide an additional rationale to the user if the permission was not granted 
      // and the user would benefit from additional context for the use of the permission. 
      // For example, if the request has been denied previously. 
      Log.i(TAG, 
        "Displaying disk permission rationale to provide additional context."); 

      // Display a SnackBar with an explanation and a button to trigger the request. 
      Snackbar.make(mainView, R.string.permission_storage_rationale, 
        Snackbar.LENGTH_INDEFINITE) 
        .setAction(R.string.ok, new View.OnClickListener() { 
         @Override 
         public void onClick(View view) { 
          ActivityCompat 
            .requestPermissions(MainActivity.this, 
              PERMISSIONS_STORAGE, 
              REQUEST_STORAGE); 
         } 
        }) 
        .show(); 
     } else { 
      // Storage permissions have not been granted. Request them directly. 
      ActivityCompat.requestPermissions(
        this, PERMISSIONS_STORAGE, REQUEST_STORAGE); 
     } 

    } 
}