简体   繁体   English

Delphi Firemonkey (Android) - 检测发送短信失败

[英]Delphi Firemonkey (Android) - Detecting Failed Sending SMS

when my app was using Android5, I can monitor if the SMS was sent or failed by checking the content://sms/sent and content://sms/failed.当我的应用程序使用 Android5 时,我可以通过检查 content://sms/sent 和 content://sms/failed 来监控短信是否已发送或失败。 Aside from via my app, I can also see the message and its status directly from the SMS app of the phone.除了通过我的应用程序,我还可以直接从手机的 SMS 应用程序查看消息及其状态。

Now that the good old Android5 smartphone is dead, I am upgrading to a newer smartphone base on Android8 (Oreo).既然旧的 Android5 智能手机已经死了,我正在升级到基于 Android8 (Oreo) 的更新的智能手机。 However I am facing a problem of detecting the status of the sent sms.但是,我面临检测已发送短信状态的问题。

First... I can no longer "see" the sms using the phone's default SMS app.首先......我无法再使用手机的默认短信应用程序“看到”短信。 Second... I cant also find the sms using my app even if I scroll through all messages one by one.第二...即使我一一滚动所有消息,我也无法使用我的应用程序找到短信。

This is the code I use to send the SMS:这是我用来发送短信的代码:

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

While this is the code I use to scroll through all my messages:虽然这是我用来滚动浏览所有消息的代码:

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;

** using the repeat until loop to read each and every sms until "islast" is true ** ** 使用重复直到循环读取每条短信,直到“islast”为真 **

But I cant find the sent SMS irregardless if the SMS was successfully sent or not.但是无论短信是否成功发送,我都无法找到已发送的短信。

I need to do this detection because the signal strength in my area is very low and around 20% of the time the sms failed, and my app should resend the intended message.我需要做这个检测,因为我所在地区的信号强度非常低,大约 20% 的短信失败,我的应用程序应该重新发送预期的消息。

PS: I also tried searching for the SMS from the content://sms/sent and content://sms/failed but to no avail. PS:我也尝试从 content://sms/sent 和 content://sms/failed 中搜索短信但无济于事。

Anyway, my questions are:无论如何,我的问题是:

  1. How to make the send out sms show up inside the phone's default sms app?如何使发送的短信显示在手机的默认短信应用程序中?
  2. How to correctly determine if the send out sms was successful or not?如何正确判断发送短信是否成功?

I read somewhere that the method above is using the API and there is a way to use the phone's sms app instead... But I dont have any idea how to do it.我在某处读到上面的方法是使用 API 并且有一种方法可以使用手机的短信应用程序代替...但我不知道该怎么做。

Thank you.谢谢你。

For the benefit of others who may be in similar situation that requires to:为了可能处于类似情况的其他人的利益,需要:

(A) Able to send an SMS directly from the app without using the Phone's built-in SMS default app (A) 无需使用手机内置短信默认应用程序,即可直接从应用程序发送短信

(B) The SMS length can be more than the default 160 characters limit (using sendmultiparttextMessage) (B) 短信长度可以超过默认的 160 个字符限制(使用 sendmultiparttextMessage)

(C) Able to know if the SMS was process or not (base on aResultCode of the onReceive) (C) 能够知道短信是否被处理(基于onReceive的ResultCode)

Known Limitation:已知限制:

  • Under multi-sim phone, sms is sent via the default sim在多卡手机下,短信通过默认卡发送
  • if sending to multiple phone recipients, there is no way to know which ones failed, if any.如果发送给多个电话收件人,则无法知道哪些失败(如果有)。 So I suggest send 1 sms to 1 recipient at a time所以我建议一次发送 1 条短信给 1 个收件人

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

What I did:我做了什么:

  1. Create and save a unit for the BroadcastReceiver (I call it BCast.pas) from the 2nd answer from this link How read JPendingIntent in Delphi?从此链接的第二个答案中为 BroadcastReceiver 创建并保存一个单元(我称之为 BCast.pas) How read JPendingIntent in Delphi?

  2. In your main.pas (assuming it is save as main.pas), add the following:在您的 main.pas(假设它另存为 main.pas)中,添加以下内容:

  • ADD TO PROJECT the unit created in step 1 (in my case bcast.pas)添加到项目在步骤 1 中创建的单元(在我的情况下是 bcast.pas)

  • add BCAST in uses clause在使用子句中添加 BCAST

  • add variable for the TBroadCastReceiver (ie fbroadcast : Tbroadcastreceiver;)为 TBroadCastReceiver 添加变量(即 fbroadcast : Tbroadcastreceiver;)

  • make an OnReceiveBroadcast procedure in my case:在我的例子中做一个 OnReceiveBroadcast 程序:

     private { Private declarations } procedure OnReceiveBroadcast(aContext: JContext; aIntent: JIntent; aResultCode: integer);
  • then under implementation, create the code for the OnReceiveBroadcast:然后在实现中,为 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;
  • initialize the fbroadcast as follows: (i put them under my main's onshow):初始化 fbroadcast 如下:(我把它们放在我主要的 onshow 下):

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

    where xxx is any string that will be use to match the intent's action其中 xxx 是用于匹配意图操作的任何字符串

  1. Add in a procedure to sendsms:在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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM