这两天为买票伤透了脑筋,铁道部的网站实在不给力,先不说性能怎么样,单就用户界面就够令人蛋疼了。各种莫名其妙的错误,各种重复输入密码...
于是自己改了一下Phone的代码,替换原来的apk,让它自动重拨。
市场上也有一些所谓疯狂拨号的apk,但是限于api,并不能对电话进行精确的控制,一个典型的例子就是,拨打95105105之后,如果不能接通,对方不会自动挂断,而是一直在提示“对不起,..blablabla”,这个时候是phone以外的应用是不知道有没有接通的。
因为PhoneStateListener的接口onCallStateChanged只能监听到3个粗略的状态。
/**
* Callback invoked when device call state changes.
*
* @see TelephonyManager#CALL_STATE_IDLE
* @see TelephonyManager#CALL_STATE_RINGING
* @see TelephonyManager#CALL_STATE_OFFHOOK
*/
public void onCallStateChanged(int state, String incomingNumber) {
// default implementation empty
}
具体一个Call状态的流程是DIALING--->ALERTING---->ACTIVE。
其中CALL_STATE_OFFHOOK涵盖了除了IDLE,DISCONNECTED,DISCONNECTING之外的所有状态。对方提示了“对不起,..blablabla”的时候正是ALERTING状态,而且这个状态还很久。所以市场上这些重复拨号的apk都不能自动挂断,这对订火车票这种分秒必争的事情来说是不可接受的。
因此,我需要做的就是判断4~5秒内,如果没有成为ACTIVE就果断挂断,继续重拨。
package com.android.phone;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.BroadcastReceiver;
import android.util.Log;
import android.os.Handler;
import android.os.Message;
import java.util.Timer;
import java.util.TimerTask;
import android.view.KeyEvent;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.Call;
import android.os.AsyncResult;
public class LoopDialer extends BroadcastReceiver {
private static final String TAG = "LoopDialer";
private static final String[] NUMBER_SUFFIX = {"95105105", "96020088"};
private static final long INTERVAL = 1*1000;
private final Timer timer = new Timer();
private Context mContext;
private String number;
private Phone phone;
private boolean isTicketBookNumber(String num) {
for(int i = 0; i < NUMBER_SUFFIX.length; i++) {
if(num.endsWith(NUMBER_SUFFIX[i])) {
return true;
}
}
return false;
}
public void onReceive(Context context, Intent intent) {
if(mContext == null) {
mContext = context;
}
if(phone == null) {
phone = PhoneFactory.getDefaultPhone();
}
String action = intent.getAction();
Log.d(TAG, action);
if(action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
if(intent.hasExtra(Intent.EXTRA_PHONE_NUMBER)) {
String num = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
boolean needReDial = isTicketBookNumber(num);
if(isTicketBookNumber(num)) {
number = num;
timer.schedule(task, INTERVAL, INTERVAL);
}
}
}
}
private TimerTask task = new TimerTask() {
private int dialsecond;
@Override
public void run() {
Call.State state = phone.getForegroundCall().getState();
if(state == Call.State.IDLE) {
//再次发送拨号请求
Intent newIntent = new Intent(Intent.ACTION_CALL);
newIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
newIntent.setClass(mContext, InCallScreen.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(newIntent);
dialsecond = 0;
}
if(state == Call.State.ACTIVE) {
timer.cancel();
return;
}
dialsecond++;
if(dialsecond >=4) {
PhoneUtils.hangup(phone);
dialsecond = 0;
}
}
};
}