如何读取 Delphi 中的 JPendingIntent?

How read JPendingIntent in Delphi?

如何阅读此代码中的 deliveryIntent

uses
  Androidapi.JNI.JavaTypes, Androidapi.JNI.Telephony;

    procedure TForm1.Button1Click(Sender: TObject);
var
  smsTo: JString;
  smsManager: JSmsManager;
begin
  smsManager := TJSmsManager.JavaClass.getDefault;
  smsTo := StringToJString(ENum.text);
  PendIntent1:=TJPendingIntent.JavaClass.getBroadcast();
  PendIntent2:=TJPendingIntent.JavaClass.getBroadcast();
  smsManager.sendTextMessage(smsTo, nil, StringToJString(MSms.lines.text),PendIntent1,PendIntent2);
end;

因为我知道短信是不是没了?

谢谢

如果您阅读 SmsManager.sendTextMessage() documentation,您应该提供自己的 Intent 对象(Delphi 中的 JIntent),这些对象包含在 PendingIntent 中对象(Delphi 中的JPendingIntent)。

因此,您将创建两个 Intent 对象,并为其分配了所需的操作字符串,然后使用 PendingIntent.getBroadcast() 方法将它们包裹在两个 PendingIntent 对象中(TJPendingIntent.JavaClass.getBroadcast() in Delphi),然后将它们分别传递给 sentIntentdeliveryIntent 参数中的 sendTextMessage()

短信sent/failed后,将广播sentIntent参数里面的Intent。如果短信成功发送给收件人,将广播deliveryIntent参数中的Intent

要处理这些 Intent 对象,您需要在您的应用中创建并注册一个 broadcastReceiver。当您收到广播的 Intent 时,您可以检索它的 action 值(请参阅 Intent.getAction() 方法)并采取相应的行动。

不涉及 String 转换,除非您想在 Delphi String 和 Android JString.[=36= 之间转换]

这是我在 Delphi 10.1 Berlin 上的做法:

  1. 基于 Java 代码示例,我采用了 here or here
  2. 这里是 Delphi 广播接收器的完整代码。使用此代码,您可以捕获意图和 ResultCode (getResultCode)。 Here 是一个如何实现它的简单示例。

单位

unit BroadcastReceiver;

interface

{$IFDEF ANDROID}
uses
  Androidapi.JNI.Embarcadero, Androidapi.JNI.GraphicsContentViewText, Androidapi.helpers,
  Androidapi.JNIBridge, FMX.Helpers.Android, Androidapi.JNI.JavaTypes,
  System.Classes, System.SysUtils;

type
  TBroadcastReceiver = class;

  TListener = class(TJavaLocal, JFMXBroadcastReceiverListener)
  private
    fOwner: TBroadcastReceiver;
    fReceiver: JFMXBroadcastReceiver;
  public
    constructor Create(aOwner: TBroadcastReceiver);
    destructor Destroy; override;
    procedure onReceive(context: JContext; intent: JIntent); cdecl;
  end;


  TOnReceive = procedure (aContext: JContext; aIntent: JIntent; aResultCode: integer) of object;

  TBroadcastReceiver = class
  private
    fListener : TListener;
    fRegistered: boolean;
    fOnReceive: TOnReceive;
  public
    constructor Create(aOnReceiveProc: TOnReceive);
    destructor Destroy; override;
    procedure AddActions(const Args: array of JString);
    procedure SendBroadcast(const aValue: string);
  end;
{$ENDIF}

implementation

{$IFDEF ANDROID}

{ TBroadcastReceiver }

constructor TBroadcastReceiver.Create(aOnReceiveProc: TOnReceive);
begin
  inherited Create;
  fListener := TListener.Create(Self);
  fOnReceive := aOnReceiveProc;
end;

destructor TBroadcastReceiver.Destroy;
begin
  fListener.Free;
  inherited;
end;

procedure TBroadcastReceiver.AddActions(const Args: array of JString);
var
  vFilter: JIntentFilter;
  i: Integer;
begin
  if fRegistered then
    TAndroidHelper.context.getApplicationContext.UnregisterReceiver(fListener.fReceiver);

  vFilter := TJIntentFilter.JavaClass.init;
  for i := 0 to High(Args) do
    vFilter.addAction(Args[i]);

  TAndroidHelper.context.getApplicationContext.registerReceiver(fListener.fReceiver, vFilter);
  fRegistered := true;
end;

procedure TBroadcastReceiver.SendBroadcast(const aValue: string);
var
  Inx: JIntent;
begin
  Inx := TJIntent.Create;
  Inx.setAction(StringToJString(aValue));
  TAndroidHelper.Context.sendBroadcast(Inx);
end;

constructor TListener.Create(aOwner: TBroadcastReceiver);
begin
  inherited Create;
  fOwner := aOwner;
  fReceiver := TJFMXBroadcastReceiver.JavaClass.init(Self);
end;

destructor TListener.Destroy;
begin
  TAndroidHelper.context.getApplicationContext.unregisterReceiver(fReceiver);
  inherited;
end;

// usually android call it from "UI thread" - it's not main Delphi thread
procedure TListener.onReceive(context: JContext; intent: JIntent);
begin
  if Assigned(fOwner.fOnReceive) then
    fOwner.fOnReceive(Context, Intent, fReceiver.getResultCode);
end;

{$ENDIF}

end.

然后

  fBroadcast := TBroadcastReceiver.Create(OnReceiveBroadcast);
  fBroadcast.AddActions([StringToJString(SENT_ACTION)]);

SENT_ACTION - 可以是任何字符串,例如'SENT' 或 123 - 这是过滤器的 ID。

那我发过去:

procedure TAndroidSMS.SendSMS(const aText, aPhone: string);
var
  Intent: JIntent;
  PendingIntent: JPendingIntent;
  vSmsManager: JSmsManager;
begin
  Result := seNotUpdated;
  Intent := TJIntent.Create;
  Intent.setAction(StringToJString(SENT_ACTION));
 // Intent.putExtra( StringToJString(EXTRA_PHONE_PARAM), StringTojString(aPhone));

  PendingIntent := TJPendingIntent.JavaClass.getBroadcast(TAndroidHelper.Context, 0, Intent, 0);

  vSmsManager := TJSmsManager.JavaClass.getDefault;
  vSmsManager.sendTextMessage( StringToJString(aPhone), nil, StringToJString(aText), PendingIntent, nil);
end;

并使用广播接收器接收:

{ usually android call it from "UI thread" - it's not main Delphi thread}
procedure TAndroidSMS.OnReceiveBroadcast(aContext: JContext; aIntent: JIntent; aResultCode: integer);
begin
 // vAction := JStringToString(aIntent.getAction);
 // vNum := JStringToString(aIntent.getStringExtra( StringToJString(EXTRA_PHONE_PARAM) ) );

   // now change value, another thread is cheking periodically for this flag
    {Intel, Arm, write to a single byte, or to a properly aligned 2- or 4-byte value will always be an atomic write.}
  if aResultCode = TJActivity.JavaClass.RESULT_OK then
    Result := seSent
  else if aResultCode = TJSmsManager.JavaClass.RESULT_ERROR_RADIO_OFF then
    Result := seRadioOff
  else if aResultCode = TJSmsManager.JavaClass.RESULT_ERROR_GENERIC_FAILURE then
    Result := seGenericFail
  else if aResultCode = TJSmsManager.JavaClass.RESULT_ERROR_NO_SERVICE then
    Result := seNoService
  else if aResultCode = TJSmsManager.JavaClass.RESULT_ERROR_NULL_PDU then
    Result := seNullPDU
  else Result := seUnknown;
 end;