閱讀486 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Android 解決雙卡雙待手機解析短信異常

https://blog.csdn.net/t12x3456/article/details/17339657

開發中,難免會遇到各種各樣的適配問題,尤其是經過深度修改定製過的係統,有的無論是軟硬件上都有很大的區別,這裏不得不提到一種奇葩的機型,沒錯,那就是雙卡雙待的手機(比如XT800, A60, S8600 , Lenovo A750,中興V889D等).由於是雙SIM卡,而且兩個卡槽支持的運營商或者網絡製式不一定相同,比如一個卡槽支持WCDMA,另一個卻隻支持GSM ,導致用正常方法解析短信很容易遇到異常


想深入了解雙卡雙待手機短信發送與接收流程的話,請看我之前關於 MMS的分析:

Android 短信模塊分析(四) MMS之短信的發送與接收


這裏先看下解決方案,這裏需要以反射的方式解析不同類型的短信,並且對於不同機型,需對應地進行調整適配:


獲取短信信息,注意:為解決雙卡雙待手機解析短信異常問題,使用Java反射機製,優先解析GSM類型的短信,假如解析失敗才按CDMA類型的短信進行解析)

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. public static SmsMessage[] getSmsMessage(Intent intent) {  
  2.         SmsMessage[] msgs = null;  
  3.         Object messages[] = (Object[]) intent.getSerializableExtra("pdus");  
  4.         int len = 0;  
  5.         if (null != messages && (len = messages.length) > 0) {  
  6.             msgs = new SmsMessage[len];  
  7.             try {  
  8.                 for (int i = 0; i < len; i++) {  
  9.                     SmsMessage message = null;  
  10.                     if ("GSM".equals(intent.getStringExtra("from"))) { // 適配MOTO XT800雙卡雙待手機  
  11.                         message = createFromPduGsm((byte[]) messages[i]);  
  12.                     } else if ("CDMA".equals(intent.getStringExtra("from"))) { // 適配MOTO XT800雙卡雙待手機  
  13.                         message = createFromPduCdma((byte[]) messages[i]);  
  14.                     } else {  
  15.                         message = SmsMessage.createFromPdu((byte[]) messages[i]); // 係統默認的解析短信方式  
  16.                     }  
  17.                     if (null == message) { // 解決雙卡雙待類型手機解析短信異常問題  
  18.                         message = createFromPduGsm((byte[]) messages[i]);  
  19.                         if (null == message) {  
  20.                             message = createFromPduCdma((byte[]) messages[i]);  
  21.                         }  
  22.                     }  
  23.                     if (null != message) {  
  24.                         msgs[i] = message;  
  25.                     }  
  26.                 }  
  27.             } catch (Exception e) {  
  28.                 e.printStackTrace();  
  29.                 msgs = getSmsMessageByReflect(intent); // 解決雙卡雙待手機解析短信異常問題  
  30.             } catch (Error er) {  
  31.                 er.printStackTrace();  
  32.                 msgs = getSmsMessageByReflect(intent); // 解決雙卡雙待手機解析短信異常問題  
  33.             }  
  34.         }  
  35.         return msgs;  
  36.     }  


反射方式獲取短信

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.      * 使用Java反射機製獲取短信信息(解決雙卡雙待手機解析短信異常問題,優先解析GSM類型的短信,假如解析失敗才按CDMA類型的短信進行解析) 
  3.      *  
  4.      * @param intent 
  5.      * @return 
  6.      */  
  7.     private static SmsMessage[] getSmsMessageByReflect(Intent intent) {  
  8.         SmsMessage[] msgs = null;  
  9.         Object messages[] = (Object[]) intent.getSerializableExtra("pdus");  
  10.         int len = 0;  
  11.         if (null != messages && (len = messages.length) > 0) {  
  12.             msgs = new SmsMessage[len];  
  13.             try {  
  14.                 for (int i = 0; i < len; i++) {  
  15.                     SmsMessage message = createFromPduGsm((byte[]) messages[i]);  
  16.                     if (null == message) {  
  17.                         message = createFromPduCdma((byte[]) messages[i]);  
  18.                     }  
  19.                     if (null != message) {  
  20.                         msgs[i] = message;  
  21.                     }  
  22.                 }  
  23.             } catch (SecurityException e) {  
  24.                 e.printStackTrace();  
  25.             } catch (IllegalArgumentException e) {  
  26.                 e.printStackTrace();  
  27.             } catch (ClassNotFoundException e) {  
  28.                 e.printStackTrace();  
  29.             } catch (NoSuchMethodException e) {  
  30.                 e.printStackTrace();  
  31.             } catch (IllegalAccessException e) {  
  32.                 e.printStackTrace();  
  33.             } catch (InvocationTargetException e) {  
  34.                 e.printStackTrace();  
  35.             } catch (InstantiationException e) {  
  36.                 e.printStackTrace();  
  37.             }  
  38.         }  
  39.         return msgs;  
  40.     }  



通過Java反射機製解析GSM類型的短信:

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. private static SmsMessage createFromPduGsm(byte[] pdu) throws SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {  
  2.         return createFromPdu(pdu, "com.android.internal.telephony.gsm.SmsMessage");  
  3.     }  

解析CDMA類型的短信

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. private static SmsMessage createFromPduCdma(byte[] pdu) throws SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {  
  2.     return createFromPdu(pdu, "com.android.internal.telephony.cdma.SmsMessage");  
  3. }  

解析GSM或者CDMA類型的短信

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. private static SmsMessage createFromPdu(byte[] pdu, String className) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {  
  2.         Class<?> clazz = Class.forName(className);  
  3.         Object object = clazz.getMethod("createFromPdu"byte[].class).invoke(clazz.newInstance(), pdu);  
  4.         if (null != object) {  
  5.             Constructor<?> constructor = SmsMessage.class.getDeclaredConstructor(Class.forName("com.android.internal.telephony.SmsMessageBase"));  
  6.             constructor.setAccessible(true);  
  7.             return (SmsMessage) constructor.newInstance(object);  
  8.         } else {  
  9.             return null;  
  10.         }  
  11.     }  

最後更新:2017-04-03 12:54:02

  上一篇:go HI3531編譯helloworld,執行錯誤
  下一篇:go 使用Sublime 2 配置GoLang語言