Dans le code ci-dessous, mon objet audioRecord
n'est pas en cours d'initialisation. J'ai essayé de le déplacer vers la méthode onCreate
et d'en faire une méthode globale. J'ai enregistré l'état et qui renvoie la valeur 1
, ce qui signifie que vous êtes prêt à utiliser. Le débogueur dit que startRecording
est appelé sur un objet non initialisé. Il est également dit qu'il ne pouvait pas obtenir la source audio.
Pourquoi est-ce que je reçois ces erreurs?
package com.tecmark;
import Java.io.BufferedOutputStream;
import Java.io.DataOutputStream;
import Java.io.File;
import Java.io.FileOutputStream;
import Android.app.Activity;
import Android.media.AudioFormat;
import Android.media.AudioRecord;
import Android.media.MediaRecorder;
import Android.os.Bundle;
import Android.os.Environment;
import Android.util.Log;
import Android.view.View;
import Android.widget.TextView;
public class recorder extends Activity {
private Thread thread;
private boolean isRecording;
private AudioRecord recorder;
private FileOutputStream os;
private BufferedOutputStream bos;
private DataOutputStream dos;
private TextView text;
private int audioSource = MediaRecorder.AudioSource.MIC;
private int sampleRate = 22050;
private int channel = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int encoding = AudioFormat.ENCODING_PCM_16BIT;
private int result = 0;
private int bufferSize;
private byte[] buffer;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v("onCreate", "layout set, about to init audiorec obj");
text = (TextView)findViewById(R.id.TextView01);
bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding);
buffer = new byte[bufferSize];
recorder = new AudioRecord(audioSource, sampleRate,channel,encoding,
AudioRecord.getMinBufferSize(sampleRate, channel,encoding));
Log.i("recorder obj state",""+recorder.getRecordingState());
}
public void onClickPlay(View v){
}
public void record(){
Log.i("inside record method", "******");
File path = Environment.getExternalStorageDirectory();
Log.v("file path", ""+path.getAbsolutePath());
File file = new File(path, "test.wav");
if(file.exists()){
file.delete();
}
path.mkdirs();
Log.v("file path", ""+file.getAbsolutePath());
try {
os = new FileOutputStream(file);
bos = new BufferedOutputStream(os);
dos = new DataOutputStream(bos);
} catch (Exception e1) {
e1.printStackTrace();
}
int bufferSize = AudioRecord.getMinBufferSize(sampleRate,channel,encoding);
byte[] buffer = new byte[bufferSize];
recorder.startRecording();
isRecording = true;
try{
while (isRecording){
result = recorder.read(buffer, 0, bufferSize);
for(int a=0; a<result;a++){
dos.write(buffer[a]);
if(!isRecording){
recorder.stop();
break;
}
}
}
dos.flush();
dos.close();
}catch(Exception e){
e.printStackTrace();
}
}// end of record method
public void onClickStop(View v){
Log.v("onClickStop", "stop clicked");
isRecording=false;
}
public void onClickReverse(View v){
Log.v("onClickReverse", "reverse clicked");
}
public void onClickRecord(View v){
Log.v("onClickRecourd", "record clicked, thread gona start");
text.setText("recording");
thread = new Thread(new Runnable() {
public void run() {
isRecording = true;
record();
}
});
thread.start();
isRecording = false;
}
}//end of class
Logcat
01-30 15:23:16.724: ERROR/AudioRecord(12817): Could not get audio input for record source 1 01-30 15:23:16.729:
ERROR/AudioRecord-JNI(12817): Error creating AudioRecord instance: initialization check failed. 01-30 15:23:16.729:
ERROR/AudioRecord-Java(12817): [ Android.media.AudioRecord ] Error code
-20 when initializing native AudioRecord object. 01-30 15:23:16.729: INFO/recorder obj state(12817): 1 01-30 15:23:16.729:
WARN/dalvikvm(12817): threadid=13: thread exiting with uncaught exception (group=0x4001b180) 01-30 15:23:16.729:
ERROR/AndroidRuntime(12817): Uncaught handler: thread Thread-7 exiting due to uncaught exception 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): Java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord. 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at Android.media.AudioRecord.startRecording(AudioRecord.Java:495) 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at com.tecmark.recorder.record(recorder.Java:114) 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at com.tecmark.recorder$1.run(recorder.Java:175) 01-30 15:23:16.739:
ERROR/AndroidRuntime(12817): at Java.lang.Thread.run(Thread.Java:1096)
Le truc avec AudioRecord est que chaque périphérique peut avoir différents paramètres d’initialisation. Vous devrez donc créer une méthode qui réponde à toutes les combinaisons possibles de débit, d’encodage, etc.
private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
public AudioRecord findAudioRecord() {
for (int rate : mSampleRates) {
for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT }) {
for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO }) {
try {
Log.d(C.TAG, "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: "
+ channelConfig);
int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
// check if we can instantiate and have a success
AudioRecord recorder = new AudioRecord(AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);
if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
return recorder;
}
} catch (Exception e) {
Log.e(C.TAG, rate + "Exception, keep trying.",e);
}
}
}
}
return null;
}
AudioRecord recorder = findAudioRecord();
recorder.release();
J'ai eu le même problème, il a été résolu en mettant
<uses-permission Android:name="Android.permission.RECORD_AUDIO"></uses-permission>
dans le manifeste.
Depuis Lollipop, vous devez également demander spécifiquement à l'utilisateur chaque autorisation. Comme ils peuvent les avoir révoqués. Assurez-vous que l'autorisation est accordée.
Selon les javadocs, tous les appareils sont compatibles avec ce format (pour l’enregistrement):
44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT.
Passez à CHANNEL_OUT_MONO pour la lecture.
Maintenant, avec Lollipop, vous devez demander spécifiquement à l'utilisateur chaque autorisation. Assurez-vous que l'autorisation est accordée.
Même après avoir suivi toutes les étapes ci-dessus, le même problème se posait. Ce qui a bien fonctionné pour moi, c’est que mon os était Marshmallow et que je devais demander des autorisations .
Un problème avec l’initialisation de quelques objets AudioRecord pourrait être résolu en utilisant audioRecord.release();
avant de créer l’objet suivant ... Plus ici: Android AudioRecord - Ne initialisera pas la 2ème fois
Si votre système de téléphonie mobile est Android M ou supérieur, vous devez peut-être appliquer une autorisation d'enregistrement audio sous Android M. http://developer.Android.com/guide/topics/security/permissions.html
Je viens d'avoir le même problème ... La solution consistait à redémarrer l'appareil. Lors de la lecture du code, je n'ai pas publié l'objet AudioRecord, qui bloquait manifestement le périphérique audio . Pour vérifier s'il fonctionne ou non, j'ai téléchargé Audalyzer de Google Play.
J'ai remarqué que lorsque la carte SD sur l'avd que je cours est pleine, le constructeur AudioRecord renvoie la valeur null. Avez-vous essayé d'effacer la carte SD?
dans mon cas, je devais autoriser manuellement l'autorisation dans Android 7 pour le microphone, comme l'a commenté sean zhu.
Je pense que cela est dû au fait que le fil ne sache pas que vous avez mis en pause l'activité principale et tente toujours d'enregistrer après avoir arrêté l'enregistreur.
Je l'ai résolu en changeant mes méthodes onResume () et onPause () pour modifier le boolean isRecording.
public void onResume() {
...
isRecording = true;
}
public void onPause() {
...
isRecording = false;
}
Ensuite, dans votre fil de discussion, entourez votre startRecording()
et votre stop()
avec des instructions if recherchant isRecording:
if(isRecording)
recorder.startRecording();
...
if(isRecording)
recorder.stop(); // which you've done
J'ai réécrit la réponse de @DustinB pour quiconque utilise Xamarin Android AudioRecord avec C #.
int[] sampleRates = new int[] { 44100, 22050, 11025, 8000 };
Encoding[] encodings = new Encoding[] { Encoding.Pcm8bit, Encoding.Pcm16bit };
ChannelIn[] channelConfigs = new ChannelIn[]{ ChannelIn.Mono, ChannelIn.Stereo };
//Not all of the formats are supported on each device
foreach (int sampleRate in sampleRates)
{
foreach (Encoding encoding in encodings)
{
foreach (ChannelIn channelConfig in channelConfigs)
{
try
{
Console.WriteLine("Attempting rate " + sampleRate + "Hz, bits: " + encoding + ", channel: " + channelConfig);
int bufferSize = AudioRecord.GetMinBufferSize(sampleRate, channelConfig, encoding);
if (bufferSize > 0)
{
// check if we can instantiate and have a success
AudioRecord recorder = new AudioRecord(AudioSource.Mic, sampleRate, channelConfig, encoding, bufferSize);
if (recorder.State == State.Initialized)
{
mBufferSize = bufferSize;
mSampleRate = sampleRate;
mChannelConfig = channelConfig;
mEncoding = encoding;
recorder.Release();
recorder = null;
return true;
}
}
}
catch (Exception ex)
{
Console.WriteLine(sampleRate + "Exception, keep trying." + ex.Message);
}
}
}
}