2016-08-29 13 views
2

私はコールレコーダーアプリで作業していますが、着信コールを受け取ったときに私のアプリが正常に実行されています。例外はありません。しかし、私はいくつかのエラーを出しています。「もっと説明できますか」と投票するのと同じようなダムの答えを書いてはいけません。私は録音を開始するときに問題が起きる可能性があります。それについてはわからない。 MediaRecorder stopが無効な状態で呼び出されました:1

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

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

} 

に拡張したものですCallReceiver.javaですが、私は「エラーがある

PhonecallReceiver.java: はここに私のコードです得意先:

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 
+1

レコーダーの録音中に録音を開始しています。あなたの 'OnOutgoingCallStarted()'メソッドでは、次のようにします: 'if(is_recording)startRecording' ....' if(is_recording == false) '....でなければなりません。メディアレコーダーが再び初期化されている間にもう一度... – Opiatefuchs

+0

これは、アプリケーション内のコール録音オプションを無効にするsharedprefsからの単なる選択肢ではありません。 –

+1

ああ、可能性のある原因は1つだけです。やめる。これはAPIで指摘されています: 'IllegalStateException例外\tがstart()'の前に呼び出された場合はそれをスローします。したがって、正確にエラーがスローされたときは、知っておくことが重要です。電話をかけるか、電話がかかってきたのか、電話をかけられた人が電話をかけたら? – Opiatefuchs

答えて

2

上記のコードスニペットは正しいだけですが、befor

  • MediaRecorderが既に停止していると、あなたがそれを止めるために再試行: 例外

  • MediaRecorderはすでに解放され、あなたが に再びしようとしている場合はeは、あなたが以下の点を確認する必要がありますする必要があります。これをやってそれを解放:例外

アンドロイドドキュメント

上のカメラの開発者ガイドに記載されたコンフィギュレーションの正しい順序私は同じに直面しているため、問題は、これらのステートメントの順序にすることができ
  • セットオーディオ/ビデオソース、フォーマット、エンコーダ

  • 準備

  • スタート

+0

カメラのロックを解除する必要はありません。ミッキーはオーディオのみを記録し、カメラは必要ありません。また、オーディオが記録されている場合、API内にヒントはありません。 – Opiatefuchs

+0

私は自分の答えを編集しました。 –

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); 
関連する問題