【问题标题】:Delphi Firemonkey (Android) - Detecting Failed Sending SMSDelphi Firemonkey (Android) - 检测发送短信失败
【发布时间】:2021-10-13 01:13:11
【问题描述】:

当我的应用使用 Android5 时,我可以通过检查 content://sms/sent 和 content://sms/failed 来监控 SMS 是否发送或失败。除了通过我的应用程序,我还可以直接从手机的 SMS 应用程序查看消息及其状态。

现在好旧的 Android5 智能手机已经死了,我正在升级到基于 Android8 (Oreo) 的更新智能手机。但是我遇到了检测已发送短信状态的问题。

首先...我无法再使用手机的默认短信应用“看到”短信。 其次...即使我一一滚动浏览所有消息,我也无法使用我的应用找到短信。

这是我用来发送短信的代码:

smsManager := TJSmsManager.JavaClass.getDefault;
smsTo      := StringToJString(targetstr);
smsarray   := smsmanager.divideMessage(stringtojstring(bodystr));
smsManager.sendmultiparttextMessage(smsTo, nil,smsarray, nil, nil);

虽然这是我用来滚动浏览所有消息的代码:

uri := StrToJURI('content://sms');
smscursor := TAndroidHelper.Activity.getContentResolver.query(uri, nil, nil,nil,nil);
id_id := smscursor.getColumnIndex(StringToJstring('_id'));
idaddress := smscursor.getColumnIndex(StringToJstring('address'));
idbody := smscursor.getColumnIndex(StringToJstring('body'));
idstatus := smscursor.getColumnIndex(StringToJstring('status'));
idthread_id := smscursor.getColumnIndex(StringToJstring('thread_id'));
idtype := smscursor.getColumnIndex(StringToJstring('type'));
smscursor.moveToFirst;

** 使用重复直到循环读取每条短信,直到“islast”为真**

但是无论短信是否成功发送,我都找不到发送的短信。

我需要进行此检测,因为我所在地区的信号强度非常低,大约 20% 的时间短信失败,我的应用应该重新发送预期的消息。

PS:我也尝试从 content://sms/sent 和 content://sms/failed 搜索短信,但无济于事。

无论如何,我的问题是:

  1. 如何让发送的短信显示在手机的默认短信应用中?
  2. 如何正确判断发送短信是否成功?

我在某处读到上面的方法正在使用 API,并且有一种方法可以使用手机的短信应用程序来代替......但我不知道该怎么做。

谢谢。

【问题讨论】:

  • 您需要在调用 sendMultipartTextMessage 时使用 sentIntents 参数。根据the docs,当消息发送时,intent(s) 将被广播,因此您需要设置一个 BroadcastReceiver 来拦截它/它们并检查结果
  • 此外,您可以向 Java example here 学习。它使用服务来发送消息,但是您只需要关注 sentIntents 部分。你可能对deliveredIntents部分感兴趣,也可能不感兴趣。
  • 虽然我不擅长java,但我试图将它与它的Delphi等价物联系起来。但是,我想问一下......假设我能够弄清楚“sententent”部分,这是否意味着无论我的应用程序发送什么短信,手机中都会有一份短信(收件人和短信正文)的副本默认短信应用?
  • 不确定第二部分(即使用 SmsManager 检索发送的消息详细信息),但它应该回答您问题的第 2 部分。有时间我会研究第 1 部分
  • 我发送短信没有显示在手机短信应用程序中的问题是华为的一个错误 - android 8.0 与这篇文章类似stackoverflow.com/questions/51537810/… 我在另一部手机上尝试了奥利奥 8.1,并且有没问题。

标签: android delphi sms firemonkey


【解决方案1】:

为了其他可能处于类似情况的人的利益,需要:

(A) 无需使用手机内置的短信默认应用即可直接从应用发送短信

(B) SMS 长度可以超过默认的 160 个字符限制(使用 sendmultiparttextMessage)

(C) 能够知道 SMS 是否正在处理(基于 PendingIntent 的 onReceive 的结果代码)

已知限制:

  • 在多卡手机下,短信是通过默认卡发送的
  • 如果发送给多个电话收件人,则无法知道哪些失败(如果有)。所以我建议一次向 1 位收件人发送 1 条短信
  • 不检测预期收件人是否收到短信,因为 DeliveryIntent 为 nil

PS:在 Delphi Community Edition 10.4.2 和 Android Oreo 8.0 和 8.1 下测试

我做了什么:

  1. 从此链接How read JPendingIntent in Delphi?的第二个答案中为 BroadcastReceiver(我称之为 BCast.pas)创建并保存一个单元

  2. 在您的 main.pas(假设它保存为 main.pas)中,添加以下内容:

  • 添加到第 1 步中创建的单元(在我的情况下为 bcast.pas)

  • 在uses子句中添加BCAST

  • 为 TBroadCastReceiver 添加变量(即 fbroadcast : Tbroadcastreceiver;)

  • 创建一个 OnReceiveBroadcast 过程 就我而言:

    private
       { Private declarations }
       procedure OnReceiveBroadcast(aContext: JContext; aIntent: JIntent; aResultCode: integer);
    
  • 然后在实现中,为 OnReceiveBroadcast 创建代码:

      procedure Tmain.OnReceiveBroadcast(aContext: JContext; aIntent: JIntent; aResultCode: integer);
      begin
          // ... put in the codes here for the result of the last sms send. //
          // ... use the the value of AResultcode to do the checking //
          // ... AResultcode=1 means ok, other number means possible error //
      end;
    
  • 如下初始化fbroadcast:(我把它们放在我的主播下):

      fbroadcast := TBroadcastReceiver.Create(OnReceiveBroadcast);
      fbroadcast.addactions([StringToJString('xxx')]);
    

    其中 xxx 是用于匹配意图操作的任何字符串

  1. 在sendms中添加一个过程:

     procedure tmain.SendSMSAPI(target,messagestr:string);
     var
       smsManager: JSmsManager; // Androidapi.JNI.Telephony //
       smsTo     : JString;     // Androidapi.JNI.JavaTypes //
       PIntent   : JPendingIntent; // Androidapi.JNI.App //
       smsarray  : jarraylist;
       APIntent  : JArraylist;
       intent    : JIntent;
     begin
       Intent    := TJIntent.Create;
       Intent.setAction(StringToJString('xxx'));
       PIntent   := TJPendingIntent.JavaClass.getBroadcast(TAndroidHelper.Context, 0, Intent, 0);
       APIntent  := Tjarraylist.create;
       APIntent.add(PIntent);
       smsManager:= TJSmsManager.JavaClass.getDefault;
       smsTo     := StringToJString(target); // Androidapi.Helpers //
       smsarray  := smsmanager.divideMessage(stringtojstring(messagestr));
       smsManager.sendmultiparttextMessage(smsTo, nil,smsarray, APIntent, nil); 
     end;
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 2010-11-30
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多