Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Desarrollo en Delphi para Android (https://www.clubdelphi.com/foros/forumdisplay.php?f=57)
-   -   ScheduleNotification(Notification) no funciona Android 14 (https://www.clubdelphi.com/foros/showthread.php?t=96646)

jhonalone 13-03-2024 18:51:05

ScheduleNotification(Notification) no funciona Android 14
 
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;  // Para los nuevos permisos



procedure TNotificationsForm.rechazado;
begin//   Showmessage('Rechazado2'); Sleep(5000);
ShowMessage('Debe conceder todos los permisos antes usar esta aplicación.');
//   Sleep(7000);
  // Halt(1);
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
       // ShowMessage( Length(AGrantResults).ToString);
         if (Length(AGrantResults) = 4) then
  begin
   // permitido;
  //  ShowMessage('Se aceptaron todos los permisos.');
  end
  else
  begin
    rechazado;
    exit; /// No permitimos que haga lo que viene MAS ABAJO
   // ShowMessage('NO Se aceptaron todos los permisos.');
  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
  { Providing the fact that you already have a MyNotification previously issued }
  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) -->


jhonalone 18-03-2024 15:35:41

Hola a todos.
No quiero que penséis que estoy ocioso, esperando que alguien me ayude a resolver la cuestión.
Leevo 4 días buscando y buscado en Google, sin resultados positivos y probando y probando... sin ningún resultado.
Si encontrara la solución, no dudéis que la compartiría.
Saludos.

jhonalone 09-04-2024 00:56:15

Hola a todos.
Todavía no me he rendido, pero estoy a punto.

Empiezo a sospechar que el problema es de la versión de Delphi que uso: estoy en la versión Alexandria 11.0.

Se me olvidó comentaros que estoy intentando enviar notificaciones locales y que, curiosamente, cuando se envía una notificación inmediata con:

Código Delphi [-]
        vNotification.FireDate :=  Now ;
        NotificationC.ScheduleNotification(vNotification);

Tampoco se envía si se usa "ScheduleNotification(vNotification)"

Esto contradice lo que Embarcadero publica en sus páginas de ayuda

Copio una parte:

Código:

    By default, FireDate is set to Now, so if you do not change the value of FireDate,
    the notification is fired immediately.

Scheduled Notifications

Notifications can be scheduled to be fired at any time. Set FireDate to the date and time
when you want to fire the notification. 

When scheduling notifications to a particular date and time, you must bear in mind that
 if the FireDate you set has already passed, the notification is fired immediately.

Ésto es lo que me hace sospechar que las versiones de Rad Studio posteriores a la publicación de la versión 13 de Android, es praobable que lo hayan corregido.

Si alguien puede confirmarme este punto, lo agradecería, par no volverme más loco de lo que ya estoy.

Saludos cordiales.


La franja horaria es GMT +2. Ahora son las 14:50:26.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi