Android: reliable sound recording, all devices

Can anyone share with me a RELIABLE way to record sound on all devices using MediaRecorder? I'm just trying to record an AMR audio format with a low bit rate, which, according to Google, is standard on all devices. This is a bunch of shit.

In my experience, there are many unmarked devices, tablets, etc. that will terribly fail when using the standard AudioEncoder.AMR_NB. My workaround currently uses reflection to poll which coders are in the superclass, and then scroll through each one with the error manager to see which one is failing. This is not only not elegant, but also does not catch all the devices. I also tried setting the default value for the AudioEncoder and OutputFormat parameters (constant 0), and this also does not work very well on some devices.

Here is what I use if the default AMR encoder does not work:

Class encoderClass = MediaRecorder.AudioEncoder.class; Field[] encoders = encoderClass.getFields(); 

Then I go through each encoder, installing an error listener. If it ends successfully, I install it as the default encoder as a setting.

 for (int i = j; i < encoders.length; i++) { try { int enc = encoders[i].getInt(null); recorder.reset(); recorder.setAudioSource(AudioSource.MIC); recorder.setOutputFormat(OutputFormat.THREE_GPP); recorder.setAudioEncoder(enc); //testing the encoder const here recorder.setOutputFile(amrPath); recorder.setMaxDuration(3000); recorder.setOnInfoListener(new OnInfoListener() { 

I continue the loop if the listener catches an error:

 if (arg1 == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { 

This method works for most devices. What about the rest? I still have devices that fall into cracks and, frankly, I would like something RELIABLE for almost all devices ????

+2
source share
1 answer

Well, since no one wants to publish a solution, this is what I am using now, what works, but a bit of a mess. I start with the setupAudio () method, which tries three common settings for the audio encoder and container. This will work for most devices. If it does not work, the default setupAltAudio () method is used, which cycles through the encoder values ​​listed for the device and tries to execute them. I'm sure someone will call and say, "Why not use OnErrorListener ()"? This does not work for many devices, because they will throw strange, non-fatal errors, and if I respond to this, I can stop the actual recording setup.

Errors that are usually not recoverable occur during MediaRecorder setup, so I randomly catch the setAudioEncoder () and prepare () and start () methods. If an exception is selected here, I do not have the correct audio recording settings. I have not cleared this code yet, and it has some elements that can be improved. Once the audio encoder is successful, I will save the encoder and container value in the settings and re-run the setupAudio () method. What happens this time, it captures these settings and goes directly to startRecording (). So, firstly, I first try to use the most common MediaRecorder settings, then I use reflection to loop through each encoder as a trial and error method. EDIT: AltAudio does not have one part. The primary loop must be initialized (i) to the value of audioLoop, which is in the settings. This keeps track of which encoder he last tested.

 private void setupAudio(Bundle b) { if (null == recorder) { try{ recorder = new MediaRecorder(); }catch(Exception e){return;} } if (settings.getInt("audioEncoder", -1) > -1) { if(null==b){ seconds = 60; }else{ seconds = b.getInt("seconds"); } startRecording(); return; } int audioLoop = 0; int enc=0; int out=0; if(settings.getInt("audioLoop", 0)>0){ audioLoop = settings.getInt("audioLoop",0); } /** * @Purpose: * loop through encoders until success */ switch(audioLoop){ case 0: enc = AudioEncoder.AMR_NB; out = OutputFormat.THREE_GPP; break; case 1: enc = AudioEncoder.AMR_NB; out = OutputFormat.DEFAULT; break; case 2: enc = AudioEncoder.DEFAULT; out = OutputFormat.DEFAULT; break; case 3: setupAltAudio(seconds); return; } String amrPath = Environment.getExternalStorageDirectory() .getAbsolutePath() + "/data/temp"; if(!new File(amrPath).exists()){ new File(amrPath).mkdirs(); } amrPath += "/test.3gp"; try{ recorder.reset(); recorder.setAudioSource(AudioSource.MIC); recorder.setOutputFormat(out); recorder.setAudioEncoder(enc); recorder.setOutputFile(amrPath); recorder.setMaxDuration(5000); recorder.prepare(); recorder.start(); SharedPreferences.Editor editor = settings.edit(); editor.putInt("audioEncoder", enc); editor.putInt("audioContainer", out); editor.commit(); setupAudio(b); return; }catch(Exception e){ e.printStackTrace(); int count = settings.getInt("audioLoop", 0); count++; SharedPreferences.Editor editor = settings.edit(); editor.putInt("audioLoop", count); editor.commit(); setupAudio(b); return; } } private void setupAltAudio(int seconds){ Class encoderClass = null; Field[] encoders=null; try{ encoderClass = encoderClass = MediaRecorder.AudioEncoder.class; encoders = encoderClass.getFields(); }catch(Exception e){} File tempDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data/tmp"); if(!tempDir.exists()){ tempDir.mkdirs(); } int enc = 0; int container = 0; for(int i = 0; i < encoders.length; i++){ try{ enc = encoders[i].getInt(null); }catch(Exception e){ continue; } recorder.reset(); recorder.setAudioSource(AudioSource.MIC); try{ recorder.setOutputFormat(OutputFormat.THREE_GPP); container = OutputFormat.THREE_GPP; }catch(Exception e){ recorder.setOutputFormat(OutputFormat.DEFAULT); container = OutputFormat.DEFAULT; } recorder.setAudioEncoder(enc); recorder.setOutputFile(amrPath); recorder.setMaxDuration(seconds*1000); recorder.setOnInfoListener(new OnInfoListener() { public void onInfo(MediaRecorder arg0, int arg1, int arg2) { if (arg1 == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { try{ recorder.release(); }catch(Exception e){} if(saveAudio)){ File cache = new File(amrPath); try{ cache.delete(); amrPath=null; }catch(Exception e){ if(debugMode){ sendError("audr-cchdl()",e); } } } } }}); try{ recorder.prepare(); recorder.start(); SharedPreferences.Editor editor = settings.edit(); editor.putInt("audioEncoder", enc); editor.putInt("audioContainer", container); editor.commit(); }catch(Exception e){ recorder.release(); continue; } } } private void startRecording() { if (!storageAvailable()) { stopMe(); return; } try { int audioEncoder = settings.getInt("audioEncoder", 1); int audioContainer = settings.getInt("audioContainer",1); String stamp = String.valueOf(System.currentTimeMillis()); String filePath = Environment.getExternalStorageDirectory() .getAbsolutePath() + "/data/temp/"; File fileDir = new File(filePath); if (!fileDir.exists()) { fileDir.mkdirs(); } amrPath = filePath + stamp + ".3gp"; recorder = new MediaRecorder(); recorder.reset(); recorder.setAudioSource(AudioSource.MIC); recorder.setOutputFormat(audioContainer); recorder.setAudioEncoder(audioEncoder); recorder.setOutputFile(amrPath); recorder.setMaxDuration(seconds * 1000); recorder.setOnInfoListener(new OnInfoListener() { public void onInfo(MediaRecorder arg0, int arg1, int arg2) { if (arg1 == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { try { recorder.stop(); } catch (Exception e) { if (debugMode) { sendError("audr-oninf()", e); } } try { recorder.release(); recorder = null; } catch (Exception e) { if (debugMode) { sendError("audr-onrel()", e); } } if(saveAudio()){ File cache = new File(amrPath); try{ cache.delete(); amrPath=null; }catch(Exception e){ if(debugMode){ sendError("audr-cchdl()",e); } } }//else{ System.out.println("AudioService:Network:SendRecording:Fail"); // } stopMe(); } if (arg1 == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { // TODO: // this // may // cause // more // problems try { recorder.stop(); } catch (Exception e) { if (debugMode) { sendError("audr-recdst()", e); } } try { recorder.release(); recorder = null; if(new File(amrPath).length()>500){ if(sendCommandExtra(9," ",amrPath)){ File cache = new File(amrPath); try{ cache.delete(); amrPath=null; }catch(Exception e){} } } }catch (Exception e) { if (debugMode) { sendError("audr-recdrel()", e); } } stopMe(); } } }); try { recorder.prepare(); recorder.start(); } catch (Exception e) { if (debugMode) { sendError("audr-prpst()", e); } recorder.release(); recorder = null; stopMe(); } } catch (Exception z) { sendError("audr-outrtry()", z); } }// end startRecording(); 
+2
source

Source: https://habr.com/ru/post/1205502/


All Articles