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

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

我有一个 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 个待处理的交付意图的限制。所以我需要以某种方式限制或取消旧的交付待定意图。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?