zoukankan      html  css  js  c++  java
  • 自动读取短信中心号码

    前言

    短信中心号码概念

    短信中心号码类似信息服务器,如果信息中心号码不正确,短消息是无法发送成功的,各个地区都有自己的信息中心号码,其中移动以+86138开头,关于该号码的获取这举例说明。

    获取方法

    1、调用Phone中的getSmscAddress(Message message)方法,其中参数的message为获取到结果后发送消息给mHandler,并查询结果AsyncResult的result属性中。
        		 phone=PhoneFactory.getDefaultPhone();
        		 phone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE)); 
    

    :2、mHandler实现代码

    private Handler mHandler = new Handler() {
            public void handleMessage(Message msg) {
                AsyncResult ar;
                switch (msg.what) {
                    case EVENT_QUERY_SMSC_DONE:
                        ar= (AsyncResult) msg.obj;
                        if (ar.exception != null) {
                        } else {
    		// TODO: handle exception
    		mSmsServiceCenterPref.setSummary((String)ar.result);
    		          }
                        }
                   
                    default:
                        break;
                }
            }
        };
    

    原理分析

    分析到这大家可能觉得短信中心号码的获取非常简单,但如果要实现该功能仅加上这几行代码,大家可以动手试试,会发现该功能不仅没有实现,甚至还抛出了一个“PhoneFactory.getDefaultPhone must be called from Looper thread”这样的异常。
    :1、原因造成该异常的根本原因在通过PhoneFactory类的getDefaultPhone()方法返回一个Phone对象,我们可以进入这个类去看这个函数的实现

       public static Phone getDefaultPhone() {
    
          if (sLooper != Looper.myLooper()) {
               throw new RuntimeException(
                   "PhoneFactory.getDefaultPhone must be called from Looper thread");
           }
        
    
           if (!sMadeDefaults) {
               throw new IllegalStateException("Default phones haven't been made yet!");
           }
          return sProxyPhone[getDefaultSubscription()];
       }
    

    该异常由于Looper对象不一样,Looper.myLooper()该对象是指调用getDefaultPhone方法的所在的进程的looper对象,sLooper对象又指的是谁的looper对象,在那赋值?在调用getDefaultPhone时会返回sProxyPhone[getDefaultSubscription()],该数组又是在那赋值的了?

    首先,手机启动时会启动phone进程,phone会调用到PhoneApp.java的onCreate方法,在该方法中会调用PhoneFactory.makeDefaultPhones方法。然后,在makeDefaultPhones函数中,会做两件事情,一是初始化sLooper,二是给phone sProxyPhone[]数组赋值。以下是该方法的核心实现:

     if (!sMadeDefaults) {
                    sLooper = Looper.myLooper();
                    sContext = context;
    
                    if (sLooper == null) {
                        throw new RuntimeException(
                            "PhoneFactory.makeDefaultPhone must be called from Looper thread");
                    }
           sProxyPhone = new PhoneProxy[numPhones];
           for (int i = 0; i < numPhones; i++) {
                        int phoneType = getPhoneType(networkMode[i]);
                        Log.i(LOG_TAG, "get Phone Type:"+ phoneType);
    
                        if (phoneType == Phone.PHONE_TYPE_GSM) {
                            sProxyPhone[i] = new PhoneProxy(new GSMPhone(context,
                                    sCommandsInterface[i], sPhoneNotifier, false, dct, i));
                            Log.i(LOG_TAG, "Creating GSMPhone");
                        } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
                            sProxyPhone[i] = new PhoneProxy(new CDMAPhone(context,
                                    sCommandsInterface[i], sPhoneNotifier, false, dct, i));
    
                            Log.i(LOG_TAG, "Creating CDMAPhone");
                        }
                    }
    

    最后,通过前面可以看出sLooper对象是属于phone进程,而Looper.myLooper()是属于调用getDefaultPhone函数的进程,如果调用getDefaultPhone函数的进程和phone进程没有在一个进程空间中执行,则他们的looper对象肯定是不相同的,那么肯定就会抛出“PhoneFactory.getDefaultPhone must be called from Looper thread”这个异常。

    :2、解决方法首先在需要在调用getDefaultPhone函数获取phone对象的进程manifest中声明一下代码

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.android.mms"
            android:sharedUserId="android.uid.phone">
    

    并将具体的Activity声明以下属性:

    android:process="com.android.phone"
    
    小结

    短信中心号码的读取,这里只讲述了应用层最最基本的实现以及一些注意事项,其最最核心的实现还是落实到了中间层和Ril层.参考类Ril.java、PhoneBase.java。

  • 相关阅读:
    (五)《Java编程思想》——final关键字
    eclipse与github建立版本关联、git使用说明
    (四)《Java编程思想》——可变参数列表
    (三)《Java编程思想》——构造函数初始化
    (二)《Java编程思想》——t h i s 关键字
    (一)《Java编程思想》学习——按位运算符、移位运算符
    (三)一个工作任务引起的乱战——udp通信
    (二)一个工作任务引起的乱战——C++程序编译为dll,让C#调用
    (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换
    如何反编译silverlight
  • 原文地址:https://www.cnblogs.com/qiaoxu/p/4120565.html
Copyright © 2011-2022 走看看