以编程方式向多个人发送短信时收到“通用错误”

6

我目前正在尝试开发一款短信应用程序,并允许用户向多人发送短信。

由于短信较长,因此我必须使用下面的sendMultipartTextMessage方法:

private void sendSMS(final String phoneNumber, String message) {
    String SENT = "SMS_SENT";
    String DELIVERED = "SMS_DELIVERED";

    SmsManager sms = SmsManager.getDefault();
    ArrayList<String> parts = sms.divideMessage(message);
    int messageCount = parts.size();

    Log.i("Message Count", "Message Count: " + messageCount);

    ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
    ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();

    PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0);
    PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0, new Intent(DELIVERED), 0);

    for (int j = 0; j < messageCount; j++) {
        sentIntents.add(sentPI);
        deliveryIntents.add(deliveredPI);
    }

    // ---when the SMS has been sent---
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode()) {
            case Activity.RESULT_OK:
                Toast.makeText(getBaseContext(), "SMS sent",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                Toast.makeText(getBaseContext(), "Generic failure",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_NO_SERVICE:
                Toast.makeText(getBaseContext(), "No service",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_NULL_PDU:
                Toast.makeText(getBaseContext(), "Null PDU",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_RADIO_OFF:
                Toast.makeText(getBaseContext(), "Radio off",
                        Toast.LENGTH_SHORT).show();
                break;
            }
        }
    }, new IntentFilter(SENT));

    // ---when the SMS has been delivered---
    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode()) {

            case Activity.RESULT_OK:
                Toast.makeText(getBaseContext(), "SMS delivered",
                        Toast.LENGTH_SHORT).show();
                break;
            case Activity.RESULT_CANCELED:
                Toast.makeText(getBaseContext(), "SMS not delivered",
                        Toast.LENGTH_SHORT).show();
                break;
            }
        }
    }, new IntentFilter(DELIVERED));

    sms.sendMultipartTextMessage(phoneNumber, null, parts, sentIntents, deliveryIntents);
}

当我尝试像这样循环发送消息并将其发送给多个人时,我会遇到一个通用错误,并且消息无法发送。我怀疑这是因为消息可能有3-4部分,即使延迟3000毫秒,安卓系统也无法及时发送消息。

    for (int t = 0; t < array.length; t++) {
        System.out.println("temp: " + array[t].toString());
        try {
            sendSMS(array[t].toString(), message);
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

编辑:上面的代码位于一个AsyncTask中,该AsyncTask在Service中执行。

没有logcat错误,只有Toast会显示“发送短信失败”的泛型错误提示,如果我尝试将其发送给两个联系人,它会显示两次。 - dythe
你在模拟器或设备上遇到了这个错误? - Shashank Kadne
不行,三星Galaxy Note运行在4.1.2版本的Jellybean系统上。 - dythe
2个回答

22

在我看来,你没有采用正确的方法。我正在使用不同的方法,并且它是有效的。我试着解释一下:

你应该保留一个计数器来跟踪所有待处理的意图,因为如果你发送的短信有两个部分,你将会收到两个RESULT_OK(或RESULT_ERROR_*),只有当你接收到所有部分的结果后,才应该继续发送下一条短信。我不喜欢阻塞线程的想法...也许这就是你收到奇怪错误的原因。

我使用我的方法重构了你的代码:

private int mMessageSentParts;
private int mMessageSentTotalParts;
private int mMessageSentCount;

private void startSendMessages(){

    registerBroadCastReceivers();

    mMessageSentCount = 0;
    sendSMS(array[mMessageSentCount].toString(), message);
}

private void sendNextMessage(){
    if(thereAreSmsToSend()){
        sendSMS(array[mMessageSentCount].toString(), message);
    }else{
        Toast.makeText(getBaseContext(), "All SMS have been sent",
                        Toast.LENGTH_SHORT).show();
    }
}

private boolean thereAreSmsToSend(){
    return mMessageSentCount < array.length;
}

private void sendSMS(final String phoneNumber, String message) {
    String SENT = "SMS_SENT";
    String DELIVERED = "SMS_DELIVERED";

    SmsManager sms = SmsManager.getDefault();
    ArrayList<String> parts = sms.divideMessage(message);
    mMessageSentTotalParts = parts.size();

    Log.i("Message Count", "Message Count: " + mMessageSentTotalParts);

    ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
    ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();

    PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0);
    PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0, new Intent(DELIVERED), 0);

    for (int j = 0; j < mMessageSentTotalParts; j++) {
        sentIntents.add(sentPI);
        deliveryIntents.add(deliveredPI);
    }

    mMessageSentParts = 0;
    sms.sendMultipartTextMessage(phoneNumber, null, parts, sentIntents, deliveryIntents);
}

private void registerBroadCastReceivers(){

    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode()) {
            case Activity.RESULT_OK:

                mMessageSentParts++;
                if ( mMessageSentParts == mMessageSentTotalParts ) {
                    mMessageSentCount++;
                    sendNextMessage();
                }

                Toast.makeText(getBaseContext(), "SMS sent",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                Toast.makeText(getBaseContext(), "Generic failure",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_NO_SERVICE:
                Toast.makeText(getBaseContext(), "No service",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_NULL_PDU:
                Toast.makeText(getBaseContext(), "Null PDU",
                        Toast.LENGTH_SHORT).show();
                break;
            case SmsManager.RESULT_ERROR_RADIO_OFF:
                Toast.makeText(getBaseContext(), "Radio off",
                        Toast.LENGTH_SHORT).show();
                break;
            }
        }
    }, new IntentFilter(SENT));

    registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode()) {

            case Activity.RESULT_OK:
                Toast.makeText(getBaseContext(), "SMS delivered",
                        Toast.LENGTH_SHORT).show();
                break;
            case Activity.RESULT_CANCELED:
                Toast.makeText(getBaseContext(), "SMS not delivered",
                        Toast.LENGTH_SHORT).show();
                break;
            }
        }
    }, new IntentFilter(DELIVERED));

}

你的方法只是向单个用户发送消息吗?因为在我的情况下,array[t].toString() 是大约2到3人的数字字符串数组,而不仅仅是一个人。 - dythe
1
它一次只向一个收件人发送消息。我假设你的数组的每个位置都是一个单独的电话号码。 - rciovati
我想问一下,是否有办法在我发送的接收器中检测到电话号码? - dythe
应该是 array[mMessageSentCount].toString()。 - rciovati
谢谢。当我想要发送大量短信时,这非常有帮助,因为我的应用程序会在各种设备上随机停止在某些号码上。现在所有的消息都被发送了。 - gbotha
@rciovati,“new IntentFilter(SENT)”是什么意思?“SENT”和“DELIVERED”是什么? - Atiar Talukdar

2
我使用这段代码时出现了“一般故障”错误。但是我使用了array[mMessageSentCount].toString().trim(),然后问题得到解决,它现在可以正常工作了。谢谢。

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