Im using Delphi 10.1 for developing android application and I have used the Delphi sample for implementing Android 26 API and when I have used notification, it does not display. And also I have tried with the Notification example. But it does not works. Please help me to implement the notification as I need to implement this from Android services.
procedure TForm1.ImmediateNotification;
var
LNotification: TNotification;
begin
LNotification.EnableSound := False;
LNotification.Title := 'Immediate Notification';
LNotification.Subtitle := 'Subtitles are cool';
LNotification.AlertBody := 'This is an immediate notification';
FNotifications.PresentNotification(LNotification);
end;
Seeing that you aren't responsive, I'm going on a whim here, I've put my notification code up for you, to implement it with Android Service, you should check out: This from the DocWiki
procedure TF_SS_MAIN.NotifyAndroid(text: string);
var
Notification: TNotification;
begin
{verify if the service is actually supported}
if NotificationCenter1.Supported then
begin
Notification := NotificationCenter1.CreateNotification;
Notification.Name := 'Notif Name';
Notification.AlertBody := text;
Notification.FireDate := Now;
{Send notification in Notification Center}
NotificationCenter1.ScheduleNotification(Notification);
end;
end;
Related
A client of mine had the question of whether it is possible to send a push notification in the employee app if they have not entered their hours by a certain time.
Is it possible to create a service for Android and iOS apps that checks every hour if the hours of the day have been entered in the database, and if not then send a push notification?
I don't know where to start, and if it is possible. But if other apps can do it, it should be possible with this app as well.
As #SilverWarior Suggests I have created two pieces of code one makes the notifications when the app goes to the background then when the app goes to the foreground I clear Tnotificationcenter. I've used the appevent function to trigger the enterdbackground and willbecomeforground.
The Appevent code looks like this:
function TForm1.AppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
begin
case AAppEvent of
TApplicationEvent.EnteredBackground:
begin
Gethourregistration(FEmployeeNr,NOW);
if dm.MthourregistrationControl.RecordCount<1 then
begin
var Notification := NotificationCenter1.CreateNotification;
try
Notification.Name := 'message1';
Notification.AlertBody := 'You have not yet entered todays hours!';
Notification.FireDate :=Date+encodetime(19,0,0,0);
{ Send notification in Notification Center }
NotificationCenter1.ScheduleNotification(Notification);
Notification.Name := 'message2';
Notification.AlertBody := 'You have not yet entered todays hours!';
Notification.FireDate :=Date+encodetime(21,0,0,0);
{ Send notification in Notification Center }
NotificationCenter1.ScheduleNotification(Notification);
finally
Notification.Free;
end;
end;
end;
TApplicationEvent.WillBecomeForeground:
Notificationcenter1.CancelAll;
end;
end;
I use the OnCreate event for asking permission for sending notifications and trigger the AppEvent.
procedure TForm1.FormCreate(Sender: TObject);
var
AppEventSvc: IFMXApplicationEventService;
begin
if NotificationCenter1.AuthorizationStatus <> TAuthorizationStatus.Authorized then
begin
FPendingAction := Action;
NotificationCenter1.RequestPermission;
end;
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(AppEventSvc)) then
begin
AppEventSvc.SetApplicationEventHandler(AppEvent);
end;
end;
I have tested this code and for me, this works perfectly.
First of all, I know a little bit about restarting an app. but that's when it is for windows. In this case, I need to make this for an app that is from android. I couldn't find a solution for it that works in Delphi. Just found this from #Mihai Limbășan I quote:
Perhaps you should think outside the box. Instead of futzing with the
mutex/instance logic, you could simply create another executable that
waits for your app to close then starts it again. As an added bonus,
you can later use this mechanism to, for example, update some of your
main app's binaries. It's also much easier to run it elevated instead
of maintaining different integrity levels inside the same app, etc.
But have no idea how this works or even where to start...
Every tip, code sample, or maybe other solution to restart an app will be appreciated.
EDIT
after some questions here are some pieces of code from the procedure.
First.
after you choose for example the language 'English and push the button save this happens
Inifile := TIniFile.Create(fPath);
try
Inifile.WriteString('Instelling','ip',edit5.text);
Inifile.WriteString('Instelling','user',edit6.text);
Inifile.WriteString('Instelling','pixels',edit3.text);
Inifile.WriteInteger('Instelling','language',Combobox2.ItemIndex);
fGebruiker := Edit6.Text;
fFotoformaat := StrToInt(edit3.Text);
finally
FDConnection1.Params.Values['server']:=edit5.Text;
FDConnection1.Connected := True;
inifile.free;
End;
with this code, I fill an inifile with data as you see also the item index of the Combobox for the language.
on this point i restart the app manually so the right language is chosen by this code:
procedure TfmMain.FormShow(Sender: TObject);
VAR
param : string;
inifile : tInifile;
begin
if (System.SysUtils.fileexists(fPath)) then
Begin
begin
Inifile := TIniFile.Create(fPath);
try
if not (Inifile.ReadString('Instelling','ip','default')='default') and not (Inifile.ReadString('Instelling','Gebruiker','default')='default')then
try
edit5.text := Inifile.ReadString('Instelling','ip','default');
edit6.text := Inifile.ReadString('Instelling','user','default');
Edit3.text := Inifile.ReadString('Instelling','pixel','400');
combobox2.ItemIndex := IniFile.ReadInteger('Instelling','language',1);
fpixel:= StrToInt(edit3.Text);
fuser:=edit6.text;
FDConnection1.Params.Values['server']:=edit5.Text;
taal := 'NL';
//find language settings
if combobox2.ItemIndex=0 then
begin
language:= 'NL'
end;
if combobox2.ItemIndex=1 then
begin
language:= 'ENG';
end;
if language='ENG' then
begin
vertalerENG.vertaler('ENG');
end;
end;
end;
end;
end;
the VertalerENG is a function that is fired if the language parameter is ENG and change all of the captions to English.
the problem is that nothing is changed till i restart the app.
If you want restart app programmatically,
This code work fine for me and you can set time elapse before restart app
uses
Androidapi.Helpers,Androidapi.JNI.GraphicsContentViewText,Androidapi.JNI.App,
System.DateUtils;
...
procedure RestartApp;
{$IFDEF ANDROID}
var LPM : JPackageManager;
LIntent_Start : JIntent;
LPendingIntent : JPendingIntent;
LMS : Int64;
{$ENDIF}
begin
{$IFDEF ANDROID}
LPM := TAndroidHelper.Context.getPackageManager();
LIntent_Start := LPM.getLaunchIntentForPackage(
TAndroidHelper.Context.getPackageName()
);
LIntent_Start.addFlags( TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP );
LPendingIntent := TJPendingIntent.JavaClass.getActivity(
TAndroidHelper.Context,
223344 {RequestCode},
LIntent_Start,
TJPendingIntent.JavaClass.FLAG_CANCEL_CURRENT
);
LMS := DateTimeToUnix( Now, False {InputIsUTC} ) * 1000;
TAndroidHelper.AlarmManager.&set(
TJAlarmManager.JavaClass.RTC,
LMS + 10000,
LPendingIntent
);
// TAndroidHelper.Activity.finish();
Application.Terminate;
{$ENDIF }
end;
If changing the language is your only concern then i would suggest changing the locale of the application. You only need to restart the activity if you're using all the strings correctly from strings.xml
You can see it here how to change the locale of application programatically.
Change app language programmatically in Android
I want my app not should play the default notification sound but I want to play any other sound that is installed on Android smartphones.
I know that all other notification sounds can be changed on Android smartphones under App settings / Notification Categories.
My question is, how can I combine this sound for example 'Good news' with the MyNotification.SoundName.
I use Delphi 10.3.3
procedure TForm1.Button1Click(Sender: TObject);
var
MyNotification: TNotification;
begin
MyNotification := NotificationCenter1.CreateNotification;
try
MyNotification.Name := 'MyNotification';
MyNotification.Title := 'Notification 01';
// MyNotification.SoundName := how to get another sound that are installed on the smartphone
// for example
MyNotification.SoundName := TPath.Combine(TPath.???, 'Good news???.mp3');
MyNotification.FireDate := Now;
NotificationCenter1.ScheduleNotification(MyNotification);
finally
MyNotification.Free;
end;
end;
Great thanks for any suggestions and help.
If I do a test to view the files in this directory "TPath.GetRingtonesPath" nothing is displayed.
var
aStrArray: TStringDynArray;
i, icount: integer;
begin
aStrArray := TDirectory.GetFiles(TPath.GetRingtonesPath);
icount := High(aStrArray);
form1.memo2.lines.add('> '+TPath.GetRingtonesPath+'< Count='+IntToStr(icount));
for i := 0 to icount do form1.memo2.lines.add( aStrArray[i]);
end;
I did another test and adding a audio file 'Beep01.mp3' to deployment
assets/
by doing a test the file is well existing in this directory "TPath.GetPublicPath"
I try to add sound to the notification SoundName like this, but by starting the notification no sound audible appear.
MyNotification.SoundName: = TPath.Combine(TPath.GetPublicPath, 'Beep01.mp3');
what can i do to play another tone.
Deploy the mp3 file to .\assests\internal
You can play the file using this code example assuming the name of the file is stored in the variable 'filename':
uses
Androidapi.JNI.Media;
var
mp : JMediaPlayer
begin
mp := tjmediaplayer.Create;
mp.setdatasource(StringToJString(IncludeTrailingPathDelimiter(System.ioutils.TPath.GetDocumentsPath) + filename));
mp.prepare;
mp.start;
// mp.release;
end;
In fact you should create and release the mediaplayer outside this procedure in the forms 'oncreate' and 'ondestroy', this is why I commented out the release part in the example. Otherwise I expect the release to stop the mediaplayer immediately.
I just made an app with Delphi XE6 that receives push notifications with kinvey based on this example
When the application is running and I send a push the PushEvent handler receives it well, but when the application is closed and I press the notification it only opens my app.
Can I know which notification was pressed and get parameters from it?
Thanks in advance.
Edit:
I get a little bit closer, in my FormCreate ask for Extras:
procedure TForm1.FormCreate(Sender: TObject);
var
LIntent: JIntent;
LExtras: JBundle;
LExtrasArray: TJavaObjectArray<AndroidApi.JNI.JavaTypes.JObject>;
begin
LIntent := SharedActivity.getIntent;
try
if LIntent <> nil then
begin
LExtras := LIntent.getExtras;
if LExtras <> nil then
begin
//Now try to get the data
LExtrasArray := LExtras.KeySet.toArray;
for I := 0 to LExtrasArray.Length - 1 do
Memo1.Lines.Add(JStringToString(LExtrasArray.Items[I].toString));
end;
end;
finally
LIntent := nil;
end;
end;
With this code I get "gcm" in my memo.
So, when the notification fires my app I get this Extra available.
Now the problem is how I get info about that extra?
I tried LExtras.getString(StringToJString('message')) but this writes '' instead of the push message
Sarina DuPont answer me in her Blog
PushEvents component has a property StartupNotification for this purpose
procedure TMainForm.FormShow(Sender: TObject);
begin
if Assigned(PushEvents.StartupNotification) then
//Do something here!
//for example
//Memo.Text := PushEvents.StartupNotification.Message;
end;
I am building an application for Android using Delphi XE5 that makes use of the Zxing barcode application and it uses the clipboard to retrieve the result. All of the code (Most of it anyway) is from a tutorial that I have found on the web. When I followed the tutorial, it worked to a charm but when applying the SAME code within an application that I was already working on - it did not work. Whenever accessing the clipboard ( in the 'OnTimer' event), the application always hangs and stops working. No error, nothing. App freezes and I have to close it via the phone's task manager.
The application fails right after the following line
Log.Add('AndroidClipboardScanner:1'); Log.SaveToFile(INIFileLog);
I have changed the coding around so that the app assumed the Clipboard service was available in the Ontimer event and it proceeded but it then failed after the following line:
Log.Add('AndroidClipboardScanner:4'); Log.SaveToFile(INIFileLog);
I am not sure where to begin debugging because the same code works in the other application that I created following the initial guide I found. I can also confirm that the ClipService is being assigned properly, otherwise the intent wouldn't even begin. Any help or guidance would be much appreciated ! Below is my code...
This Declared in the 'Private' variables section of the form:
ClipService: IFMXClipboardService;
This within the 'OnTimer' event for Timer1:
procedure TMain_Form.Timer1Timer(Sender: TObject);
var
barCode : String;
begin
timer1.Enabled := false;
Log.Add('AndroidClipboardScanner:0.1'); Log.SaveToFile(INIFileLog);
Try
if assigned(ClipService) then begin
Log.Add('AndroidClipboardScanner:1'); Log.SaveToFile(INIFileLog);
if (ClipService.GetClipboard.ToString <> 'nil') then
begin
Log.Add('AndroidClipboardScanner:2'); Log.SaveToFile(INIFileLog);
timer1.Enabled := false;
Log.Add('AndroidClipboardScanner:3'); Log.SaveToFile(INIFileLog);
Elapsed := 0;
Log.Add('AndroidClipboardScanner:4'); Log.SaveToFile(INIFileLog);
editHold.PasteFromClipboard;
//EditHold.Text := ClipService.GetClipboard.ToString;
Log.Add('AndroidClipboardScanner:5'); Log.SaveToFile(INIFileLog);
end else
begin
Log.Add('AndroidClipboardScanner:6'); Log.SaveToFile(INIFileLog);
Timer1.Enabled := False;
Log.Add('AndroidClipboardScanner:7'); Log.SaveToFile(INIFileLog);
end;
Log.Add('AndroidClipboardScanner:8'); Log.SaveToFile(INIFileLog);
end else begin
ShowMessage('Unexpected error has occured');
end;
Except
ShowMessage('Unexpected error has occured..');
End;
end;
Within the ONCreate procedure of the form:
if not TPlatformServices.Current.SupportsPlatformService(IFMXClipboardService,
IInterface(ClipService)) then begin
ShowMessage('Clipboard Failed:1');
ClipService := nil;
end;
Elapsed := 0;
This is for click event for the button that begins the intent:
procedure TMain_Form.Button_ShowScannerClick(Sender: TObject);
{$IFDEF ANDROID}
var
intent: JIntent; {$ENDIF}
begin
{$IFDEF ANDROID}
//ShowMessage('Scanner:1');
if assigned(ClipService) then begin
//ShowMessage('Scanner:2');
ClipService.SetClipboard('nil');
intent := tjintent.Create;
intent.setAction(stringtojstring('com.google.zxing.client.android.SCAN'));
intent.putExtra(tjintent.JavaClass.EXTRA_INTENT,
stringtojstring('"SCAN_MODE"'));
sharedactivity.startActivityForResult(intent,0);
Elapsed := 0;
timer1.Enabled := true;
//ShowMessage('Scanner:3');
end;
{$ENDIF}
You didn't set the SCAN_MODE parameters like:
intent.putExtra(tjintent.JavaClass.EXTRA_TEXT,
stringtojstring('"SCAN_MODE","ONE_D_MODE,QR_CODE_MODE,PRODUCT_MODE,DATA_MATRIX_MODE"'));
Also you can check timer interval parameter...
I tested the solution on few devices.
With low interval value I had black screen sometimes