我正在使用通话记录器应用程序,当我接到来电时我遇到了这个问题我的应用程序运行正常,没有例外。但是当我打电话给某人时我得到了一些错误。请不要写出愚蠢的答案,例如"你能解释更多"而不是投票。我认为问题可能是我开始录制时,它不能停止。但我不确定。 这是我的代码:
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
答案 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是什么意思?我们都知道状态图,但我们只是不知道每个状态的代码。
最终,我发现的含义