这两天为买票伤透了脑筋,铁道部的网站实在不给力,先不说性能怎么样,单就用户界面就够令人蛋疼了。各种莫名其妙的错误,各种重复输入密码...
于是自己改了一下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; } } }; }