MediaRecorder停止调用无效状态:1

时间:2016-08-29 11:22:58

标签: java android

我正在使用通话记录器应用程序,当我接到来电时我遇到了这个问题我的应用程序运行正常,没有例外。但是当我打电话给某人时我得到了一些错误。请不要写出愚蠢的答案,例如"你能解释更多"而不是投票。我认为问题可能是我开始录制时,它不能停止。但我不确定。 这是我的代码:

PhonecallReceiver.java

public abstract class PhonecallReceiver 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
    ......

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

        recorder = new MediaRecorder();
       ......

        //Toast.makeText(context,"Reciever", Toast.LENGTH_SHORT).show();
        //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) {
    }

    protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
    }

    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
    }

    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
    }

    protected void onMissedCall(Context ctx, String number, Date start) {
    }

    public void onIncomingCallAsnwered(Context ctx, String number, Date start) {
    }

    public void onIncomingCallIdle(Context ctx,String number,Date start){}


    //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:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;
                onIncomingCallStarted(context, number, callStartTime);


                PhoneStateChangeListener pscl = new PhoneStateChangeListener(context, number);
                TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);


                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);
                }
                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;
    }


    //Detect if call is answered
    private class PhoneStateChangeListener extends PhoneStateListener {
        public boolean wasRinging;
        Context context;
        String number;

        public PhoneStateChangeListener(Context context, String number) {
            this.context = context;
            this.number = number;
        }

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.i("Call recorder::", "RINGING");
                    wasRinging = true;
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:

                    try {
                        Thread.sleep(500); // Delay 0,5 seconds to handle better turning on
                        // loudspeaker
                    } catch (InterruptedException e) {
                    }
                   // context.setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);



                    Log.i("Call recorder::", "OFFHOOK");

                    onIncomingCallAsnwered(context, number, callStartTime);

                    if (!wasRinging) {
                        // Start your new activity
                    } else {
                        // Cancel your old activity
                    }

                    // this should be the last piece of code before the break
                    wasRinging = true;
                    break;
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.i("Call recorder::", "IDLE");
                    // this should be the last piece of code before the break
                    onIncomingCallIdle(context, number, callStartTime);
                    wasRinging = false;
                    break;
            }
        }
    }
}

这是CallReceiver.java,它是PhoneCallReciever.java的扩展

public class CallReceiver extends PhonecallReceiver {

    private String fileName;
    private boolean recording = false;


    //Phone Ringing From Incoming Call
    @Override
    protected void onIncomingCallStarted(Context ctx, String number, Date start) {
        Log.d("Call recorder:: ", "onIncomingCallStarted Phone:" + number);
    }

