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



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

既然老款优秀的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;

**使用repeat until循环读取每条短信,直到"为真**

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

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

PS:我也试着从content://SMS/sent和content://SMS/中搜索SMS,但没有成功。

无论如何,我的问题是:
  1. 如何使发送的短信显示在手机的默认短信应用程序?
  2. 如何正确判断发送短信是否成功?

我在某个地方读到,上面的方法是使用API,有一种方法来使用手机的短信应用程序代替…但是我不知道如何去做。

谢谢。

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

(A)能够直接从应用程序发送短信,而不使用手机内置的短信默认应用程序

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

(C)能够知道SMS是否正在处理(基于onReceive from PendingIntent的aResultCode)

众所周知的局限:

  • 多sim卡下,短信通过默认sim卡发送
  • 如果发送到多个电话收件人,没有办法知道哪一个失败,如果有的话。所以我建议一次发1条短信给1个收件人
  • 不检测收件人是否收到短信,因为DeliveryIntent为nil

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

我做了什么:

  1. 创建并保存BroadcastReceiver的单位(我称之为BCast.pas)从这个链接的第二个答案如何阅读JPendingIntent在Delphi?

  2. 在你的主目录中。Pas(假设保存为main.pas),添加以下内容:

  • ADD TO PROJECT在步骤1中创建的单元(在我的例子中是bcast.pas)

  • 添加广播地址使用条款
  • 为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. 为sendsms添加一个过程:

    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;
    

最新更新