SmsManager在三星设备上崩溃

5

我在尝试发送多部分SMS短信时,从三星设备接收到了崩溃日志,导致崩溃的是以下代码行:

SmsManager.getDefault().sendMultipartTextMessage(phone, null, SmsManager.getDefault().divideMessage(message), null, null)

其中phone是一个完全指定的非空电话号码,而message是一个长字符串(长达300个字符),只包含ASCI符号。可能值得注意的是,它包含\n\n用于文本分隔。

以下是崩溃日志:

Fatal Exception: java.lang.NullPointerException
Attempt to invoke interface method 'java.util.Iterator java.lang.Iterable.iterator()' on a null object reference
android.os.Parcel.readException (Parcel.java:1699)
android.os.Parcel.readException (Parcel.java:1646)
com.android.internal.telephony.ISms$Stub$Proxy.sendMultipartTextForSubscriber (ISms.java:1719)
android.telephony.SmsManager.sendMultipartTextMessageInternal (SmsManager.java:576)
android.telephony.SmsManager.sendMultipartTextMessage (SmsManager.java:544)

我尝试查看 SmsManager 的源代码,以查找崩溃日志中指定的行,但没有找到线索 - 看起来它已被OEM修改。

这也不应该是权限问题,因为我在执行 sendMultipartTextMessage 前会检查短信权限。

崩溃发生在三星Galaxy S6和J530F手机上。除了这两种手机,从未有人报告过此问题。不幸的是,我没有三星设备来进行测试。

有人遇到过这个问题吗?先谢谢了!


请添加更多细节并尽可能编写当前类的完整代码。 - Maziyar Grami
你怎么确定这段代码首先会抛出异常?能否请你发送完整的堆栈跟踪信息? - ygngy
如果send方法首次抛出异常,您应该将SmsManager.getDefault().divideMessage(message)放在send参数之外,以更好地找到异常位置。更好的做法是,您可以通过将其放置在其他位置(例如“关于”活动的onCreate中)并使用某些常量消息值进行测试来测试此函数。 - ygngy
@BAHMAN 你可以从堆栈跟踪中看到它在android.telephony.SmsManager.sendMultipartTextMessage(SmsManager.java:544)崩溃,这是我所提到的方法。正如我所说,这种崩溃只发生在三星设备上,而我无法在自己的设备上重现它。 - Roman Samoilenko
Genymotion模拟器有一些三星模拟器映像。你能通过这个模拟器测试这段代码吗?将这些divideMessage(message)sendMultipartTextMessage放在某个测试类的两行不同代码中,以更好地找到问题。 - ygngy
2个回答

0

为三星Galaxy S2提供特殊实现,该设备在4.0.3更新中存在一个恶性bug。

查看此bug

private static class GalaxyS2IcsSmsManager extends DonutSmsManager {

    private static Method method;

    static {
        try {
            Class<?> classSmsManager = Class.forName("android.telephony.SmsManager");

            Class<?> paramTypes[] = new Class[9];

            paramTypes[0] = String.class;
            paramTypes[1] = String.class;
            paramTypes[2] = ArrayList.class;
            paramTypes[3] = ArrayList.class;
            paramTypes[4] = ArrayList.class;
            paramTypes[5] = Boolean.TYPE;
            paramTypes[6] = paramTypes[7] = paramTypes[8] = Integer.TYPE;

            method = classSmsManager.getMethod("sendMultipartTextMessage", paramTypes);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

-1

迭代器通常用于迭代一个List,而sendMultipartTextMessage有三个参数,这些参数都是List子类型(具体来说是ArrayList)。

由于出现了崩溃,我建议始终确保这些参数不为空。因此,不要传递null,而应该像这样传递一个空的ArrayList

SmsManager manager = SmsManager.getDefault();
ArrayList<String> parts = manager.divideMessage(message);
manager.sendMultipartTextMessage(phone, null, parts != null ? parts : new ArrayList(),
    new ArrayList(), new ArrayList());

请注意,我尚未尝试此解决方案,如果此解决方案导致其他错误,则最后两个参数可能需要保持null。此外,这可能会在其他地方引起错误,但希望不会崩溃。您可以在当前实现所在的try块内使用try-catch块,在发生异常的情况下,它将被捕获并执行此解决方案的代码或以不同方式处理(向用户显示错误消息)。在这种情况下,如果正确实施,可以将错误最小化。

1
这并没有回答问题,而且所做的假设是错误的。无论如何,如果消息为空,SmsManager.divideMessage都会抛出异常,并且没有必要为发送和传递挂起意图参数传递new ArrayList(),更不用说那些根本不相关了。 - Roman Samoilenko
正如之前提到的,这个崩溃只发生在三星设备上。如果我的实现有问题,它也会在其他设备上崩溃。 - Roman Samoilenko
但是你怎么确定 divideMessage 的输出不会返回一个 nullArrayList 呢?另外我提到过,你可能不需要将 new ArrayList() 传递给最后两个参数,即发送和交付挂起意图参数。我相信尝试一下不会有什么损失,而且可能会解决崩溃问题。基本上,异常告诉我们正在处理某个列表参数,但它为空,这不能被误解为其他东西。 - ahasbini
1
更进一步解释一下,我的意思是说,在三星设备上,divideMessage可能会有一些奇怪的行为/实现(到目前为止)。这个解决方案被提出作为设备兼容性的变通方法,以调整行为,以防发生这种情况。 - ahasbini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接