Phone状态的监听机制

一 监听手机Phone状态

在手机里面监听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);
}

Phone状态的监听机制

时间: 2024-10-11 17:15:14

Phone状态的监听机制的相关文章

.NET事件监听机制的局限与扩展

.NET中把“事件”看作一个基本的编程概念,并提供了非常优美的语法支持,对比如下C#和Java代码可以看出两种语言设计思想之间的差异. // C#someButton.Click += OnSomeButtonClick; // JavasomeButton.addActionListener( new ActionListener(){ public void actionPerformed(){ ... } }); 在我们的软件中就大量使用事件来对监听者与发布者解耦,但也遇到了一些局限,在这

Java 中的事件监听机制

看项目代码时遇到了好多事件监听机制相关的代码.现学习一下: java事件机制包含三个部分:事件.事件监听器.事件源. 1.事件:继承自java.util.EventObject类,开发人员自己定义. package com.shuyan.javatest.EventTest; import java.util.EventObject; public class DnsEvent extends EventObject { private String userData; private long

Android的事件处理---监听机制和回调机制-总结

Android有两种方式的事件处理: 1.基于回调的事件处理    2.基于监听器的事件处理 一.先来大概说明一下监听器的事件处理的实现原理 (学过AWT .Swing的同学对监听器基本有一点了解.) ===>>>  监听事件是一种“面向对象”的事件处理  <<<=== 涉及三类对象: Event Source(事件源): 也就是按钮,菜单,窗口等 Event(事件):就是操作的状态,单击.触摸.长按.双击等 Event Listener(事件监听器):对用户的操作做出

JAVA事件监听机制学习

//事件监听机制 import java.awt.*; import java.awt.event.*; public class TestEvent { public static void main(String[] args) { Frame f = new Frame("Test"); Button b = new Button("Press Me!"); Monitor bh = new Monitor(); //实现了某种监听器接口的类的对象 b.add

观察者模式与事件监听机制

一.观察者模式 1.1 概述 有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己.它类似B/S架构模式,构建一个服务端,多个客户端显示.其实这个主题对象就像是一个信息源,当信息源的状态发送变化时,它会通知所有订阅者,使它们进行相应的处理.在百度百科中的例子是,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上. 1

深入理解Spring的容器内事件发布监听机制

目录 1. 什么是事件监听机制 2. JDK中对事件监听机制的支持 2.1 基于JDK实现对任务执行结果的监听 3.Spring容器对事件监听机制的支持 3.1 基于Spring实现对任务执行结果的监听 4.Spring事件监听源码解析 4.1 初始化事件发布器流程 4.2 注册事件监听器流程 4.3 容器事件发布流程 5.总结 1. 什么是事件监听机制 在讲解事件监听机制前,我们先回顾下设计模式中的观察者模式,因为事件监听机制可以说是在典型观察者模式基础上的进一步抽象和改进.我们可以在JDK或

Java中的事件监听机制

鼠标事件监听机制的三个方面: 1.事件源对象: 事件源对象就是能够产生动作的对象.在Java语言中所有的容器组件和元素组件都是事件监听中的事件源对象.Java中根据事件的动作来区分不同的事件源对象,动作发生在哪个组件上,那么该组件就是事件源对象 2.事件监听方法: addMouseListener(MouseListener ml) ;该方法主要用来捕获鼠标的释放,按下,点击,进入和离开的动作:捕获到相应的动作后,交由事件处理类(实现MouseListener接口)进行处理. addAction

服务中电话状态的监听

public class AddressService extends Service { public static final String tag = "AddressService"; private TelephonyManager mTM; private MyPhoneStateListener mPhoneStateListener; private final WindowManager.LayoutParams mParams = new WindowManager

4.JAVA之GUI编程事件监听机制

事件监听机制的特点: 1.事件源 2.事件 3.监听器 4.事件处理 事件源:就是awt包或者swing包中的那些图形用户界面组件.(如:按钮) 事件:每一个事件源都有自己特点有的对应事件和共性事件.(如:鼠标单击事件) 监听器:将可以触发某一事件的动作(不止一个动作)都已经封装到了监听器中. 以上三者,在java中都已经定义好了,直接获取其对象来用就可以了. 我们要做的事情是,就是对产生的动作进行处理. 图解事件监听机制: 4.JAVA之GUI编程事件监听机制,布布扣,bubuko.com