以编程方式发送大量短信 - 递送报告问题

问题描述

我有一个 android 应用,它在短时间内发送了大量消息,该应用需要处理交付报告。这一切都很好,应用很稳定,运行没有任何崩溃,发送消息,交付报告工作正常......一段时间没问题。

假设我在发送一条消息后发送一条消息(成功发送前一条消息之后的每条消息 - 我正在查看 smsSent PendingIntent - 我只能在 hasOnProgressSend == false 时发送新消息)。交付报告可以正常工作约 1-2 小时。然后交付报告表现得很奇怪。不断丢弃一些交付报告。

所以发送完成后,大约 7 小时后,大约 8000 条短信发送报告停止出现,但有很多消息已收到,但应用程序没有收到发送报告。

但现在奇怪的部分来了:)。第二天我尝试了另一个测试并发送了另外 8000 条消息。消息立即开始发送给收件人,但我收到的交付报告来自前一天,而不是最后一天到达 broadcastReceiver。我尝试更换了我的 SIM 卡,并且还收到了前一天发送的消息。

重新启动应用程序后,一切都一样,最后一天的交付报告。但是在我重新启动设备后,它仍然表现得像昨天一样(大约 1-2 小时工作正常,然后交付报告速度变慢了很多)。

总结一下: 我收到交付报告就好了,直到看起来某些设备队列已满。此后交付报告非常缓慢。另一天,当我再次开始发送(使用新 SIM 卡)时,我的交付 broadcastReceiver 从昨天发送的消息中获取交付报告,而昨天发送的报告没有出现。我重新启动应用程序后是一样的。在我重新启动设备后,它开始表现得像第一天一样。因此,如果我的 brodactReceivers 是在我的 Activity 的 onCreate 方法注册的,并且应用程序重新启动无济于事,这一定是我需要在我的应用程序中以某种方式处理的一些 android 队列问题(可能会减慢发送速度,在成功发送后进行更多延迟)如果几条未传递的消息大于某个值,则停止发送消息或停止发送?)

谢谢,很抱歉问这么大的问题:)

我在 onCreate 中注册了两个 broadcarsReceiver:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ... check all persmissions
      
        receiverSentGlobal = new broadcastReceiver() {
            @Override
            public void onReceive(Context context,Intent intent) {
                hasOnProgressSend = false;
                
                JSONObject currentMsgSentStatus = new JSONObject();
                try {
                    currentMsgSentStatus.put("msg_id",intent.getStringExtra("msg_id"));
                    currentMsgSentStatus.put("sim_id",intent.getStringExtra("sim_id"));
                } catch (JSONException e) {
                    e.printstacktrace();
                }
                switch (getResultCode()) {
                    case Activity.RESULT_OK:
                        try {
                            currentMsgSentStatus.put("status","OK");
                        } catch (JSONException e) {
                            e.printstacktrace();
                        }
                       
                        break;
                    case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                        try {
                            currentMsgSentStatus.put("status","GENERIC_FAILURE");
                        } catch (JSONException e) {
                            e.printstacktrace();
                        }
                        break;
                    case SmsManager.RESULT_ERROR_NO_SERVICE:
                        try {
                            currentMsgSentStatus.put("status","NO_SERVICE");
                        } catch (JSONException e) {
                            e.printstacktrace();
                        }
                        break;
                    case SmsManager.RESULT_ERROR_NULL_PDU:
                        try {
                            currentMsgSentStatus.put("status","NULL_PDU");
                        } catch (JSONException e) {
                            e.printstacktrace();
                        }
                        break;
                    case SmsManager.RESULT_ERROR_RAdio_OFF:
                        try {
                            currentMsgSentStatus.put("status","RAdio_OFF");
                        } catch (JSONException e) {
                            e.printstacktrace();
                        }
                        break;
                }
                sendStatus.put(currentMsgSentStatus);
            }
        };
        registerReceiver(receiverSentGlobal,new IntentFilter(ACTION_SMS_SENT));

        receiverDeliveryGlobal = new broadcastReceiver() {
            @RequiresApi(api = Build.VERSION_CODES.Q)
            @Override
            public void onReceive(Context context,Intent intent) {
                JSONObject currentMsgDeliveryStatus = new JSONObject();
                try {
                    currentMsgDeliveryStatus.put("msg_id",intent.getStringExtra("msg_id"));
                    currentMsgDeliveryStatus.put("sim_id",intent.getStringExtra("sim_id"));
                } catch (JSONException e) {
                    e.printstacktrace();
                }
                switch (getResultCode()) {
                    case Activity.RESULT_OK:
                        try {
                            currentMsgDeliveryStatus.put("status","DELIVERED");
                        } catch (JSONException e) {
                            e.printstacktrace();
                        }
                        break;
                    case Activity.RESULT_CANCELED:
                        try {
                            currentMsgDeliveryStatus.put("status","CANCELED");
                        } catch (JSONException e) {
                            e.printstacktrace();
                        }
                        break;
                }
                deliveryStatus.put(currentMsgDeliveryStatus);
            }
        };
        registerReceiver(receiverDeliveryGlobal,new IntentFilter(ACTION_SMS_DELIVERED));

    ... 
    }

我的sendSMS方法

SmsManager sm;
... there is also some code to handle subscription,but let's make it more simple
sm = SmsManager.getDefault();


 ArrayList<String> parts = sm.divideMessage(msg);

            Intent iSent = new Intent(ACTION_SMS_SENT);
            iSent.putExtra("msg_id",msgid);
            iSent.putExtra("sim_id",String.valueOf(lastSendSimId));
            PendingIntent piSent = PendingIntent.getbroadcast(this,Integer.parseInt(msgid),iSent,PendingIntent.FLAG_ONE_SHOT);

            //Intent iDel = new Intent(ACTION_SMS_DELIVERED+msgid);

            Intent iDel = new Intent(ACTION_SMS_DELIVERED);
            iDel.putExtra("msg_id",msgid);
            iDel.putExtra("sim_id",String.valueOf(lastSendSimId));
            PendingIntent piDel = PendingIntent.getbroadcast(this,iDel,PendingIntent.FLAG_ONE_SHOT);

if (parts.size() == 1)
            {
                msg = parts.get(0);
                sm.sendTextMessage(number,null,msg,piSent,piDel);
            }
            else
            {
                ArrayList<PendingIntent> sentPis = new ArrayList<PendingIntent>();
                ArrayList<PendingIntent> delPis = new ArrayList<PendingIntent>();

                int ct = parts.size();
                for (int i = 0; i < ct; i++)
                {
                    sentPis.add(i,piSent);
                    delPis.add(i,piDel);
                }

                sm.sendMultipartTextMessage(number,parts,sentPis,delPis);
            }
            hasOnProgressSend = true;

编辑 1: 刚刚找到 - 通过向 2 个号码发送消息进行测试。 A号码在在线设备中,B在关机设备中。直到大约 250 条未发送到 B 的消息,应用程序正在接收 A 的发送报告。在 A 的 250 条未发送消息发送通知停止后,应用程序将停止发送。在为 B 供电后,所有发送给 A 和 B 的消息的所有通知都出现了。因此,有一些队列大约有 250 个等待传递报告。有什么办法可以将传递过程的生命周期限制在 10 分钟左右?

解决方法

好的,发现问题。设备上有大约 250 个待处理的交付意图的限制。所以我需要以某种方式限制或取消旧的交付待定意图。