DelphiWorlds / Kastri

Cross-platform library for Delphi
MIT License
502 stars 122 forks source link

Receiving a push notification raises a Java exception on my Samsung phone #245

Open MyBuzzTechnologies opened 3 months ago

MyBuzzTechnologies commented 3 months ago

In DW.FCMManager.Android.pas, the call to presentNotification() is raising a Java exception which is crashing my app.

Delphi 12.1, running the latest Kastri sources on a Samsung Note 20, Android 13.

procedure TPlatformFCMManager.MessageReceivedNotificationHandler(const Sender: TObject; const AMsg: TMessage);
var
  LIcon: string;
  LIntent: JIntent;
begin
  if ShowBannerIfForeground and IsForeground then
  begin
    LIntent := TMessageReceivedNotification(AMsg).Value;
    TOSMetadata.GetValue(cMetadataFCMDefaultNotificationIcon, LIcon);
    TJDWNotificationPresenter.JavaClass.presentNotification(TAndroidHelper.Context, LIntent, StringToJString(FChannelId), StrToIntDef(LIcon, 0));
  end;
end;

The error is:

java.lang.IllegalArgumentException: Invalid notification (no valid small icon): Notification(channel=MYSHIFTPLANNERv1 shortcut=null contentView=null vibrate=null sound=null defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0)

Just before it, in the logcat output are these, which may be relevant:

Key com.google.firebase.messaging.default_notification_icon expected String but value was a java.lang.Integer. The default value <null> was returned.

and

DWNotificationPresenter Unable to locate resource notification_custom
DelphiWorlds commented 3 months ago

DWNotificationPresenter Unable to locate resource notification_custom

You can ignore this message - it just indicates that you're not using custom notifications

Key com.google.firebase.messaging.default_notification_icon expected String but value was a java.lang.Integer. The default value <null> was returned.

This one is a bit odd - can you show what you have for it in AndroidManifest.xml?

MyBuzzTechnologies commented 3 months ago

The entries related to firebase are these:

<meta-data android:name="com.google.android.gms.version" android:value="12451000"/>
        <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:value="" android:resource="@color/notification_accent_color"/>
        <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="MYSHIFTPLANNERv1"/>
        <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:value="" android:resource="@drawable/ic_notification"/>

and

        <service android:name="com.google.android.gms.ads.AdService" android:enabled="true" android:exported="false"/>
        <service android:exported="false" android:name="com.delphiworlds.kastri.DWFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
        <service android:name="com.google.firebase.components.ComponentDiscoveryService" android:directBootAware="true" android:exported="false">
            <meta-data android:name="com.google.firebase.components:com.google.firebase.analytics.connector.internal.AnalyticsConnectorRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.messaging.FirebaseMessagingRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.datatransport.TransportRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
            <meta-data android:name="com.google.firebase.components:com.google.firebase.installations.FirebaseInstallationsRegistrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
        </service>

If these aren't what you meant, let me know

DelphiWorlds commented 3 months ago

Yes, this one in particular:

<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:value="" android:resource="@drawable/ic_notification"/>

I've now realized that this line of code might be incorrect:

  TOSMetadata.GetValue(cMetadataFCMDefaultNotificationIcon, LIcon);

Since LIcon is a string, and I expect if the resource is actually there, it's really an integer. Not sure why this hasn't been a problem before. Can you try changing the code so that LIcon is an Int64, thus meaning that it can be passed direct to presentNotification instead of using StrToIntDef.

Also, when including multiple lines of code on comment, you can use 3 backticks (```) at the beginning and end, and it also accepts a format specification for supported types at the beginning marker, like: ```xml and ```delphi etc.

MyBuzzTechnologies commented 3 months ago

Thanks Dave, I'll try that and report back.

I can never remember the correct markdown syntax for code so thanks for the reminder. I used 2 backticks so almost there!

MyBuzzTechnologies commented 3 months ago

Same error I'm afraid.

First chance exception at $0000006D7E6F474C. Exception class EJNIException with message 'java.lang.IllegalArgumentException: Invalid notification (no valid small icon): Notification(channel=MYSHIFTPLANNERv1 shortcut=null contentView=null vibrate=null sound=null defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0)'. Process myShiftPlanner.apk (23820)

to confirm, the changed method is

procedure TPlatformFCMManager.MessageReceivedNotificationHandler(const Sender: TObject; const AMsg: TMessage);
var
  LIcon: Int64;
  LIntent: JIntent;
begin
  if ShowBannerIfForeground and IsForeground then
  begin
    LIntent := TMessageReceivedNotification(AMsg).Value;
    TOSMetadata.GetValue(cMetadataFCMDefaultNotificationIcon, LIcon);
    TJDWNotificationPresenter.JavaClass.presentNotification(TAndroidHelper.Context, LIntent, StringToJString(FChannelId), LIcon);
  end;
end;
DelphiWorlds commented 3 months ago

Perhaps you have no valid small icon? ;-) I'll see if I can find out what the issue is...

MyBuzzTechnologies commented 3 months ago

I've got them all listed in the project, so unless it's getting it from somewhere else then not sure what I'm looking for!

image
DelphiWorlds commented 3 months ago

It may be that the actual icons are not being deployed? One sure way to check is to look at the project output folder, e.g.: image This is for a project that was probably created with Delphi 11.x and later "upgraded" to 12.x, so I may be missing files, however those that Delphi is deploying work on my Pixel 6 Pro - I suspect you have either no ic_notification.png files being deployed, or missing the one your device needs.

MyBuzzTechnologies commented 3 months ago

I checked my deployment settings, output folder etc and it all seems correct. ic_notification.png is in the correct res folders, correct size and none are corrupt. Everything it needs seems to be there, so must be something else causing it not to be able to find the icons at runtime. Your demo project seems to work fine on my phone too, so must be something in my app setup but no idea what it could be. I'll keep digging. 👍

Thanks

DelphiWorlds commented 2 months ago

Sorry, I meant to comment here a few days ago when I pushed a fix. Can you check whether it works for you now?