android -- STK

        SIM卡应用开发工具箱(STK)亦称SIM卡应用程序开发包,估计大家对它最直观的印象就是插入sim卡或usim卡开机时,会出现中国移动动感地带,神州行,中国联通这一类的提示信息,展示的方式可能字符串或一个对话框,这个就是STK的功劳了。简单说明一下,STK是sim/usim卡上的程序,含有STK功能的sim卡/usim卡就是一个单片机。在android手机上,在众多图标中会有一个sim卡应用图标,点击后进入会看到一个主菜单中,有类似品牌信息,发短信,网上营业厅选项等等,菜单内容根据运营商的不同也不完全一样。      

        这个STK涉及的东西还是蛮多的,想完全了解还是要花点力气,http://www.mobile52rd.com/?p=75这篇文章应该来说大概说明了一个学习思路,还不错,转过来分享下,在此先感谢下原作者的辛勤劳动。如果上述文章可看成是一个概述,本文将从一个具体实例来描述下STK的代码是什么样子的。还是回到开机显示的品牌信息吧,这个品牌信息是怎么出来的呢,一起看下相关的代码吧。先上图

android -- STK_第1张图片

            先做点准备工作,开机在GsmPhone的构造函数里会获StkService的一个实例,

            

      public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
        super(notifier, context, ci, unitTestMode);
        mStkService = StkService.getInstance(mCM, mSIMRecords, mContext,
                (SIMFileHandler)mIccFileHandler, mSimCard);
      ......}

           而在stkService的构造方方法里注册一系列的监听,等待从RIL传过来的消息进行处理。我们先关注这个mCmdIf.setOnStkProactiveCmd(this, MSG_ID_PROACTIVE_COMMAND, null);         

      public void setOnStkProactiveCmd(Handler h, int what, Object obj) {
        mStkProCmdRegistrant = new Registrant (h, what, obj);
      }

          这里实例化mStkProCmdRegistrant对象,那么是谁在用呢,在RIL.java的代码,在这我在processUnsolicited ()方法的RIL _UNSOL_STK_PROACTIVE_COMMAND这个分支里,看到这个processUnsolicited()方法,可以知道这是一个主动上报的命令,    

      case RIL_UNSOL_STK_PROACTIVE_COMMAND:
                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mStkProCmdRegistrant != null) {
                    mStkProCmdRegistrant.notifyRegistrant(
                                        new AsyncResult (null, ret, null));
                }
         上面关注的是消息监听是怎么注册的,这个能解释我们为什么能收到消息,在这里有种逆向思维的感觉,下面看收到消息后我们是怎么处理的。
      public void handleMessage(Message msg) {
        switch (msg.what) {
        case MSG_ID_PROACTIVE_COMMAND:      
            StkLog.d(this, "ril message arrived");//RIL消息来了
            String data = null;
            if (msg.obj != null) {
                AsyncResult ar = (AsyncResult) msg.obj;
                if (ar != null && ar.result != null) {
                    try {
                        data = (String) ar.result;
                    } catch (ClassCastException e) {
                        break;
                    }
                }
            }
       mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, data));
            break;
     
     public void sendStartDecodingMessageParams(RilMessage rilMsg) {//又是消息
        Message msg = obtainMessage(CMD_START);//这个CMD_START很关键
        msg.obj = rilMsg;
        sendMessage(msg);
     }

     private class StateStart extends HierarchicalState {
        @Override protected boolean processMessage(Message msg) {
            if (msg.what == CMD_START) {
                if (decodeMessageParams((RilMessage)msg.obj)) {
                    transitionTo(mStateCmdParamsReady);
                }
				…省略无关代码
            }
            return true;
     } }
         这里频繁使用了消息机制,设计的是很巧妙,不过找起来也有点费事,要注意好那些关键的TAG标志,在最一段代码里,decodeMessageParams((RilMessage)msg.obj)看起来要解码了,没错,具体的解码过程看Bertlv.java里的代码就好了。为什么要那么解,要看3gpp 11.14文档。解码结束后又回到stkservice.java的这个分支:         
     case MSG_ID_PROACTIVE_COMMAND:
            cmdParams = (CommandParams) rilMsg.mData;
            if (cmdParams != null) {
                if (rilMsg.mResCode == ResultCode.OK) {
                    handleProactiveCommand(cmdParams);
                } ..省略次要代码..
            }
            break;
         在这个handleProactiveCommand()方法最后的几行代码里会发送带参数的Intent
     Intent  intent = new Intent(AppInterface.STK_CMD_ACTION);//关注这个action
        intent.putExtra("STK CMD",cmdMsg);
        mContext.sendBroadcast(intent);
          然后在StkCmdReceiver.java的onReceive()方法里接收,再启动StkAppService.java,先在onstart()方法做下简单的消息处理,然后转到内部类ServiceHandler
     private final class ServiceHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            int opcode = msg.arg1;
            //省略代码……。
            switch (opcode) {            
            case OP_CMD:
			   //省略代码…..
        handleCmd((StkCmdMessage) msg.obj);

          在handleCmd()里这个launchTextDialog()方法,终于看到Dialog了,里面的代码就是显示一个对话框的,没有什么特别的。这个就是品牌信息显示的对话框了,过程还是蛮曲折的。虽然这只是一个品牌信息的显示,但这里已经可以说明stk应用代码调用的基本流程了,可以借一斑以窥全豹了,要注意好消息的传递,不过STK细节很多,想完全掌握还是要花些功夫的


    



你可能感兴趣的:(android -- STK)