您的位置:首页 > 移动开发 > Android开发

Android 解决双卡双待手机解析短信异常

2014-04-16 12:09 429 查看
开发中,难免会遇到各种各样的适配问题,尤其是经过深度修改定制过的系统,有的无论是软硬件上都有很大的区别,这里不得不提到一种奇葩的机型,没错,那就是双卡双待的手机(比如XT800, A60, S8600 , Lenovo A750,中兴V889D等).由于是双SIM卡,而且两个卡槽支持的运营商或者网络制式不一定相同,比如一个卡槽支持WCDMA,另一个却只支持GSM ,导致用正常方法解析短信很容易遇到异常

想深入了解双卡双待手机短信发送与接收流程的话,请看我之前关于 MMS的分析:

Android 短信模块分析(四) MMS之短信的发送与接收

这里先看下解决方案,这里需要以反射的方式解析不同类型的短信,并且对于不同机型,需对应地进行调整适配:

获取短信信息,注意:为解决双卡双待手机解析短信异常问题,使用Java反射机制,优先解析GSM类型的短信,假如解析失败才按CDMA类型的短信进行解析)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public
static
SmsMessage[] getSmsMessage(Intent intent) {

SmsMessage[] msgs =
null
;

Object messages[] = (Object[]) intent.getSerializableExtra(pdus);

int
len =
0
;

if
(
null
!= messages && (len =messages.length) >
0
) {

msgs =
new
SmsMessage[len];

try
{

for
(
int
i =
0
;i <len;i++) {

SmsMessage message =
null
;

if
(GSM.equals(intent.getStringExtra(from))) {
// 适配MOTO XT800双卡双待手机

message = createFromPduGsm((
byte
[]) messages[i]);

}
else
if
(CDMA.equals(intent.getStringExtra(from))) {
// 适配MOTO XT800双卡双待手机

message = createFromPduCdma((
byte
[]) messages[i]);

}
else
{

message = SmsMessage.createFromPdu((
byte
[]) messages[i]);
// 系统默认的解析短信方式

}

if
(
null
== message) {
// 解决双卡双待类型手机解析短信异常问题

message = createFromPduGsm((
byte
[]) messages[i]);

if
(
null
== message) {

message = createFromPduCdma((
byte
[]) messages[i]);

}

}

if
(
null
!= message) {

msgs[i] = message;

}

}

}
catch
(Exception e) {

e.printStackTrace();

msgs =getSmsMessageByReflect(intent);
// 解决双卡双待手机解析短信异常问题

}
catch
(Error er) {

er.printStackTrace();

msgs =getSmsMessageByReflect(intent);
// 解决双卡双待手机解析短信异常问题

}

}

return
msgs;

}


反射方式获取短信


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**

 
* 使用Java反射机制获取短信信息(解决双卡双待手机解析短信异常问题,优先解析GSM类型的短信,假如解析失败才按CDMA类型的短信进行解析)

 
*

 
* @param intent

 
* @return

 
*/

private
static
SmsMessage[] getSmsMessageByReflect(Intent intent) {

SmsMessage[] msgs =
null
;

Object messages[] = (Object[]) intent.getSerializableExtra(pdus);

int
len =
0
;

if
(
null
!= messages && (len =messages.length) >
0
) {

msgs =
new
SmsMessage[len];

try
{

for
(
int
i =
0
;i <len;i++) {

SmsMessage message =createFromPduGsm((
byte
[]) messages[i]);

if
(
null
== message) {

message = createFromPduCdma((
byte
[]) messages[i]);

}

if
(
null
!= message) {

msgs[i] = message;

}

}

}
catch
(SecurityException e) {

e.printStackTrace();

}
catch
(IllegalArgumentException e) {

e.printStackTrace();

}
catch
(ClassNotFoundException e) {

e.printStackTrace();

}
catch
(NoSuchMethodException e) {

e.printStackTrace();

}
catch
(IllegalAccessException e) {

e.printStackTrace();

}
catch
(InvocationTargetException e) {

e.printStackTrace();

}
catch
(InstantiationException e) {

e.printStackTrace();

}

}

return
msgs;

}


通过Java反射机制解析GSM类型的短信:


1
2
3

private
static
SmsMessage createFromPduGsm(
byte
[] pdu)
throws
SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

return
createFromPdu(pdu, com.android.internal.telephony.gsm.SmsMessage);

}


解析CDMA类型的短信


1
2
3

private
static
SmsMessage createFromPduCdma(
byte
[] pdu)
throws
SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

return
createFromPdu(pdu, com.android.internal.telephony.cdma.SmsMessage);

}


解析GSM或者CDMA类型的短信


1
2
3
4
5
6
7
8
9
10
11

private
static
SmsMessage createFromPdu(
byte
[] pdu, String className)
throws
ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {

Class<!--?-->clazz = Class.forName(className);

Object object = clazz.getMethod(createFromPdu,
byte
[].
class
).invoke(clazz.newInstance(), pdu);

if
(
null
!= object) {

Constructor<!--?-->constructor = SmsMessage.
class
.getDeclaredConstructor(Class.forName(com.android.internal.telephony.SmsMessageBase));

constructor.setAccessible(
true
);

return
(SmsMessage) constructor.newInstance(object);

}
else
{

return
null
;

}

}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: