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.
Related
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;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I developed an android application where there is a service working in the background that job is to send notification about all rendezvous of the day.
In the main Application onCreat even i created the service form :
Application.CreateForm(TTservice, Tservice);
and i created a Tswitchbutton to start the service and to stop it :
if switchnotificationenable.IsChecked then
var
Fservice : TLocalServiceConnection;
begin
Fservice := TLocalServiceConnection.Create;
Fservice.StartService('TheService');
end;
and another code in the service's event OnstartCommande :
Result := TJService.JavaClass.START_REDELIVER_INTENT;
when debugging a violation Access pointed at the code:
Fservice.StartService('TheService');
the error normally means that what i'm calling doesn't exist i was able to access a timer that is on my service form, so i have no idea what can be the problem.
i hope you guys can help me find the solution.
i'm using Delphi XE10.2 tokyo with an sqlite database,
have a good day everyone !
Update
I found out that when i remove the file.jar of the service from the project the violation access error is gone but the service doesn't start.
-----UPDATE-----
after finding out that i cannot work with a TTimer to create my push notifications, I'm thinking about making a iTask implemented with a loop that check every 30seconds with sleep function if the system time is equal to the time given in the main application by the user
procedure TDM.AndroidServiceCreate(Sender: TObject);
var
ntf : Jnotification;
today : Ttime;
mynotification : Tnotification;
notiftime : TTime;
T : iTask;
TheINIFIle : string;
config : Tstringlist;
begin
// Loading the database path and the time given by the user in the main apps who are saved in A Ini file
TheINIFILE := TPath.Combine(TPath.GetSharedDocumentsPath ,'NotificationParams.ini');
if FileExists(TheINIFILE) then
begin
config := Tstringlist.Create;
config.loadfromfile(TheINIFILE);
notiftime := strtotime(config.Values['TimeNotification']);
TimerConnection.Database := config.Values['DatabasePath'];
TimerConnection.Connect;
// creating the iTask and giving it code that create notifications everytime the system time is equal to the notification time
if TimerCOnnection.Connected = true then
begin
T := TTask.Run(procedure
begin
while Checking = true do
begin
sleep(30000);
today := time;
with QueryForNotification do
begin
SQL.Clear;
SQL.Add('select client.entreprise, RDV.date_ntf, RDV.date_rdv, Client.num_C from client, Rdv where client.num_c = rdv.num_c and rdv.Date_Ntf = date(''now'')');
Open;
First;
while not eof do
if sametext(fieldvalues['date_ntf'], FormatDateTime('yyyy-mm-dd', now)) then
begin
MyNotification := TheNotifications.CreateNotification;
try
if sametext(formatdatetime('HH-MM',NotifTime),formatdatetime('HH-MM',today)) then
begin
MyNotification.AlertBody := 'Le RDV avec ' + FieldValues['entreprise'] + ' vous attend!' ;
TheNotifications.ScheduleNotification(MyNotification);
end;
finally
next;
MyNotification.DisposeOf;
end;
end;
end;
end;
end);
end;
end;
end;
I'm trying to make an application with local service, with an example from
http://docwiki.embarcadero.com/RADStudio/Seattle/en/Creating_Android_Services
But in my case, my service just won't fire a notification after started (nor can I be sure that the service is running). Is there any way to make sure my service is running? Since when I tried to check on device's System - Apps - Running even my app is not listed. It's like my app just died (or sleep) after it lost focus/switch to other app
Below is my simple service & notification code
function TAndroidServiceDM.AndroidServiceStartCommand(const Sender: TObject;
const Intent: JIntent; Flags, StartId: Integer): Integer;
var TheNotif: TNotification;
begin
TheNotif := Notif.CreateNotification;
try
TheNotif.Title := 'Notif Title';
TheNotif.Name := 'NotifServiceStart';
TheNotif.AlertBody := 'I''m alive!!!!';
TheNotif.FireDate := Now;
Notif.PresentNotification(TheNotif);
finally
TheNotif.Free;
end;
Result := TJService.JavaClass.START_STICKY;
end;
and this is my caller app code
procedure TfmMain.FormCreate(Sender: TObject);
var FServiceConn: TLocalServiceConnection;
begin
FServiceConn := TLocalServiceConnection.Create;
FServiceConn.StartService('unMainServiceLocation');
FServiceConn.BindService('unMainServiceLocation');
end;
procedure TfmMain.NotifReceiveLocalNotification(Sender: TObject;
ANotification: TNotification);
begin
Text1.Text :=
'Title : ' + ANotification.Title + #13#10 +
'Name : ' + ANotification.Name + #13#10 +
'Alert : ' + ANotification.AlertBody ;
end;
I tried to put a button on app and do the same thing (send notification from app) and when I pressed the button, my Text1 component shows the right thing, and the notification did appear, but not when starting my app (should've been started by the service). Service name suppose to be right since when I change the service name it got forced stopped (segmentation fault 11)
Please kindly give advice. Thanks
After having put this lines in other event (like a button click), it works fine:
FServiceConn.StartService('unMainServiceLocation');
FServiceConn.BindService('unMainServiceLocation');
The scope of your variable var FServiceConn: TLocalServiceConnection; is limited to FormCreate, meaning it will not be available outside the FormCreate procedure. Place the variable up it in the private section of the form. Don't forget to clean up on closing / destroying the form.
Typically in a Delphi VCL application which uses a TDataset descendent as data storage (eg TClientDataset), in the Dataset1BeforeDelete handler we do something like this:
procedure TClientModule1.MyCDSBeforeDelete(DataSet: TDataSet);
begin
if MessageDlg('Delete?', mtCOnfirmation, [mbyes, mbNo], 0) <> mrYes then
SysUtils.Abort
end;
Now in a FMX application designed to run on Android, this becomes:
procedure TClientModule1.MyCDSBeforeDelete(DataSet: TDataSet);
MessageDlg('Delete?'
,
TMsgDlgType.mtWarning, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure(const AResult: TModalResult)
begin
if AResult <> mrYes then
Abort;
end
);
end;
Except, that's not going to work! The messagedlg is going to hold the user's attention, but the event handler code is going to continue and allow the record to be deleted anyway.
What's the solution?
Because modal window and Message Box currently are not supported in FMX for Android you should use some kind of "dog-nail" solution
Ad-Hoc solution #1, .
In main form or in form which should open Modal window write code like:
procedure TForm1.btnSelectClick(Sender: TObject);
begin
if fmSelect = nil then
begin
Application.CreateForm(TfmSelect, fmSelect);
fmSelect.Callback := Yahoo;
end;
fmSelect.Show;
end;
procedure TForm1.Yahoo(ASelectedItem: String);
begin
ShowMessage(ASelectedItem);
end;
in fmSelect should be your message and buttons with options (like Yes, No, May be, Not today).
in fmSelect form you should declare PUBLIC variable Callback: TCallback;
Once user press some button, you should call this function and close form:
procedure TfmSelect.btnSelectClick(Sender: TObject);
begin
if Assigned(Callback) then
Callback('user press button XXX');
Close;
end;
TCallback just regular function which return String type (you could change it to Integer).
TCallback = procedure (ASelected: String) of object;
Ad-Hoc solution #2
simulat to first, but with using hidden TComboBox. In combobox items will be stored all options, like "Yes", "No", "Maybe tomorrow". Once ComboBox was closed OnClosePopup event, you get value of user choise.
3. Take a look how it's done somewhere in Embarcadero samples (from XE8):
http://docwiki.embarcadero.com/RADStudio/XE8/en/Mobile_Tutorial:_Using_FireDAC_and_SQLite_%28iOS_and_Android%29
So in your case will be
private
procedure FCloseDialogProc(const AResult: TModalResult);
procedure TForm1.Button1Click(Sender: TObject);
begin
MessageDlg('Want something', TMsgDlgType.mtWarning, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0, FCloseDialogProc);
end;
procedure TForm1.FCloseDialogProc(const AResult: TModalResult);
begin
Label1.Text := IntToStr(AResult);
// -1 -- click outside
// 6 -- yes
// 7 -- no
end;
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;