    //Phone Outgoing Call Started
    @Override
    protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
        Log.d("Call recorder:: ", "onOutgoingCallStarted Phone:" + number);
        if (is_recording) {


            startRecording(number, ctx, "outgoing", false);


        }

    }

    //Phone Incoming Call Ended
    @Override
    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
        Log.d("Call recorder:: ", "onIncomingCallEnded Phone:" + number);
    }

    //Phone Outgoing Call Ended
    @Override
    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
        Log.d("Call recorder:: ", "onOutgoingCallEnded Phone:" + number);
        if (is_recording) {
            stopAndReleaseRecorder(ctx);
        }


    }

    //Phone Call Missed
    @Override
    protected void onMissedCall(Context ctx, String number, Date start) {
        Log.d("Call recorder:: ", "onMissedCall Phone:" + number);
    }

    //Phone Incoming Answered<--Main
    @Override
    public void onIncomingCallAsnwered(Context ctx, String number, Date start) {
        Log.d("Call recorder:: ", "onIncomingCallAsnwered Phone:" + number);
        if (is_recording) {


            if (is_record_contacts_only && new FileHelper().is_number_in_contacts(ctx, number)) {
                startRecording(number, ctx, "incoming", false);
            } else if (!is_record_contacts_only) {
                startRecording(number, ctx, "incoming", false);
            }


            if (is_record_all_except_contacts && !new FileHelper().is_number_in_contacts(ctx, number)) {
                startRecording(number, ctx, "incoming", false);
            } else if (!is_record_all_except_contacts) {
                startRecording(number, ctx, "incoming", false);
            }

        }

    }

    //Phone Incoming Call Idle
    @Override
    public void onIncomingCallIdle(Context ctx, String number, Date start) {
        Log.d("Call recorder:: ", "onIncomingCallIdle Phone:" + number);
        if (is_recording) {
            stopAndReleaseRecorder(ctx);
        }

    }


    /*

    Call feature

     */


    //Recording
    private void terminateAndEraseFile(Context context) {
        Log.d(Constants.TAG, "RecordService terminateAndEraseFile");
        stopAndReleaseRecorder(context);
        recording = false;
        deleteFile();
    }

    private void deleteFile() {
        Log.d(Constants.TAG, "RecordService deleteFile");
        FileHelper.deleteFile(fileName);
        fileName = null;
    }

    public void stopAndReleaseRecorder(Context context) {
        Log.d("Call recorder:: ", "Stoped recording");
        if (recorder == null) {
            Log.d("Call recorder:: ", "nill");
            return;
        }

        Log.d(Constants.TAG, "RecordService stopAndReleaseRecorder");
        boolean recorderStopped = false;
        boolean exception = false;

        try {
            recorder.stop();
            recorderStopped = true;
        } catch (IllegalStateException e) {
            Log.e(Constants.TAG, "IllegalStateException");
            e.printStackTrace();
            exception = true;
        } catch (RuntimeException e) {
            Log.e(Constants.TAG, "RuntimeException");
            exception = true;
        } catch (Exception e) {
            Log.e(Constants.TAG, "Exception");
            e.printStackTrace();
            exception = true;
        }
        try {
            recorder.reset();
        } catch (Exception e) {
            Log.e(Constants.TAG, "Exception");
            e.printStackTrace();
            exception = true;
        }
        try {
            recorder.release();
        } catch (Exception e) {
            Log.e(Constants.TAG, "Exception");
            e.printStackTrace();
            exception = true;
        }

        recorder = null;
        if (exception) {
            deleteFile();
        }
        if (recorderStopped) {

            Toast.makeText(context, "" + context.getResources().getString(R.string.receiver_end_call), Toast.LENGTH_SHORT).show();

        }
    }


    public void startRecording(String phoneNumber, final Context context, String incoming_or_outgoing, boolean is_missed) {
        Log.d(Constants.TAG, "RecordService startRecording");
        boolean exception = false;
        recorder = new MediaRecorder();


        try {


            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            recorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
            fileName = FileHelper.getFilename(phoneNumber, incoming_or_outgoing, is_missed);
            recorder.setOutputFile(fileName);
            Log.d("Name of file", "" + fileName);


            MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
                public void onError(MediaRecorder arg0, int arg1, int arg2) {
                    Log.e(Constants.TAG, "OnErrorListener " + arg1 + "," + arg2);
                    terminateAndEraseFile(context);
                }
            };
            recorder.setOnErrorListener(errorListener);

            MediaRecorder.OnInfoListener infoListener = new MediaRecorder.OnInfoListener() {
                public void onInfo(MediaRecorder arg0, int arg1, int arg2) {
                    Log.e(Constants.TAG, "OnInfoListener " + arg1 + "," + arg2);
                    terminateAndEraseFile(context);
                }
            };
            recorder.setOnInfoListener(infoListener);

            recorder.prepare();
            // Sometimes prepare takes some time to complete
            Thread.sleep(2000);
            recorder.start();
            recording = true;
            Log.d(Constants.TAG, "RecordService recorderStarted");
        } catch (IllegalStateException e) {
            Log.e(Constants.TAG, "IllegalStateException");
            e.printStackTrace();
            exception = true;
        } catch (IOException e) {
            Log.e(Constants.TAG, "IOException");
            e.printStackTrace();
            exception = true;
        } catch (Exception e) {
            Log.e(Constants.TAG, "Exception");
            e.printStackTrace();
            exception = true;
        }

        if (exception) {
            terminateAndEraseFile(context);
        }

        if (recording) {
            Toast.makeText(context, "" + context.getResources().getString(R.string.receiver_start_call), Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "" + context.getResources().getString(R.string.record_impossible), Toast.LENGTH_SHORT).show();
        }
    }

}

以下是我收到的错误:

 RecordService stopAndReleaseRecorder
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder E/MediaRecorder: stop called in an invalid state: 1
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder E/Call recorder:: IllegalStateException
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err: java.lang.IllegalStateException
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at android.media.MediaRecorder.stop(Native Method)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at free.call.automatic.recorder.helper.CallReceiver.stopAndReleaseRecorder(CallReceiver.java:133)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at free.call.automatic.recorder.helper.CallReceiver.onOutgoingCallEnded(CallReceiver.java:53)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at free.call.automatic.recorder.helper.PhonecallReceiver.onCallStateChanged(PhonecallReceiver.java:151)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at free.call.automatic.recorder.helper.PhonecallReceiver.onReceive(PhonecallReceiver.java:84)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2725)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at android.app.ActivityThread.-wrap14(ActivityThread.java)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at android.os.Looper.loop(Looper.java:148)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
08-29 13:16:02.586 19691-19691/free.call.automatic.recorder D/Call recorder:: RecordService deleteFile

3 个答案:

答案 0 :(得分:2)

上面的代码段只是正确的,但在此之前,您必须确保以下几点:

  • MediaRecorder已停止,您再次尝试停止它: 例外

  • 如果MediaRecorder已经发布,您又要再次尝试 发布它:例外

在android文档的相机开发者指南中提到的正确配置顺序

  • 设置音频/视频源,格式,编码器

  • 准备

  • 开始

答案 1 :(得分:0)

问题可能是这些陈述的顺序,因为几个月前我遇到了同样的问题,我不记得正确的订单,但你可以从developer.android文档中确认它

 recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            recorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
            fileName = FileHelper.getFilename(phoneNumber, incoming_or_outgoing, is_missed);
            recorder.setOutputFile(fileName);

答案 2 :(得分:0)

在哪里可以找到状态码列表?我认为这是解决相关问题的关键。

对于此问题,状态1是什么意思?我们都知道状态图,但我们只是不知道每个状态的代码。

最终,我发现的含义

  • 1:最初,如果我两次调用stop(),第二次将告诉您。
  • 2:?
  • 3:?
  • 4 :?