Android 4.2上的Mediarecorder - 无效状态异常

时间:2015-10-21 10:43:37

标签: java android

我正在尝试使用媒体记录录制来电。在Android 5上录制完美但在android 4.2上我在recorder.start()

中获得了无效状态异常

我已将persmissions定义为:READ_PHONE_STATE,RECORD_VIDEO,RECORD_AUDIO

有人帮忙吗?

我的广播接收器代码:

public class PhoneStateChangeReceiver extends BroadcastReceiver {
    //The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations

private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;  //because the passed incoming is only valid in ringing

private static MediaRecorder recorder;
private static long RecordingStartedTime = 0;
private static Context Context;
private static Configuration Config;
private static boolean Recording = false;

public void dropRecording() {

    try {
        Recording = false;
        long EndTime = System.currentTimeMillis();
        long Duration = EndTime - callStartTime.getTime();

        // record to database
        FileRecords fileRecords = new FileRecords(Context);
        fileRecords.record(callStartTime.getTime(),
                EndTime,
                Duration,
                Context.getFilesDir() + "/" + RecordingStartedTime + ".3gp",
                0,
                FileRecords.TYPE.THREEGP,
                savedNumber);

        if(recorder != null) {
            recorder.stop();
            recorder.release();
        }
    } catch (Exception e) {
        Logs.Put(e, Context);
    }
}

private void StartRecording() {
    try {

        RecordingStartedTime = System.currentTimeMillis();

        try {

            recorder.stop();
            recorder.reset();
            recorder.release();

        } catch(Exception e) {

        }

        recorder = new MediaRecorder();
        String FileName = Context.getFilesDir() + "/" + RecordingStartedTime + ".3gp";

        recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setAudioChannels(1);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recorder.setOutputFile(FileName);
        recorder.setMaxFileSize(Config.MaxRecordFileSize() * 1024 * 1024);
        recorder.setMaxDuration(Config.MaxRecordTime());
        recorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
            @Override
            public void onError(MediaRecorder mr, int what, int extra) {
            Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
                dropRecording();
            }
        });
        recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
            @Override
            public void onInfo(MediaRecorder mr, int what, int extra) {
                if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED || what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
                    Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
                    dropRecording();
                }
            }
        });
        recorder.setAudioEncodingBitRate(Config.AudioBitRateQuality());

        recorder.prepare();
        recorder.start();
        Recording = true;

    } catch (Exception e) {
        Logs.Put(e, Context);

        try {

            RecordingStartedTime = System.currentTimeMillis();

            try {

                recorder.stop();
                recorder.reset();
                recorder.release();

            } catch(Exception ex) {

            }

            recorder = new MediaRecorder();
            String FileName = Context.getFilesDir() + "/" + RecordingStartedTime + ".3gp";

            recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
            recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            recorder.setAudioChannels(1);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            recorder.setOutputFile(FileName);
            recorder.setMaxFileSize(Config.MaxRecordFileSize() * 1024 * 1024);
            recorder.setMaxDuration(Config.MaxRecordTime());
            recorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
                @Override
                public void onError(MediaRecorder mr, int what, int extra) {
                    Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
                    dropRecording();
                }
            });
            recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
                @Override
                public void onInfo(MediaRecorder mr, int what, int extra) {
                    if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED || what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
                        Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
                        dropRecording();
                    }
                }
            });
            recorder.setAudioEncodingBitRate(Config.AudioBitRateQuality());

            recorder.prepare();
            recorder.start();

            Recording = true;
        } catch (Exception ex) {
            Logs.Put(ex, Context);
        }

    }
}

@Override
public void onReceive(Context context, Intent intent) {

    Context = context;
    Config = new Configuration(context);

    if(!Config.RecordCalls())
        return;

    //We listen to two intents.  The new outgoing call only tells us of an outgoing call.  We use it to get the number.
    if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
        savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
    }
    else{
        String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
        String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
        int state = 0;
        if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
            state = TelephonyManager.CALL_STATE_IDLE;
        }
        else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
            state = TelephonyManager.CALL_STATE_OFFHOOK;
        }
        else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
            state = TelephonyManager.CALL_STATE_RINGING;
        }

        onCallStateChanged(context, state, number);
    }
}

//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start){
    StartRecording();
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start){
    StartRecording();
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){
    dropRecording();
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end){
    dropRecording();
}
protected void onMissedCall(Context ctx, String number, Date start){
    // do nothing;
}

//Deals with actual events

//Incoming call-  goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call-  goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCallStateChanged(Context context, int state, String number) {
    if(lastState == state){
        //No change, debounce extras
        return;
    }

    switch (state) {
        case TelephonyManager.CALL_STATE_RINGING:
            // ringing do nothing
            savedNumber = number;
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:
            //Transition of ringing->offhook are pickups of incoming calls.  Nothing done on them
            if(lastState != TelephonyManager.CALL_STATE_RINGING){
                isIncoming = false;
                callStartTime = new Date();
                onOutgoingCallStarted(context, savedNumber, callStartTime);
            } else {
                isIncoming = true;
                callStartTime = new Date();
                onIncomingCallStarted(context, number, callStartTime);
            }
            break;
        case TelephonyManager.CALL_STATE_IDLE:
            //Went to idle-  this is the end of a call.  What type depends on previous state(s)
            if(lastState == TelephonyManager.CALL_STATE_RINGING){
                //Ring but no pickup-  a miss
                onMissedCall(context, savedNumber, callStartTime);
            }
            else if(isIncoming){
                onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
            }
            else{
                onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
            }
            break;
    }
    lastState = state;
}
}

0 个答案:

没有答案