1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

PushNotifications: Assert instead of crashing if Android notification icon cannot be located

This commit is contained in:
reuk 2024-11-21 22:06:42 +00:00
parent 98031a814c
commit ed0092a8bc
No known key found for this signature in database

View file

@ -276,7 +276,7 @@ bool PushNotifications::Notification::isValid() const noexcept
//============================================================================== //==============================================================================
struct PushNotifications::Pimpl struct PushNotifications::Pimpl
{ {
Pimpl (PushNotifications& p) explicit Pimpl (PushNotifications& p)
: owner (p) : owner (p)
{} {}
@ -303,16 +303,18 @@ struct PushNotifications::Pimpl
auto* env = getEnv(); auto* env = getEnv();
auto notificationManager = getNotificationManager(); if (auto notificationManager = getNotificationManager())
{
if (notificationManager.get() != nullptr) if (auto notification = juceNotificationToJavaNotification (n))
{ {
auto notification = juceNotificationToJavaNotification (n);
auto tag = javaString (n.identifier); auto tag = javaString (n.identifier);
const int id = 0; const int id = 0;
env->CallVoidMethod (notificationManager.get(), NotificationManagerBase.notify, tag.get(), id, notification.get()); env->CallVoidMethod (notificationManager.get(),
NotificationManagerBase.notify,
tag.get(),
id, notification.get());
}
} }
} }
@ -607,11 +609,12 @@ struct PushNotifications::Pimpl
auto notificationBuilder = createNotificationBuilder (n); auto notificationBuilder = createNotificationBuilder (n);
setupRequiredFields (n, notificationBuilder); notificationBuilder = setupRequiredFields (n, notificationBuilder);
setupOptionalFields (n, notificationBuilder); notificationBuilder = setupOptionalFields (n, notificationBuilder);
notificationBuilder = setupActions (n, notificationBuilder);
if (n.actions.size() > 0) if (notificationBuilder == nullptr)
setupActions (n, notificationBuilder); return notificationBuilder;
return LocalRef<jobject> (env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.build)); return LocalRef<jobject> (env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.build));
} }
@ -648,8 +651,11 @@ struct PushNotifications::Pimpl
return LocalRef<jobject> (env->NewObject (builderClass, builderConstructor, context.get())); return LocalRef<jobject> (env->NewObject (builderClass, builderConstructor, context.get()));
} }
static void setupRequiredFields (const Notification& n, LocalRef<jobject>& notificationBuilder) static LocalRef<jobject> setupRequiredFields (const Notification& n, LocalRef<jobject> notificationBuilder)
{ {
if (notificationBuilder == nullptr)
return notificationBuilder;
auto* env = getEnv(); auto* env = getEnv();
LocalRef<jobject> context (getMainActivity()); LocalRef<jobject> context (getMainActivity());
@ -676,9 +682,17 @@ struct PushNotifications::Pimpl
env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setContentIntent, notifyPendingIntent.get()); env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setContentIntent, notifyPendingIntent.get());
auto resources = LocalRef<jobject> (env->CallObjectMethod (context.get(), AndroidContext.getResources)); auto resources = LocalRef<jobject> (env->CallObjectMethod (context.get(), AndroidContext.getResources));
const int iconId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (n.icon).get(), const auto iconId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (n.icon).get(),
javaString ("raw").get(), packageNameString.get()); javaString ("raw").get(), packageNameString.get());
if (iconId == 0)
{
// If you hit this, the notification icon could not be located, and the notification
// will not be sent.
jassertfalse;
return {};
}
env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setSmallIcon, iconId); env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setSmallIcon, iconId);
if (n.publicVersion != nullptr) if (n.publicVersion != nullptr)
@ -688,12 +702,17 @@ struct PushNotifications::Pimpl
auto publicNotificationBuilder = createNotificationBuilder (n); auto publicNotificationBuilder = createNotificationBuilder (n);
setupRequiredFields (*n.publicVersion, publicNotificationBuilder); publicNotificationBuilder = setupRequiredFields (*n.publicVersion, publicNotificationBuilder);
setupOptionalFields (*n.publicVersion, publicNotificationBuilder); publicNotificationBuilder = setupOptionalFields (*n.publicVersion, publicNotificationBuilder);
if (publicNotificationBuilder == nullptr)
return {};
auto publicVersion = LocalRef<jobject> (env->CallObjectMethod (publicNotificationBuilder, NotificationBuilderApi16.build)); auto publicVersion = LocalRef<jobject> (env->CallObjectMethod (publicNotificationBuilder, NotificationBuilderApi16.build));
env->CallObjectMethod (notificationBuilder, NotificationBuilderApi21.setPublicVersion, publicVersion.get()); env->CallObjectMethod (notificationBuilder, NotificationBuilderApi21.setPublicVersion, publicVersion.get());
} }
return notificationBuilder;
} }
static LocalRef<jobject> juceNotificationToBundle (const Notification& n) static LocalRef<jobject> juceNotificationToBundle (const Notification& n)
@ -753,8 +772,11 @@ struct PushNotifications::Pimpl
return bundle; return bundle;
} }
static void setupOptionalFields (const Notification& n, LocalRef<jobject>& notificationBuilder) static LocalRef<jobject> setupOptionalFields (const Notification n, LocalRef<jobject>& notificationBuilder)
{ {
if (notificationBuilder == nullptr)
return notificationBuilder;
auto* env = getEnv(); auto* env = getEnv();
if (n.subtitle.isNotEmpty()) if (n.subtitle.isNotEmpty())
@ -871,12 +893,15 @@ struct PushNotifications::Pimpl
env->CallObjectMethod (notificationBuilder, NotificationBuilderApi26.setTimeoutAfter, (jlong) n.timeoutAfterMs); env->CallObjectMethod (notificationBuilder, NotificationBuilderApi26.setTimeoutAfter, (jlong) n.timeoutAfterMs);
} }
setupNotificationDeletedCallback (n, notificationBuilder); return setupNotificationDeletedCallback (n, notificationBuilder);
} }
static void setupNotificationDeletedCallback (const Notification& n, static LocalRef<jobject> setupNotificationDeletedCallback (const Notification& n,
LocalRef<jobject>& notificationBuilder) LocalRef<jobject> notificationBuilder)
{ {
if (notificationBuilder == nullptr)
return notificationBuilder;
auto* env = getEnv(); auto* env = getEnv();
LocalRef<jobject> context (getMainActivity()); LocalRef<jobject> context (getMainActivity());
@ -898,16 +923,19 @@ struct PushNotifications::Pimpl
0)); 0));
env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setDeleteIntent, deletePendingIntent.get()); env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setDeleteIntent, deletePendingIntent.get());
return notificationBuilder;
} }
static void setupActions (const Notification& n, LocalRef<jobject>& notificationBuilder) static LocalRef<jobject> setupActions (const Notification& n, LocalRef<jobject> notificationBuilder)
{ {
if (notificationBuilder == nullptr || n.actions.isEmpty())
return notificationBuilder;
auto* env = getEnv(); auto* env = getEnv();
LocalRef<jobject> context (getMainActivity()); LocalRef<jobject> context (getMainActivity());
int actionIndex = 0; for (const auto [actionIndex, action] : enumerate (n.actions))
for (const auto& action : n.actions)
{ {
auto activityClass = LocalRef<jobject> (env->CallObjectMethod (context.get(), JavaObject.getClass)); auto activityClass = LocalRef<jobject> (env->CallObjectMethod (context.get(), JavaObject.getClass));
auto notifyIntent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructorWithContextAndClass, context.get(), activityClass.get())); auto notifyIntent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructorWithContextAndClass, context.get(), activityClass.get()));
@ -938,6 +966,14 @@ struct PushNotifications::Pimpl
iconId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (n.icon).get(), iconId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (n.icon).get(),
javaString ("raw").get(), packageNameString.get()); javaString ("raw").get(), packageNameString.get());
if (iconId == 0)
{
// If this is hit, the notification icon could not be located, so the notification
// cannot be displayed.
jassertfalse;
return {};
}
auto actionBuilder = LocalRef<jobject> (env->NewObject (NotificationActionBuilder, auto actionBuilder = LocalRef<jobject> (env->NewObject (NotificationActionBuilder,
NotificationActionBuilder.constructor, NotificationActionBuilder.constructor,
iconId, iconId,
@ -982,9 +1018,9 @@ struct PushNotifications::Pimpl
env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.addAction, env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.addAction,
env->CallObjectMethod (actionBuilder, NotificationActionBuilder.build)); env->CallObjectMethod (actionBuilder, NotificationActionBuilder.build));
++actionIndex;
} }
return notificationBuilder;
} }
static LocalRef<jobject> juceUrlToAndroidUri (const URL& url) static LocalRef<jobject> juceUrlToAndroidUri (const URL& url)