這兩天為買票傷透了腦筋,鐵道部的網站實在不給力,先不說效能怎麼樣,單就使用者介面就夠令人蛋疼了。各種莫名其妙的錯誤,各種重複輸入密碼...
於是自己改了一下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; } } };}