Saludos Amigos.
Necesito vuestra ayuda, una vez más.
Estoy desarrollando una agenda de eventos para recordar sucesos futuros, tales como cumpleaños, citas médicas, reuniones, etc.
Me gustaría implementar un sistema local de notificaciones para recordar al usuario con anticipación.
He pensado utilizar el sistema de notificaciones push local del dispositivo para ello.
Antes de incorporarlo a la app de la agenda, estoy probando con el ejemplo de Delphi 11:
Object Pascal\Mobile Snippets\Notifications\SendCancelNotification.
He tenido que hablilitar
algunos permisos (cono veréis en el codigo más abajo) y alguna bandera en la unidad
System.Android.Notification.pas como esta:
TJPendingIntent.JavaClass.getActivity(TAndroidHelper.Context, TGeneratorUniqueID.GenerateID, Intent, TJPendingIntent.JavaClass.FLAG_UPDATE_CURRENT
or TJPendingIntent.JavaClass.FLAG_IMMUTABLE);
Lo explico por si alguien quiere que funcionen las notificaciones en versiones Android 13 y superiores.
También he actualizado el SDK a la última versión. (No sé si esto era necesario)
Bien. He conseguido que funcione en las versiones 9 y 10 de Andoid, (que he podido probar, tanto en
notificariones inmediatas como diferidas.
El problema está en la versión 14. (Supongo que en la 13 taambién) Estoy probando y las
notificaciones inmediatas se emiten correctamente,
PERO LAS QUE SON DIFERIDAS EN EL TIEMPO SE PIERDEN Y NO APARECEN.
Y en eso estoy...
Si alguien ha resuelto el problema y tiene a bein comprtirlo se lo agradezco. Quizás ayude también a quienes puedan tener el mismo problema en el futuro.
Gracias anticipadas. Por leerme y ayudarme.
Saludos cordiales a todos.
Esta es la unidad modificada.
Código Delphi
[-]
unit uMain;
interface
uses
System.Actions, System.Classes, System.Notification,
FMX.ActnList, FMX.Controls, FMX.Controls.Presentation, FMX.Forms, FMX.Memo,
FMX.Memo.Types, FMX.ScrollBox, FMX.StdCtrls, FMX.Types, FMX.Dialogs,
AndroidApi.Helpers, AndroidAPI.JNI.Os, System.Permissions, System.DateUtils;
type
TNotificationsForm = class(TForm)
btnSendScheduledNotification: TButton;
ToolBar1: TToolBar;
Label1: TLabel;
btnSendNotificationImmediately: TButton;
ToolBar2: TToolBar;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
NotificationC: TNotificationCenter;
Memo1: TMemo;
ActionList: TActionList;
ActionSendScheduledNotification: TAction;
ActionSendNotificationImmediately: TAction;
ActionCancelScheduled: TAction;
ActionCancelAllNotifications: TAction;
procedure NotificationCPermissionRequestResult(Sender: TObject; const AIsGranted: Boolean);
procedure NotificationCReceiveLocalNotification(Sender: TObject; ANotification: TNotification);
procedure ActionListExecute(Action: TBasicAction; var Handled: Boolean);
procedure ActionSendScheduledNotificationExecute(Sender: TObject);
procedure ActionSendNotificationImmediatelyExecute(Sender: TObject);
procedure ActionCancelScheduledExecute(Sender: TObject);
procedure ActionCancelAllNotificationsExecute(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
private
FPendingAction: TBasicAction;
procedure rechazado;
end;
var
NotificationsForm: TNotificationsForm;
Read_SD : String;
Write_SD : String;
Internet :String;
Notific: String;
implementation
{$R *.fmx}
uses
System.SysUtils,
DW.Consts.Android, DW.Permissions.Helpers;
procedure TNotificationsForm.rechazado;
beginShowMessage('Debe conceder todos los permisos antes usar esta aplicación.');
end;
procedure TNotificationsForm.NotificationCPermissionRequestResult(Sender: TObject; const AIsGranted: Boolean);
begin
if AIsGranted and (FPendingAction <> nil) then
begin
FPendingAction.Execute;
end;
FPendingAction := nil;
end;
procedure TNotificationsForm.NotificationCReceiveLocalNotification(Sender: TObject; ANotification: TNotification);
begin
Memo1.Lines.Add(ANotification.AlertBody);
end;
procedure TNotificationsForm.ActionListExecute(Action: TBasicAction; var Handled: Boolean);
begin
if NotificationC.AuthorizationStatus <> TAuthorizationStatus.Authorized then
begin
Handled := True;
FPendingAction := Action;
NotificationC.RequestPermission;
end;
end;
procedure TNotificationsForm.ActionSendScheduledNotificationExecute(Sender: TObject);
begin
var vNotifiCenter:= TNotificationCenter.Create(nil);
try
if vNotifiCenter.Supported then
begin
var LChannel := vNotifiCenter.CreateChannel('MyChannel', 'MyChannel', 'My Channel');
try
LChannel.Importance := TImportance.High;
vNotifiCenter.CreateOrUpdateChannel(LChannel);
finally
LChannel.Free;
end;
var vNotification := vNotifiCenter.CreateNotification;
try
vNotification.AlertBody := 'Este es mi mensaje';
vNotification.Title := 'Recuerde';
vNotification.EnableSound := true;
vNotification.ChannelId := 'MyChannel';
vNotification.FireDate := EncodeDateTime(2024,3,12,17,10,0,0);
vNotifiCenter.ScheduleNotification(vNotification);
finally
vNotification.Free;
end;
end;
finally
vNotifiCenter.Free;
end;
end;
procedure TNotificationsForm.FormCreate(Sender: TObject);
begin
Read_SD := JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE);
Write_SD := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
Internet := JStringToString(TJManifest_permission.JavaClass.INTERNET);
Notific := 'android.permission.POST_NOTIFICATIONS';
end;
procedure TNotificationsForm.FormShow(Sender: TObject);
begin
begin
PermissionsService.RequestPermissions([Read_SD, Write_SD,Internet,Notific],
procedure(const APermissions: TPermissionArray; const AGrantResults: TPermissionStatusArray)
begin
if (Length(AGrantResults) = 4) then
begin
end
else
begin
rechazado;
exit; end;
end
);
end;
end;
procedure TNotificationsForm.ActionSendNotificationImmediatelyExecute(Sender: TObject);
begin
var vNotifiCenter:= TNotificationCenter.Create(nil);
try
if vNotifiCenter.Supported then
begin
var LChannel := vNotifiCenter.CreateChannel('MyChannel', 'MyChannel', 'My Channel');
try
LChannel.Importance := TImportance.High;
vNotifiCenter.CreateOrUpdateChannel(LChannel);
finally
LChannel.Free;
end;
var vNotification := vNotifiCenter.CreateNotification;
try
vNotification.AlertBody := 'Este es mi mensaje';
vNotification.Title := 'Recuerde';
vNotification.EnableSound := true;
vNotification.ChannelId := 'MyChannel';
vNotification.FireDate := Now;
vNotifiCenter.PresentNotification(vNotification);
finally
vNotification.Free;
end;
end;
finally
vNotifiCenter.Free;
end;
end;
procedure TNotificationsForm.ActionCancelScheduledExecute(Sender: TObject);
begin
NotificationC.CancelNotification('MyNotification');
end;
procedure TNotificationsForm.ActionCancelAllNotificationsExecute(Sender: TObject);
begin
NotificationC.CancelAll;
end;
end.
Y éste el archivo del Manifiesto modificado.
Código:
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="%package%"
android:versionCode="%versionCode%"
android:versionName="%versionName%"
android:installLocation="%installLocation%">
<uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="34" />
<%uses-permission%>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<queries>
<%queries-child-elements%>
</queries>
<application
android:persistent="%persistent%"
android:restoreAnyVersion="%restoreAnyVersion%"
android:label="%label%"
android:debuggable="%debuggable%"
android:largeHeap="%largeHeap%"
android:icon="%icon%"
android:theme="%theme%"
android:hardwareAccelerated="%hardwareAccelerated%"
android:resizeableActivity="false"
android:requestLegacyExternalStorage="true">
<%provider%>
<%application-meta-data%>
<%uses-libraries%>
<%services%>
<!-- Our activity is a subclass of the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
<activity
android:name="com.embarcadero.firemonkey.FMXNativeActivity"
android:label="%activityLabel%"
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
android:launchMode="singleTask"
android:exported="true">
<!-- Tell NativeActivity the name of our .so -->
<meta-data android:name="android.app.lib_name" android:value="%libNameValue%" />
<receiver
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver" android:exported="true"/>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<%activity%>
<%receivers%>
</application>
</manifest>
<!-- END_INCLUDE(manifest) -->