通常我们在对电话状态进行监听的时候通常会使用TelephonyManager这个类的CALL_STATE_IDLE CALL_STATE_OFFHOOK,CALL_STATE_RINGING 三种状态来进行判断当前电话所处的状态。但是对于CALL_STATE_OFFHOOK这个状态来说,其中包含了两个电话状态:接听,正在拨号状态。这导致了我们在拨打电话时无法通过该状态来判断是接听了,还是正在拨号。
在网上找了很多,都没有找到很好的办法来判断,仅仅搜到了Call.State这种说法:IDLE,ACTIVE,DIALING,DISCONNECTING等状态,但是具体怎么用却没有人解答。我只好自己去寻找解决办法,这里会牵扯到系统Phone应用的源码,所以我去搜寻关于该源码的一些资料
具体可以参考:http://blog.csdn.net/yangwen123/article/details/10105051
http://m.blog.csdn.net/blog/lksodit_yiyi/8279271
理论的电话流程弄懂后,下面来做一下实践,我所写的程序是需要在linux源码编译环境下操作的,可以嵌入到系统应用中运行。第三方的应用可能通过我这个方法实现不了。不废话了,讲一下大致流程:
//导包
import com.android.internal.telephony.Call
import com.android.internal.telephony.CallManager
import com.android.internal.telephony.Phone
import com.android.internal.telephony.PhoneFactory
//初始化实例
private CallManager cm=CallManager.getInstance();
private Phone phone=PhoneFactory.getDefaultPhone();
//在程序初始化完的时候需要注册phone,电话状态改变时的方法(构造方法或者Oncreate方法等一些可以初始化类的方法)
cm.registerPhone(phone);
cm.registerForPreciseCallStateChanged(mHandler,PHONE_STATE_CHANGED,null);
private Handler mHandler=new Handler(){
@Override
protected void handleMessage(){
//此处来处理系统发出的Message
switch(msg.what){
....
....
....
case:PHONE_STATE_CHANGED:
stateChanged();
break;
}
}
}
private void stateChanged(){
Phone curPhone=cm.getPhone();
//Phone的状态:RING,IDLE,OFFHOOK
Phone.State state=cm.getState();
//Call的状态
Call.State callState=curPhone.getForgroundCall().getState();
//电话状态的判断
switch (callState) {
case DIALING:
//正在拨号
break;
case ACTIVE:
//已经摘机
break;
case DISCONNECTED:
//断开连接
case IDLE:
//挂断或者等待接听状态
if(state==Phone.State.RING){
//来电
}else{
//挂断
}
break;
default:
break;
}
}
就像TelephonyManager注册listen(PhoneStateListener….)似的,我们在
cm.registerForPreciseCallStateChanged(mHandler,PHONE_STATE_CHANGED,null);里注册,第一个参数是传进系统的Handler,有该方法里来监听电话状态并作出相应并发出消息。第二个参数PHONE_STATE_CHANGED是标志位,第三个参数我也不明白,不过不影响我们理解。
OK,以上的操作完成后可以进行一下编译了,将新建的应用工程代码移入到packages/apps/,指定目录下 mm -B,发现编译通过,运行一下试试,。。。。。。。。不出所料,会报异常:
PhoneFactory.getDefaultPhone must be called from Looper thread
解决办法请参考
http://blog.csdn.net/kuangjp/article/details/7092212
此处只是针对拨打电话,当你需要监听来电并且要得到来电号码时,可以和TelephonyManager,BroadcastReceiver来配合使用。
好了,经过这一连串的操作,最终你会得到你想要的结果,我亲测过,我要实现的功能是:拨打电话的时候显示:正在拨号,当对方接听后,会显示时间。
补充一下:在android4.4中,Phone.State转换成了PhoneConstants。State 导入import com.android.internal.telephony.PhoneConstants;