1、在Android中我们可以通过下面这段代码获取SIM的iccid,关于手机中常用术语简介可参考《Android中CS域和PS域以及手机中常用术语简介》

            TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);        String simSerialNumber = telephonyManager.getSimSerialNumber();

注:ICCID (Integrate circuit card identity ) 集成电路卡识别码(固化在手机SIM 卡中) ICCID 为IC 卡的唯一识别号码,共有20 位数字组成。

但调用这个方法有时候并不能获取到20位完整的SIM iccid,怀着好奇心看了下android源码,下面就来一层层揭开这面纱。

    frameworks/base/telephony/java/android/telephony/TelephonyManager.java        public String getSimSerialNumber(int subId) {        android.util.SeempLog.record_str(388, ""+subId);        try {            IPhoneSubInfo info = getSubscriberInfo();            if (info == null)                return null;            return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName());        } catch (RemoteException ex) {            return null;        } catch (NullPointerException ex) {            // This could happen before phone restarts due to crashing            return null;        }    }

getIccSerialNumberForSubscriber是在PhoneSubInfoController.java中实现,具体方式如下:

frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneSubInfoController.java        public String getIccSerialNumberForSubscriber(int subId, String callingPackage) {        Phone phone = getPhone(subId);        if (phone != null) {            if (!checkReadPhoneState(callingPackage, "getIccSerialNumber")) {                return null;            }            return phone.getIccSerialNumber();        } else {            loge("getIccSerialNumber phone is null for Subscription:" + subId);            return null;        }    }

getIccSerialNumber是在GsmCdmaPhone.java实现:

frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaPhone.java    @Override    public String getIccSerialNumber() {        IccRecords r = mIccRecords.get();        if (!isPhoneTypeGsm() && r == null) {            // to get ICCID form SIMRecords because it is on MF.            r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP);        }        return (r != null) ? r.getIccId() : null;    }

getIccId是IccRecords.java中定义的,但其赋值是在IccRecords的两个子类SIMRecords.java和RuimRecords.java中赋值的

frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/SIMRecords.java        // ***** Overridden from Handler    @Override    public void handleMessage(Message msg) {        AsyncResult ar;        AdnRecord adn;        byte data[];        boolean isRecordLoadResponse = false;        if (mDestroyed.get()) {            loge("Received message " + msg + "[" + msg.what + "] " +                    " while being destroyed. Ignoring.");            return;        }        try { switch (msg.what) {            case EVENT_GET_ICCID_DONE:                isRecordLoadResponse = true;                ar = (AsyncResult)msg.obj;                data = (byte[])ar.result;                if (ar.exception != null) {                    break;                }                mIccId = IccUtils.bcdToString(data, 0, data.length);                mFullIccId = IccUtils.bchToString(data, 0, data.length);                log("iccid: " + SubscriptionInfo.givePrintableIccid(mFullIccId));            break;            ...            default:                super.handleMessage(msg);   // IccRecords handles generic record load responses        }}catch (RuntimeException exc) {            // I don't want these exceptions to be fatal            logw("Exception parsing SIM record", exc);        } finally {            // Count up record load responses even if they are fails            if (isRecordLoadResponse) {                onRecordLoaded();            }        }    }

EVENT_GET_ICCID_DONE是在IccFileHandler.java@loadEFTransparent里调用

        public void loadEFTransparent(int fileid, Message onLoaded) {        Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,                        fileid, 0, onLoaded);        mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);    }

这里会调用RIL.java里的iccIOForApp向modem发送查询请求,有结果返回后便会调用EVENT_GET_ICCID_DONE对mIccId进行赋值

frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/IccUtils.java        public static String    bcdToString(byte[] data, int offset, int length) {        StringBuilder ret = new StringBuilder(length*2);        for (int i = offset ; i < offset + length ; i++) {            int v;            v = data[i] & 0xf;            if (v > 9)  break;            ret.append((char)('0' + v));            v = (data[i] >> 4) & 0xf;            // Some PLMNs have 'f' as high nibble, ignore it            if (v == 0xf) continue;            if (v > 9)  break;            ret.append((char)('0' + v));        }        return ret.toString();    }

可以看到在bcdToString时,如果data里面包含非0-9的字符,就只取第一个非0-9的字段
eg:8986011785a113040534 ,按照这个方法获取的为8986011785

当然在GsmCdmaPhone@getFullIccSerialNumber,这个方法在调用的时候,只是调用了IccUtils.bchToString

 /**     * Some fields (like ICC ID) in GSM SIMs are stored as nibble-swizzled BCH     */    public static String    bchToString(byte[] data, int offset, int length) {        StringBuilder ret = new StringBuilder(length*2);        for (int i = offset ; i < offset + length ; i++) {            int v;            v = data[i] & 0xf;            ret.append("0123456789abcdef".charAt(v));            v = (data[i] >> 4) & 0xf;            ret.append("0123456789abcdef".charAt(v));        }        return ret.toString();    }

此时获取到的iccid才是完整的,然而现在很多sim卡的iccid包含0-f之外的字符,还是不能取到完整的iccid,如果你有好的方案,欢迎留言指教,谢谢!
eg:8986011785N113040534,不能获取到正确完整的20位iccid

更多相关文章

  1. android 连接服务器的方法及安全性问题
  2. android中Bitmap的放大和缩小的方法
  3. Android遍历文件Listfile返回值为null问题解决方法适用Android8.
  4. Android 最新获取手机内置存储大小,SD卡存储空间大小方法
  5. Android 启动浏览器的方法
  6. Android根据电量变化为不同图片的方法【电池电量提示】
  7. Android之日期时间选择器使用方法
  8. Android 图片旋转(使用Matrix.setRotate方法)
  9. Android Http请求失败解决方法

随机推荐

  1. Android原生(Native)C开发
  2. Android之Activity的四种启动模式
  3. Android 实现动画方式
  4. Android学习笔记——入门框
  5. android 简易任务管理器源码
  6. android:screenOrientation的说明
  7. Android Studio导入项目常出现的问题
  8. android超炫的图片浏览器
  9. android常用函数参数补充
  10. TextView跑马灯效果