一 监听手机Phone状态 转载:http://www.cnblogs.com/bastard/archive/2012/11/23/2784559.html
在手机里面监听Phone的状态有两种方法:
1 注册接收广播
AndroidMenifest.xml: <receiver android:name="CallListener" > <intent-filter> <action android:name="android.intent.action.PHONE_STATE" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver> 权限 <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 广播: public class CallListener extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent){ } }
2 注册PhoneStateListener
//获得相应的系统服务
TelephonyManager tm = (TelephonyManager) getSystemService(
Context.TELEPHONY_SERVICE);
//创建Listener
MyPhoneCallListener myPhoneCallListener = new MyPhoneCallListener();
//注册监听 设置监听的State
tm.listen(myPhoneCallListener, PhoneStateListener.LISTEN_CALL_STATE);
//实现PhoneStateListener listener并实现相应的方法
public class MyPhoneCallListener extends PhoneStateListener
{
@Override
public void onCallStateChanged(int state, String incomingNumber)
{
switch (state)
{
//电话通话的状态
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
//电话响铃的状态
case TelephonyManager.CALL_STATE_RINGING:
break;
//空闲中
case TelephonyManager.CALL_STATE_IDLE:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
这里需要通过TelephonyManager,那么注册过程是如果实现的,以及触发的过程又是如何的呢。
Framework层telephony处理的核心是RIL这个类,网络层得各种状态变化由此传递给监听者。
Application层很多的地方都需要对Phone的state进行监听处理。下面将此过程是如何实现的。
类继承结构图:
二 监听Phone状态的实现机制
Phone state listen 时序图:
1 PhoneNotifier与Phone
在PhoneFactory中对Framework的telephony层进行了对象的初始化:
public static void makeDefaultPhone(Context context)
{
sPhoneNotifier = new DefaultPhoneNotifier();
//创建CommandsInterface实例
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
//创建Phone实例 以及代理对象ProxyPhone
sProxyPhone = new PhoneProxy(new GSMPhone(context,
sCommandsInterface, sPhoneNotifier));
}
Public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
// notifier
super(notifier, context, ci, unitTestMode);
}
在创建GSMPhone父类时传递了PhoneNotifier对象到PhoneBase类中:
protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
boolean unitTestMode) {
//保存notifier对象引用
this.mNotifier = notifier;
this.mContext = context;
mLooper = Looper.myLooper();
mCM = ci;
//PhoneBase是个handler 注册来电监听
mCM.setOnCallRing(this, EVENT_CALL_RING, null);
}
这里看到:GSMPhone将存储了一个PhoneNotifier对象的引用,PhoneBase是一个Handler,
但是并没有注册到RIL 的mCallStateRegistrants表中对Phone状态变化的事件监听,也没有在PhoneBase中
看到使用mNotifier来进行PhoneStateListener .LISTEN_CALL_STATE状态的通知触发。
其实通过代码可以看到Phone的状态并不是直接由RIL来控制判断的,而是类GsmCallTracker对各种状态监听,综合起来进行判断通知的。
简单看下这个类继承结构:
这个类也挺复杂,先看看这样一个函数:
GsmCallTracker:
private void updatePhoneState() {
Phone.State oldState = state;
//判断状态有无变化
……
if (state != oldState) {
//GSMPhone
phone.notifyPhoneStateChanged();
}
}
GSMPhone:
void notifyPhoneStateChanged() {
//这就是在创建GSMPhone时传递的PhoneNotifier——DefaultPhoneNotifier
mNotifier.notifyPhoneState(this);
}
从这里就到了PhoneNotifier派生类DefaultPhoneNotifier中,将状态变化通知其注册监听者。
DefaultPhoneNotifier:
public void notifyPhoneState(Phone sender) {
Call ringingCall = sender.getRingingCall();
String incomingNumber = "";
if (ringingCall != null && ringingCall.getEarliestConnection() != null){
incomingNumber = ringingCall.getEarliestConnection().getAddress();
}
try {
//remote调用,通知Call State
mRegistry.notifyCallState(convertCallState(sender.getState()), incomingNumber);
} catch (RemoteException ex) {
// system process is dead
}
}
对状态的监听注册Listener ,都是在TelephonyRegistry中进行。
2 TelephonyRegistry和PhoneStateListener
看一下PhoneNotifier相关类继承结构:
ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
这里核心的类就是TelephonyRegistry,从ITelephonyRegistry.Stub继承下来,这个类是运行在SystemServer中,
作为Framework层Service,可以通过binder进程间通信,提供了状态的注册监听,状态变化的通知。
在上面监听Phone状态的一种方式里面,通过继承PhoneStateListener来实现;继承结构中有个IPhoneStateListener这是AIDL文件所自动生成的类。
AIDL文件是按照已搭建好的框架,自动生成进程间通信所需要的接口和类,自动生成的类继承结构关系都如下:
再看一下实现监听需要重写的类PhoneStateListener:
PhoneStateListener持有了IPhoneStateListener.Stub对象callback,因为我们想要实现监听Phone状态的所在进程和
通知phone状态变化的进程,不是同一个进程中,要实现跨进程的通信,需要使用Binder实现。
所以在注册到TelephonyRegistry服务中的listener是一个IPhoneStateListener.Stub的binder对象。
3 Phone状态监听注册
注册过程:
//获得相应的系统服务 TelephonyManager tm = (TelephonyManager) getSystemService( Context.TELEPHONY_SERVICE); //创建Listener MyPhoneCallListener myPhoneCallListener = new MyPhoneCallListener(); //注册监听 设置监听的State tm.listen(myPhoneCallListener, PhoneStateListener.LISTEN_CALL_STATE);
获取系统服务是运行在在当前进程中的:ContextImpl.java
registerService(TELEPHONY_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new TelephonyManager(ctx.getOuterContext());
}});
//TelephonyManager远程代理服务对象TelephonyRegistry:
public void listen(PhoneStateListener listener, int events) {
//注册监听对象
sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
}
TelephonyManager远程代理服务对象TelephonyRegistry:
注册对象是在服务TelephonyRegistry中完成:
public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
boolean notifyNow) {
synchronized (mRecords) {
// register
Record r = null;
find_and_add:
{
IBinder b = callback.asBinder();
final int N = mRecords.size();
for (int i = 0; i < N; i++) {
r = mRecords.get(i);
if (b == r.binder) {
break find_and_add;
}
}
// ArrayList< Record >
r = new Record();
r.binder = b;
r.callback = callback;
r.pkgForDebug = pkgForDebug;
mRecords.add(r);
}
}
4 触发通知状态变化
public void notifyPhoneState(Phone sender) {
//remote对象TelephonyRegistry
mRegistry.notifyCallState(convertCallState(sender.getState()), incomingNumber);
}
TelephonyRegistry服务触发状态变化通知:
public void notifyCallState(int state, String incomingNumber) {
synchronized (mRecords) {
mCallState = state;
mCallIncomingNumber = incomingNumber;
for (Record r : mRecords) {
if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
// remote对象回调
r.callback.onCallStateChanged(state, incomingNumber);
}
}
}
//发送广播
broadcastCallStateChanged(state, incomingNumber);
}
这里看到通过两种方式通知Phone状态有变化:接口回调和发送广播
接口回调:PhoneStateListener中的IPhoneStateListener实例callback
IPhoneStateListener callback = new IPhoneStateListener.Stub() { public void onCallStateChanged(int state, String incomingNumber) { //Handler发送消息异步处理 Message.obtain(mHandler, LISTEN_CALL_STATE, state, 0, incomingNumber).sendToTarget(); } } Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case LISTEN_CALL_STATE: //调用子类MyPhoneCallListener接口 PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj); break; } } }
发送广播:
private void broadcastCallStateChanged(int state, String incomingNumber) {
//ACTION:android.intent.action.PHONE_STATE 正是广播所监听的ACTION
Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).
toString());
if (!TextUtils.isEmpty(incomingNumber)) {
intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
}
mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
}