how to read deliveryIntent
in this code?
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;
Because I understand that SMS is gone or not?
Thank you
If you read the SmsManager.sendTextMessage()
documentation, you are supposed to provide your own Intent
objects (JIntent
in Delphi) that are wrapped in PendingIntent
objects (JPendingIntent
in Delphi).
So, you would create two Intent
objects that have the desired action strings assigned to them, and then wrap them inside of two PendingIntent
objects using the PendingIntent.getBroadcast()
method (TJPendingIntent.JavaClass.getBroadcast()
in Delphi), and then pass those to sendTextMessage()
in the sentIntent
and deliveryIntent
parameters, respectively.
After the SMS has been sent/failed, the Intent
inside of the sentIntent
parameter will be broadcast. If the SMS is successfully delivered to the recipient, the Intent
inside of the deliveryIntent
parameter will be broadcast.
To process those Intent
objects, you need to create and register a broadcastReceiver
in your app. When you receive a broadcasted Intent
, then you can retrieve its action
value (see the Intent.getAction()
method) and act accordingly.
There are no String
conversions involved, unless you want to convert between a Delphi String
and an Android JString
.
Here is how I did it on Delphi 10.1 Berlin:
- Based on example of Java code, I took here or here
- Here is full code of Delphi Broadcast receiver. With this code you can catch intent, and ResultCode (getResultCode). Here is a simple example how to implement it.
unit
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.
Then
fBroadcast := TBroadcastReceiver.Create(OnReceiveBroadcast);
fBroadcast.AddActions([StringToJString(SENT_ACTION)]);
SENT_ACTION - can be any string, e.g. 'SENT' or 123 - that is ID for filter.
Then I send it:
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;
And receive with Broadcast Receiver:
{ 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;