I'm using Delphi DX Seattle and testing on an android Device
when a user clicks a button i'm creating multiple scheduled notifications
and when a user clicks another button im clearing the remaining notifications
I cant seem to get the TNotificationCenter.CancelAll to actually cancel notifications after one notification has fired
Similar Question Here
Using the Delphi sample SendCancelNotification as the base code
I'm Changing the "Send Notification Immediately" button to "Send Multiple Notifications" and the code looks like this
procedure TNotificationsForm.btnSendMultipleNotificationsClick(
Sender: TObject);
procedure MyNotificationCreate(aNotificationName : String; aSecondDelay : Word);
var
Notification: TNotification;
begin
if (aSecondDelay < 0) or (aSecondDelay > 60) then
raise Exception.Create('Seconds must be between 0 and 60');
{ verify if the service is actually supported }
Notification := NotificationC.CreateNotification;
try
Notification.Name := aNotificationName;
Notification.AlertBody := aNotificationName + ' ran after ' + inttostr(aSecondDelay) + ' seconds';
{ Fired in 10 second }
Notification.FireDate := Now + EncodeTime(0,0,aSecondDelay,0);
{ Send notification in Notification Center }
NotificationC.ScheduleNotification(Notification);
finally
Notification.DisposeOf;
end;
end;
begin
MyNotificationCreate('First' , 5);
MyNotificationCreate('Second', 10);
MyNotificationCreate('Third' , 15);
end;
This sends three notifications after the button has been clicked.
if i click the "Send Multiple Notifications" button and then before 5 seconds click the "cancel all notifications" button the notifications are canceled successfully.
procedure TNotificationsForm.SpeedButton2Click(Sender: TObject);
begin
NotificationC.CancelAll;
end;
But if i click the multi notification button and wait until the first notification has fired then click the "cancel all notifications" button, it doesn't cancel the remaining notifications. e.g. notifications Second and Third still run.
Has anyone come across this? or have any ideas on why the CancelAll event doesn't work after one of the notifications have been sent
I have found the issue and have got it to work
this solution requires you to not have a numerical number as the first character of your notification name
if you can think of a better way to resolve this issue please post your answer
if you are running into the same issue then copy the System.Android.Notification.pas from Source code here file into your project folder and give it a go
after sending off three or more notifications and the first notification is triggered on android the notifications were loosing the #10 character.
e.g. one=10#10Two=11#10Three=12 was becoming Two=11Three=12 and then the cancel all was not getting a name match and never canceling two or three
I have copied the
Embarcadero\Studio\17.0\source\rtl\common\System.Android.Notification.pas
file to my project file and modified it to help make more sense of what was happening
this is the function that i was using to help track down the problem
function TAndroidPreferenceAdapter.GetAllNotificationsNames: TStringList;
var
Notifications: TStringList;
NotificationsStr: JString;
I: Integer;
begin
Notifications := TStringList.Create;
NotificationsStr := FPreference.getString(TJNotificationAlarm.JavaClass.SETTINGS_NOTIFICATION_IDS, nil);
Notifications.Text := JStringToString(NotificationsStr);
for I := 0 to Notifications.Count - 1 do
Notifications[I] := ExtractName(Notifications[I]);
Result := Notifications;
end;
what i ended up doing was to check for more than 1 = character in the string list loop
if there were more than 1, Delete the original line then loop through the original string from the = character until a non numeric number occurred and re insert that into the string list
function TAndroidPreferenceAdapter.GetAllNotificationsNamesNonFiltered: TStringList;
var
Notifications: TStringList;
NotificationsStr: JString;
I: Integer;
function OccurrencesOfChar(const S: string; const C: char): integer;
var
i: Integer;
begin
result := 0;
for i := 1 to Length(S) do
if S[i] = C then
inc(result);
end;
function InsertLineBreaks(const S: string) : String;
var sNewString, sRemaining : String;
i : integer;
const validChars = '0123456789';
begin
try
sNewString := '';
sRemaining := S;
for I := pos('=',sRemaining,1) to length(sRemaining) -1 do begin
if pos( sRemaining[i], validChars ) > 0 then begin
//continue as its still an integer
end else begin
sNewString := copy( sRemaining, 0, i);
sRemaining := copy( sRemaining, i+1, Length(s));
if OccurrencesOfChar(sRemaining, '=') > 1 then begin
InsertLineBreaks(sRemaining);
sRemaining := '';
end;
break;
end;
end;
if sNewString <> '' then
Notifications.Add( sNewString ) ;
if sRemaining <> '' then
Notifications.Add( sRemaining ) ;
Result := sNewString + sRemaining;
except
on E:Exception do begin
e.Message := e.Message + #13#10 + 'fn[TAndroidPreferenceAdapter.GetAllNotificationsNamesNonFiltered.InsertLineBreaks]';
raise;
end;
end;
end;
var sTemp : String;
begin
Notifications := TStringList.Create;
NotificationsStr := FPreference.getString(TJNotificationAlarm.JavaClass.SETTINGS_NOTIFICATION_IDS, nil);
Notifications.Text := JStringToString(NotificationsStr);
for I := 0 to Notifications.Count - 1 do begin
if OccurrencesOfChar(Notifications[I], '=') > 1 then begin
sTemp := Notifications[I];
Notifications.Delete( i );
InsertLineBreaks( sTemp );
break;
end;
end;
Result := Notifications;
end;
i also had to change anywhere that was calling the
Notifications := TStringList.Create;
NotificationsStr := FPreference.getString(TJNotificationAlarm.JavaClass.SETTINGS_NOTIFICATION_IDS, nil);
Notifications.Text := JStringToString(NotificationsStr);
to the new GetAllNotificationsNamesNonFiltered
have a look at the source code if something above doesn't make sense Source code here