Android: Надежден аудиозапис, всички устройства

Може ли някой да сподели с мен НАДЕЖДЕН начин за запис на аудио на всички устройства с помощта на MediaRecorder? Просто се опитвам да запиша аудиофайл във формат AMR с нисък битрейт, който според google е стандартен за всички устройства. Това е един куп глупости.

Според моя опит има много устройства, таблети и т.н. на други марки, които ще се провалят ужасно, когато използвате AudioEncoder.AMR_NB по подразбиране. Моето заобиколно решение в момента е да използвам отражение, за да проучвам кои енкодери са в суперкласа, след което да преглеждам всеки от тях с слушател на грешки, за да видя кой от тях не се проваля. Това не само не е изящно, но и не улавя всички устройства. Опитах също да настроя по подразбиране опциите AudioEncoder и OutputFormat (константа 0) и това също се проваля ужасно на някои устройства.

Ето какво използвам, ако AMR енкодерът по подразбиране не работи:

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

След това преминавам през всеки енкодер, като задавам слушател на грешки. Ако завърши успешно, го задавам като енкодер по подразбиране като настройка.

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() {

Продължавам цикъла, ако слушателят открие грешка:

if (arg1 == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {

Тази техника работи за повечето устройства. Какво ще кажете за останалите? Все още имам устройства, които падат през пукнатините и честно казано бих искал нещо НАДЕЖДНО за почти всички устройства????


person ThumbsDP    schedule 11.09.2012    source източник
comment
Защо не опитате този?   -  person Praveenkumar    schedule 11.09.2012
comment
@SpK: благодаря за връзката, но кодът му следва нормалния път на настройка на AMR_NB, който, както казах, се проваля на много устройства.   -  person ThumbsDP    schedule 11.09.2012


Отговори (1)


Е, тъй като никой не иска да публикува решение, ето какво използвам сега, което работи, но е малко бъркотия. Започвам с метод setupAudio(), който опитва три често срещани настройки на аудио енкодер и контейнер. Това ще работи за повечето устройства. Ако не работи, по подразбиране се използва допълнителен метод setupAltAudio(), който преминава през стойностите на енкодера, изброени за устройството, и опитва всяка една. Сигурен съм, че някой ще се включи и ще каже „защо да не използвам OnErrorListener()“? Това не работи за много устройства, тъй като те извеждат странни, нефатални грешки и ако отговоря на това, може да спра валидна настройка на запис.

Грешки, които обикновено не могат да бъдат възстановени, се случват при настройване на MediaRecorder, така че аз безумно улавям методите setAudioEncoder() и подготви() и start(). Ако хвърли изключение тук, нямам валидна настройка за аудиозапис. Все още не съм изчистил този код и има някои елементи в него, които могат да бъдат подобрени. След като аудио енкодерът е успешен, запазвам стойността на енкодера и контейнера в настройките и стартирам отново метода setupAudio(). Какво се случва този път, дали грабва тези настройки и отива директно към startRecording(). Така че като цяло първо опитвам най-често срещаните настройки на MediaRecorder, след което използвам отражение, за да преминавам през всеки енкодер като метод на проба и грешка. РЕДАКТИРАНЕ: В setupAltAudio липсва един детайл. Първичният цикъл трябва да се инициализира (i) до стойност на audioLoop, която е в настройките. Това следи кой енкодер е тестван последно.

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();
person ThumbsDP    schedule 02.10.2012