|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662 |
- /*
- ==============================================================================
-
- This file is part of the JUCE 6 technical preview.
- Copyright (c) 2020 - Raw Material Software Limited
-
- You may use this code under the terms of the GPL v3
- (see www.gnu.org/licenses).
-
- For this technical preview, this file is not subject to commercial licensing.
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (constructor, "<init>", "(Ljava/lang/String;Ljava/lang/CharSequence;I)V") \
- METHOD (enableLights, "enableLights", "(Z)V") \
- METHOD (enableVibration, "enableVibration", "(Z)V") \
- METHOD (setBypassDnd, "setBypassDnd", "(Z)V") \
- METHOD (setDescription, "setDescription", "(Ljava/lang/String;)V") \
- METHOD (setGroup, "setGroup", "(Ljava/lang/String;)V") \
- METHOD (setImportance, "setImportance", "(I)V") \
- METHOD (setLightColor, "setLightColor", "(I)V") \
- METHOD (setLockscreenVisibility, "setLockscreenVisibility", "(I)V") \
- METHOD (setShowBadge, "setShowBadge", "(Z)V") \
- METHOD (setSound, "setSound", "(Landroid/net/Uri;Landroid/media/AudioAttributes;)V") \
- METHOD (setVibrationPattern, "setVibrationPattern", "([J)V")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationChannel, "android/app/NotificationChannel", 26)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (constructor, "<init>", "(Ljava/lang/String;Ljava/lang/CharSequence;)V")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationChannelGroup, "android/app/NotificationChannelGroup", 26)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- FIELD (extras, "extras", "Landroid/os/Bundle;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidNotification, "android/app/Notification", 19)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (addExtras, "addExtras", "(Landroid/os/Bundle;)Landroid/app/Notification$Action$Builder;") \
- METHOD (addRemoteInput, "addRemoteInput", "(Landroid/app/RemoteInput;)Landroid/app/Notification$Action$Builder;") \
- METHOD (constructor, "<init>", "(ILjava/lang/CharSequence;Landroid/app/PendingIntent;)V") \
- METHOD (build, "build", "()Landroid/app/Notification$Action;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationActionBuilder, "android/app/Notification$Action$Builder", 20)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (getNotification, "getNotification", "()Landroid/app/Notification;") \
- METHOD (setAutoCancel, "setAutoCancel", "(Z)Landroid/app/Notification$Builder;") \
- METHOD (setContentInfo, "setContentInfo", "(Ljava/lang/CharSequence;)Landroid/app/Notification$Builder;") \
- METHOD (setContentIntent, "setContentIntent", "(Landroid/app/PendingIntent;)Landroid/app/Notification$Builder;") \
- METHOD (setContentText, "setContentText", "(Ljava/lang/CharSequence;)Landroid/app/Notification$Builder;") \
- METHOD (setContentTitle, "setContentTitle", "(Ljava/lang/CharSequence;)Landroid/app/Notification$Builder;") \
- METHOD (setDefaults, "setDefaults", "(I)Landroid/app/Notification$Builder;") \
- METHOD (setDeleteIntent, "setDeleteIntent", "(Landroid/app/PendingIntent;)Landroid/app/Notification$Builder;") \
- METHOD (setLargeIcon, "setLargeIcon", "(Landroid/graphics/Bitmap;)Landroid/app/Notification$Builder;") \
- METHOD (setLights, "setLights", "(III)Landroid/app/Notification$Builder;") \
- METHOD (setNumber, "setNumber", "(I)Landroid/app/Notification$Builder;") \
- METHOD (setOngoing, "setOngoing", "(Z)Landroid/app/Notification$Builder;") \
- METHOD (setOnlyAlertOnce, "setOnlyAlertOnce", "(Z)Landroid/app/Notification$Builder;") \
- METHOD (setProgress, "setProgress", "(IIZ)Landroid/app/Notification$Builder;") \
- METHOD (setSmallIcon, "setSmallIcon", "(I)Landroid/app/Notification$Builder;") \
- METHOD (setSound, "setSound", "(Landroid/net/Uri;)Landroid/app/Notification$Builder;") \
- METHOD (setTicker, "setTicker", "(Ljava/lang/CharSequence;)Landroid/app/Notification$Builder;") \
- METHOD (setVibrate, "setVibrate", "([J)Landroid/app/Notification$Builder;") \
- METHOD (setWhen, "setWhen", "(J)Landroid/app/Notification$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationBuilderBase, "android/app/Notification$Builder", 11)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (addAction, "addAction", "(ILjava/lang/CharSequence;Landroid/app/PendingIntent;)Landroid/app/Notification$Builder;") \
- METHOD (build, "build", "()Landroid/app/Notification;") \
- METHOD (setPriority, "setPriority", "(I)Landroid/app/Notification$Builder;") \
- METHOD (setSubText, "setSubText", "(Ljava/lang/CharSequence;)Landroid/app/Notification$Builder;") \
- METHOD (setUsesChronometer, "setUsesChronometer", "(Z)Landroid/app/Notification$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationBuilderApi16, "android/app/Notification$Builder", 16)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (setShowWhen, "setShowWhen", "(Z)Landroid/app/Notification$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationBuilderApi17, "android/app/Notification$Builder", 17)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (addAction, "addAction", "(Landroid/app/Notification$Action;)Landroid/app/Notification$Builder;") \
- METHOD (addExtras, "addExtras", "(Landroid/os/Bundle;)Landroid/app/Notification$Builder;") \
- METHOD (setLocalOnly, "setLocalOnly", "(Z)Landroid/app/Notification$Builder;") \
- METHOD (setGroup, "setGroup", "(Ljava/lang/String;)Landroid/app/Notification$Builder;") \
- METHOD (setGroupSummary, "setGroupSummary", "(Z)Landroid/app/Notification$Builder;") \
- METHOD (setSortKey, "setSortKey", "(Ljava/lang/String;)Landroid/app/Notification$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationBuilderApi20, "android/app/Notification$Builder", 20)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (addPerson, "addPerson", "(Ljava/lang/String;)Landroid/app/Notification$Builder;") \
- METHOD (setCategory, "setCategory", "(Ljava/lang/String;)Landroid/app/Notification$Builder;") \
- METHOD (setColor, "setColor", "(I)Landroid/app/Notification$Builder;") \
- METHOD (setPublicVersion, "setPublicVersion", "(Landroid/app/Notification;)Landroid/app/Notification$Builder;") \
- METHOD (setVisibility, "setVisibility", "(I)Landroid/app/Notification$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationBuilderApi21, "android/app/Notification$Builder", 21)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (setChronometerCountDown, "setChronometerCountDown", "(Z)Landroid/app/Notification$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationBuilderApi24, "android/app/Notification$Builder", 24)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (setBadgeIconType, "setBadgeIconType", "(I)Landroid/app/Notification$Builder;") \
- METHOD (setGroupAlertBehavior, "setGroupAlertBehavior", "(I)Landroid/app/Notification$Builder;") \
- METHOD (setTimeoutAfter, "setTimeoutAfter", "(J)Landroid/app/Notification$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationBuilderApi26, "android/app/Notification$Builder", 26)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (cancel, "cancel", "(Ljava/lang/String;I)V") \
- METHOD (cancelAll, "cancelAll", "()V") \
- METHOD (notify, "notify", "(Ljava/lang/String;ILandroid/app/Notification;)V")
-
- DECLARE_JNI_CLASS (NotificationManagerBase, "android/app/NotificationManager")
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (getActiveNotifications, "getActiveNotifications", "()[Landroid/service/notification/StatusBarNotification;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationManagerApi23, "android/app/NotificationManager", 23)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (areNotificationsEnabled, "areNotificationsEnabled", "()Z")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationManagerApi24, "android/app/NotificationManager", 24)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (createNotificationChannel, "createNotificationChannel", "(Landroid/app/NotificationChannel;)V") \
- METHOD (createNotificationChannelGroup, "createNotificationChannelGroup", "(Landroid/app/NotificationChannelGroup;)V")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (NotificationManagerApi26, "android/app/NotificationManager", 26)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- STATICMETHOD (getResultsFromIntent, "getResultsFromIntent", "(Landroid/content/Intent;)Landroid/os/Bundle;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (RemoteInput, "android/app/RemoteInput", 20)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (constructor, "<init>", "(Ljava/lang/String;)V") \
- METHOD (build, "build", "()Landroid/app/RemoteInput;") \
- METHOD (setAllowFreeFormInput, "setAllowFreeFormInput", "(Z)Landroid/app/RemoteInput$Builder;") \
- METHOD (setChoices, "setChoices", "([Ljava/lang/CharSequence;)Landroid/app/RemoteInput$Builder;") \
- METHOD (setLabel, "setLabel", "(Ljava/lang/CharSequence;)Landroid/app/RemoteInput$Builder;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (RemoteInputBuilder, "android/app/RemoteInput$Builder", 20)
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (getNotification, "getNotification", "()Landroid/app/Notification;")
-
- DECLARE_JNI_CLASS_WITH_MIN_SDK (StatusBarNotification, "android/service/notification/StatusBarNotification", 23)
- #undef JNI_CLASS_MEMBERS
-
- //==============================================================================
- #if defined(JUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME)
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- STATICMETHOD (getInstance, "getInstance", "()Lcom/google/firebase/iid/FirebaseInstanceId;") \
- METHOD (getToken, "getToken", "()Ljava/lang/String;")
-
- DECLARE_JNI_CLASS (FirebaseInstanceId, "com/google/firebase/iid/FirebaseInstanceId")
- #undef JNI_CLASS_MEMBERS
- #endif
-
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- STATICMETHOD (getInstance, "getInstance", "()Lcom/google/firebase/messaging/FirebaseMessaging;") \
- METHOD (send, "send", "(Lcom/google/firebase/messaging/RemoteMessage;)V") \
- METHOD (subscribeToTopic, "subscribeToTopic", "(Ljava/lang/String;)Lcom/google/android/gms/tasks/Task;") \
- METHOD (unsubscribeFromTopic, "unsubscribeFromTopic", "(Ljava/lang/String;)Lcom/google/android/gms/tasks/Task;") \
-
- DECLARE_JNI_CLASS (FirebaseMessaging, "com/google/firebase/messaging/FirebaseMessaging")
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (getCollapseKey, "getCollapseKey", "()Ljava/lang/String;") \
- METHOD (getData, "getData", "()Ljava/util/Map;") \
- METHOD (getFrom, "getFrom", "()Ljava/lang/String;") \
- METHOD (getMessageId, "getMessageId", "()Ljava/lang/String;") \
- METHOD (getMessageType, "getMessageType", "()Ljava/lang/String;") \
- METHOD (getNotification, "getNotification", "()Lcom/google/firebase/messaging/RemoteMessage$Notification;") \
- METHOD (getSentTime, "getSentTime", "()J") \
- METHOD (getTo, "getTo", "()Ljava/lang/String;") \
- METHOD (getTtl, "getTtl", "()I")
-
- DECLARE_JNI_CLASS (RemoteMessage, "com/google/firebase/messaging/RemoteMessage")
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (addData, "addData", "(Ljava/lang/String;Ljava/lang/String;)Lcom/google/firebase/messaging/RemoteMessage$Builder;") \
- METHOD (build, "build", "()Lcom/google/firebase/messaging/RemoteMessage;") \
- METHOD (constructor, "<init>", "(Ljava/lang/String;)V") \
- METHOD (setCollapseKey, "setCollapseKey", "(Ljava/lang/String;)Lcom/google/firebase/messaging/RemoteMessage$Builder;") \
- METHOD (setMessageId, "setMessageId", "(Ljava/lang/String;)Lcom/google/firebase/messaging/RemoteMessage$Builder;") \
- METHOD (setMessageType, "setMessageType", "(Ljava/lang/String;)Lcom/google/firebase/messaging/RemoteMessage$Builder;") \
- METHOD (setTtl, "setTtl", "(I)Lcom/google/firebase/messaging/RemoteMessage$Builder;")
-
- DECLARE_JNI_CLASS (RemoteMessageBuilder, "com/google/firebase/messaging/RemoteMessage$Builder")
- #undef JNI_CLASS_MEMBERS
-
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- METHOD (getBody, "getBody", "()Ljava/lang/String;") \
- METHOD (getBodyLocalizationArgs, "getBodyLocalizationArgs", "()[Ljava/lang/String;") \
- METHOD (getBodyLocalizationKey, "getBodyLocalizationKey", "()Ljava/lang/String;") \
- METHOD (getClickAction, "getClickAction", "()Ljava/lang/String;") \
- METHOD (getColor, "getColor", "()Ljava/lang/String;") \
- METHOD (getIcon, "getIcon", "()Ljava/lang/String;") \
- METHOD (getLink, "getLink", "()Landroid/net/Uri;") \
- METHOD (getSound, "getSound", "()Ljava/lang/String;") \
- METHOD (getTag, "getTag", "()Ljava/lang/String;") \
- METHOD (getTitle, "getTitle", "()Ljava/lang/String;") \
- METHOD (getTitleLocalizationArgs, "getTitleLocalizationArgs", "()[Ljava/lang/String;") \
- METHOD (getTitleLocalizationKey, "getTitleLocalizationKey", "()Ljava/lang/String;")
-
- DECLARE_JNI_CLASS (RemoteMessageNotification, "com/google/firebase/messaging/RemoteMessage$Notification")
- #undef JNI_CLASS_MEMBERS
- #endif
-
- //==============================================================================
- bool PushNotifications::Notification::isValid() const noexcept
- {
- bool isValidForPreApi26 = title.isNotEmpty() && body.isNotEmpty() && identifier.isNotEmpty() && icon.isNotEmpty();
- bool apiAtLeast26 = (getAndroidSDKVersion() >= 26);
-
- if (apiAtLeast26)
- return isValidForPreApi26 && channelId.isNotEmpty();
-
- return isValidForPreApi26;
- }
-
- //==============================================================================
- struct PushNotifications::Pimpl
- {
- Pimpl (PushNotifications& p)
- : owner (p)
- {}
-
- bool areNotificationsEnabled() const
- {
- if (getAndroidSDKVersion() >= 24)
- {
- auto* env = getEnv();
-
- auto notificationManager = getNotificationManager();
-
- if (notificationManager.get() != nullptr)
- return env->CallBooleanMethod (notificationManager, NotificationManagerApi24.areNotificationsEnabled);
- }
-
- return true;
- }
-
- //==============================================================================
- void sendLocalNotification (const PushNotifications::Notification& n)
- {
- // All required fields have to be setup!
- jassert (n.isValid());
-
- auto* env = getEnv();
-
- auto notificationManager = getNotificationManager();
-
- if (notificationManager.get() != nullptr)
- {
- auto notification = juceNotificationToJavaNotification (n);
-
- auto tag = javaString (n.identifier);
- const int id = 0;
-
- env->CallVoidMethod (notificationManager.get(), NotificationManagerBase.notify, tag.get(), id, notification.get());
- }
- }
-
- void getDeliveredNotifications() const
- {
- if (getAndroidSDKVersion() >= 23)
- {
- auto* env = getEnv();
-
- Array<PushNotifications::Notification> notifications;
-
- auto notificationManager = getNotificationManager();
- jassert (notificationManager != nullptr);
-
- if (notificationManager.get() != nullptr)
- {
- auto statusBarNotifications = LocalRef<jobjectArray> ((jobjectArray)env->CallObjectMethod (notificationManager,
- NotificationManagerApi23.getActiveNotifications));
-
- const int numNotifications = env->GetArrayLength (statusBarNotifications.get());
-
- for (int i = 0; i < numNotifications; ++i)
- {
- auto statusBarNotification = LocalRef<jobject> (env->GetObjectArrayElement (statusBarNotifications.get(), (jsize) i));
- auto notification = LocalRef<jobject> (env->CallObjectMethod (statusBarNotification, StatusBarNotification.getNotification));
-
- notifications.add (javaNotificationToJuceNotification (notification));
- }
- }
-
- owner.listeners.call ([&] (Listener& l) { l.deliveredNotificationsListReceived (notifications); });
- }
- else
- {
- // Not supported on this platform
- jassertfalse;
- owner.listeners.call ([] (Listener& l) { l.deliveredNotificationsListReceived ({}); });
- }
- }
-
- void notifyListenersAboutLocalNotification (const LocalRef<jobject>& intent)
- {
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- auto bundle = LocalRef<jobject> (env->CallObjectMethod (intent, AndroidIntent.getExtras));
-
- const auto notification = localNotificationBundleToJuceNotification (bundle);
-
- auto packageName = juceString ((jstring) env->CallObjectMethod (context.get(), AndroidContext.getPackageName));
-
- String notificationString = packageName + ".JUCE_NOTIFICATION.";
- String notificationButtonActionString = packageName + ".JUCE_NOTIFICATION_BUTTON_ACTION.";
- String notificationTextInputActionString = packageName + ".JUCE_NOTIFICATION_TEXT_INPUT_ACTION.";
-
- auto actionString = juceString ((jstring) env->CallObjectMethod (intent, AndroidIntent.getAction));
-
- if (actionString.contains (notificationString))
- {
- owner.listeners.call ([&] (Listener& l) { l.handleNotification (true, notification); });
- }
- else if (actionString.contains (notificationButtonActionString))
- {
- auto prefix = notificationButtonActionString + notification.identifier + ".";
-
- auto actionTitle = actionString.fromLastOccurrenceOf (prefix, false, false) // skip prefix
- .fromFirstOccurrenceOf (".", false, false); // skip action index
-
- owner.listeners.call ([&] (Listener& l) { l.handleNotificationAction (true, notification, actionTitle, {}); });
- }
- else if (getAndroidSDKVersion() >= 20 && actionString.contains (notificationTextInputActionString))
- {
- auto prefix = notificationTextInputActionString + notification.identifier + ".";
-
- auto actionTitle = actionString.fromLastOccurrenceOf (prefix, false, false) // skip prefix
- .fromFirstOccurrenceOf (".", false, false); // skip action index
-
- auto actionIndex = actionString.fromLastOccurrenceOf (prefix, false, false).upToFirstOccurrenceOf (".", false, false);
- auto resultKeyString = javaString (actionTitle + actionIndex);
-
- auto remoteInputResult = LocalRef<jobject> (env->CallStaticObjectMethod (RemoteInput, RemoteInput.getResultsFromIntent, intent.get()));
- String responseString;
-
- if (remoteInputResult.get() == nullptr)
- {
- auto charSequence = LocalRef<jobject> (env->CallObjectMethod (remoteInputResult, AndroidBundle.getCharSequence, resultKeyString.get()));
- auto responseStringRef = LocalRef<jstring> ((jstring) env->CallObjectMethod (charSequence, JavaCharSequence.toString));
- responseString = juceString (responseStringRef.get());
- }
-
- owner.listeners.call ([&] (Listener& l) { l.handleNotificationAction (true, notification, actionTitle, responseString); });
- }
- }
-
- void notifyListenersAboutLocalNotificationDeleted (const LocalRef<jobject>& intent)
- {
- auto* env = getEnv();
-
- auto bundle = LocalRef<jobject> (env->CallObjectMethod (intent, AndroidIntent.getExtras));
- auto notification = localNotificationBundleToJuceNotification (bundle);
-
- owner.listeners.call ([&] (Listener& l) { l.localNotificationDismissedByUser (notification); });
- }
-
- void removeAllDeliveredNotifications()
- {
- auto* env = getEnv();
-
- auto notificationManager = getNotificationManager();
-
- if (notificationManager.get() != nullptr)
- env->CallVoidMethod (notificationManager.get(), NotificationManagerBase.cancelAll);
- }
-
- void removeDeliveredNotification (const String& identifier)
- {
- auto* env = getEnv();
-
- auto notificationManager = getNotificationManager();
-
- if (notificationManager.get() != nullptr)
- {
- auto tag = javaString (identifier);
- const int id = 0;
-
- env->CallVoidMethod (notificationManager.get(), NotificationManagerBase.cancel, tag.get(), id);
- }
- }
-
- //==============================================================================
- String getDeviceToken() const
- {
- #if defined(JUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME)
- auto* env = getEnv();
-
- auto instanceId = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseInstanceId, FirebaseInstanceId.getInstance));
-
- return juceString ((jstring) env->CallObjectMethod (instanceId, FirebaseInstanceId.getToken));
- #else
- return {};
- #endif
- }
-
- void notifyListenersTokenRefreshed (const String& token)
- {
- #if defined(JUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME)
- MessageManager::callAsync ([this, token]
- {
- owner.listeners.call ([&] (Listener& l) { l.deviceTokenRefreshed (token); });
- });
- #else
- ignoreUnused (token);
- #endif
- }
-
- //==============================================================================
- void subscribeToTopic (const String& topic)
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- auto* env = getEnv();
-
- auto firebaseMessaging = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseMessaging,
- FirebaseMessaging.getInstance));
-
- env->CallObjectMethod (firebaseMessaging, FirebaseMessaging.subscribeToTopic, javaString (topic).get());
- #else
- ignoreUnused (topic);
- #endif
- }
-
- void unsubscribeFromTopic (const String& topic)
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- auto* env = getEnv();
-
- auto firebaseMessaging = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseMessaging,
- FirebaseMessaging.getInstance));
-
- env->CallObjectMethod (firebaseMessaging, FirebaseMessaging.unsubscribeFromTopic, javaString (topic).get());
- #else
- ignoreUnused (topic);
- #endif
- }
-
- void sendUpstreamMessage (const String& serverSenderId,
- const String& collapseKey,
- const String& messageId,
- const String& messageType,
- int timeToLive,
- const StringPairArray& additionalData)
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- auto* env = getEnv();
-
- auto messageBuilder = LocalRef<jobject> (env->NewObject (RemoteMessageBuilder,
- RemoteMessageBuilder.constructor,
- javaString (serverSenderId + "@gcm_googleapis.com").get()));
-
- env->CallObjectMethod (messageBuilder, RemoteMessageBuilder.setCollapseKey, javaString (collapseKey).get());
- env->CallObjectMethod (messageBuilder, RemoteMessageBuilder.setMessageId, javaString (messageId).get());
- env->CallObjectMethod (messageBuilder, RemoteMessageBuilder.setMessageType, javaString (messageType).get());
- env->CallObjectMethod (messageBuilder, RemoteMessageBuilder.setTtl, timeToLive);
-
- auto keys = additionalData.getAllKeys();
-
- for (const auto& key : keys)
- env->CallObjectMethod (messageBuilder,
- RemoteMessageBuilder.addData,
- javaString (key).get(),
- javaString (additionalData[key]).get());
-
- auto message = LocalRef<jobject> (env->CallObjectMethod (messageBuilder, RemoteMessageBuilder.build));
-
- auto firebaseMessaging = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseMessaging,
- FirebaseMessaging.getInstance));
-
- env->CallVoidMethod (firebaseMessaging, FirebaseMessaging.send, message.get());
- #else
- ignoreUnused (serverSenderId, collapseKey, messageId, messageType);
- ignoreUnused (timeToLive, additionalData);
- #endif
- }
-
- void notifyListenersAboutRemoteNotificationFromSystemTray (const LocalRef<jobject>& intent)
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- auto* env = getEnv();
-
- auto bundle = LocalRef<jobject> (env->CallObjectMethod (intent, AndroidIntent.getExtras));
- auto notification = remoteNotificationBundleToJuceNotification (bundle);
-
- owner.listeners.call ([&] (Listener& l) { l.handleNotification (false, notification); });
- #else
- ignoreUnused (intent);
- #endif
- }
-
- void notifyListenersAboutRemoteNotificationFromService (const LocalRef<jobject>& remoteNotification)
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- GlobalRef rn (remoteNotification);
-
- MessageManager::callAsync ([this, rn]
- {
- auto notification = firebaseRemoteNotificationToJuceNotification (rn.get());
- owner.listeners.call ([&] (Listener& l) { l.handleNotification (false, notification); });
- });
- #else
- ignoreUnused (remoteNotification);
- #endif
- }
-
- void notifyListenersAboutRemoteNotificationsDeleted()
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- MessageManager::callAsync ([this]
- {
- owner.listeners.call ([] (Listener& l) { l.remoteNotificationsDeleted(); });
- });
- #endif
- }
-
- void notifyListenersAboutUpstreamMessageSent (const LocalRef<jstring>& messageId)
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- GlobalRef mid (LocalRef<jobject>(messageId.get()));
-
- MessageManager::callAsync ([this, mid]
- {
- auto midString = juceString ((jstring) mid.get());
- owner.listeners.call ([&] (Listener& l) { l.upstreamMessageSent (midString); });
- });
- #else
- ignoreUnused (messageId);
- #endif
- }
-
- void notifyListenersAboutUpstreamMessageSendingError (const LocalRef<jstring>& messageId,
- const LocalRef<jstring>& error)
- {
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- GlobalRef mid (LocalRef<jobject>(messageId.get())), e (LocalRef<jobject>(error.get()));
-
- MessageManager::callAsync ([this, mid, e]
- {
- auto midString = juceString ((jstring) mid.get());
- auto eString = juceString ((jstring) e.get());
-
- owner.listeners.call ([&] (Listener& l) { l.upstreamMessageSendingError (midString, eString); });
- });
- #else
- ignoreUnused (messageId, error);
- #endif
- }
-
- static LocalRef<jobject> getNotificationManager()
- {
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- return LocalRef<jobject> (env->CallObjectMethod (context.get(),
- AndroidContext.getSystemService,
- javaString ("notification").get()));
- }
-
- static LocalRef<jobject> juceNotificationToJavaNotification (const PushNotifications::Notification& n)
- {
- auto* env = getEnv();
-
- auto notificationBuilder = createNotificationBuilder (n);
-
- setupRequiredFields (n, notificationBuilder);
- setupOptionalFields (n, notificationBuilder);
-
- if (n.actions.size() > 0)
- setupActions (n, notificationBuilder);
-
- if (getAndroidSDKVersion() >= 16)
- return LocalRef<jobject> (env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.build));
-
- return LocalRef<jobject> (env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.getNotification));
- }
-
- static LocalRef<jobject> createNotificationBuilder (const PushNotifications::Notification& n)
- {
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- jclass builderClass = env->FindClass ("android/app/Notification$Builder");
- jassert (builderClass != nullptr);
-
- if (builderClass == nullptr)
- return LocalRef<jobject> (nullptr);
-
- jmethodID builderConstructor = nullptr;
-
- const bool apiAtLeast26 = (getAndroidSDKVersion() >= 26);
-
- if (apiAtLeast26)
- builderConstructor = env->GetMethodID (builderClass, "<init>", "(Landroid/content/Context;Ljava/lang/String;)V");
- else
- builderConstructor = env->GetMethodID (builderClass, "<init>", "(Landroid/content/Context;)V");
-
- jassert (builderConstructor != nullptr);
-
- if (builderConstructor == nullptr)
- return LocalRef<jobject> (nullptr);
-
- if (apiAtLeast26)
- return LocalRef<jobject> (env->NewObject (builderClass, builderConstructor,
- context.get(), javaString (n.channelId).get()));
-
- return LocalRef<jobject> (env->NewObject (builderClass, builderConstructor, context.get()));
- }
-
- static void setupRequiredFields (const PushNotifications::Notification& n, LocalRef<jobject>& notificationBuilder)
- {
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- auto activityClass = LocalRef<jobject> (env->CallObjectMethod (context.get(), JavaObject.getClass));
- auto notifyIntent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructorWithContextAndClass, context.get(), activityClass.get()));
-
- auto packageNameString = LocalRef<jstring> ((jstring) (env->CallObjectMethod (context.get(), AndroidContext.getPackageName)));
- auto actionStringSuffix = javaString (".JUCE_NOTIFICATION." + n.identifier);
- auto actionString = LocalRef<jstring> ((jstring)env->CallObjectMethod (packageNameString, JavaString.concat, actionStringSuffix.get()));
-
- env->CallObjectMethod (notifyIntent, AndroidIntent.setAction, actionString.get());
- // Packaging entire notification into extras bundle here, so that we can retrieve all the details later on
- env->CallObjectMethod (notifyIntent, AndroidIntent.putExtras, juceNotificationToBundle (n).get());
-
- auto notifyPendingIntent = LocalRef<jobject> (env->CallStaticObjectMethod (AndroidPendingIntent,
- AndroidPendingIntent.getActivity,
- context.get(),
- 1002,
- notifyIntent.get(),
- 0));
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setContentTitle, javaString (n.title).get());
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setContentText, javaString (n.body).get());
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setContentIntent, notifyPendingIntent.get());
-
- auto resources = LocalRef<jobject> (env->CallObjectMethod (context.get(), AndroidContext.getResources));
- const int iconId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (n.icon).get(),
- javaString ("raw").get(), packageNameString.get());
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setSmallIcon, iconId);
-
- if (getAndroidSDKVersion() >= 21 && n.publicVersion != nullptr)
- {
- // Public version of a notification is not expected to have another public one!
- jassert (n.publicVersion->publicVersion == nullptr);
-
- auto publicNotificationBuilder = createNotificationBuilder (n);
-
- setupRequiredFields (*n.publicVersion, publicNotificationBuilder);
- setupOptionalFields (*n.publicVersion, publicNotificationBuilder);
-
- auto publicVersion = LocalRef<jobject> (env->CallObjectMethod (publicNotificationBuilder, NotificationBuilderApi16.build));
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi21.setPublicVersion, publicVersion.get());
- }
- }
-
- static LocalRef<jobject> juceNotificationToBundle (const PushNotifications::Notification& n)
- {
- auto* env = getEnv();
-
- auto bundle = LocalRef<jobject> (env->NewObject (AndroidBundle, AndroidBundle.constructor));
-
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("identifier") .get(), javaString (n.identifier).get());
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("title") .get(), javaString (n.title).get());
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("body") .get(), javaString (n.body).get());
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("subtitle") .get(), javaString (n.subtitle).get());
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("badgeNumber") .get(), n.badgeNumber);
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("soundToPlay") .get(), javaString (n.soundToPlay.toString (true)).get());
- env->CallVoidMethod (bundle, AndroidBundle.putBundle, javaString ("properties") .get(), varToBundleWithPropertiesString (n.properties).get());
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("icon") .get(), javaString (n.icon).get());
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("channelId") .get(), javaString (n.channelId).get());
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("tickerText") .get(), javaString (n.tickerText).get());
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("progressMax") .get(), n.progress.max);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("progressCurrent") .get(), n.progress.current);
- env->CallVoidMethod (bundle, AndroidBundle.putBoolean, javaString ("progressIndeterminate") .get(), n.progress.indeterminate);
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("person") .get(), javaString (n.person).get());
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("type") .get(), n.type);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("priority") .get(), n.priority);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("lockScreenAppearance") .get(), n.lockScreenAppearance);
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("groupId") .get(), javaString (n.groupId).get());
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("groupSortKey") .get(), javaString (n.groupSortKey).get());
- env->CallVoidMethod (bundle, AndroidBundle.putBoolean, javaString ("groupSummary") .get(), n.groupSummary);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("accentColour") .get(), n.accentColour.getARGB());
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("ledColour") .get(), n.ledColour.getARGB());
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("ledBlinkPatternMsToBeOn") .get(), n.ledBlinkPattern.msToBeOn);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("ledBlinkPatternMsToBeOff").get(), n.ledBlinkPattern.msToBeOff);
- env->CallVoidMethod (bundle, AndroidBundle.putBoolean, javaString ("shouldAutoCancel") .get(), n.shouldAutoCancel);
- env->CallVoidMethod (bundle, AndroidBundle.putBoolean, javaString ("localOnly") .get(), n.localOnly);
- env->CallVoidMethod (bundle, AndroidBundle.putBoolean, javaString ("ongoing") .get(), n.ongoing);
- env->CallVoidMethod (bundle, AndroidBundle.putBoolean, javaString ("alertOnlyOnce") .get(), n.alertOnlyOnce);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("timestampVisibility") .get(), n.timestampVisibility);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("badgeIconType") .get(), n.badgeIconType);
- env->CallVoidMethod (bundle, AndroidBundle.putInt, javaString ("groupAlertBehaviour") .get(), n.groupAlertBehaviour);
- env->CallVoidMethod (bundle, AndroidBundle.putLong, javaString ("timeoutAfterMs") .get(), (jlong)n.timeoutAfterMs);
-
- const int size = n.vibrationPattern.size();
-
- if (size > 0)
- {
- auto array = LocalRef<jlongArray> (env->NewLongArray (size));
-
- jlong* elements = env->GetLongArrayElements (array, nullptr);
-
- for (int i = 0; i < size; ++i)
- elements[i] = (jlong) n.vibrationPattern[i];
-
- env->SetLongArrayRegion (array, 0, size, elements);
- env->CallVoidMethod (bundle, AndroidBundle.putLongArray, javaString ("vibrationPattern").get(), array.get());
- }
-
- return bundle;
- }
-
- static void setupOptionalFields (const PushNotifications::Notification& n, LocalRef<jobject>& notificationBuilder)
- {
- auto* env = getEnv();
-
- if (n.subtitle.isNotEmpty())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setContentInfo, javaString (n.subtitle).get());
-
- auto soundName = n.soundToPlay.toString (true);
-
- if (soundName == "default_os_sound")
- {
- const int playDefaultSound = 1;
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setDefaults, playDefaultSound);
- }
- else if (! soundName.isEmpty())
- {
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setSound, juceUrlToAndroidUri (n.soundToPlay).get());
- }
-
- if (n.largeIcon.isValid())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setLargeIcon, imagetoJavaBitmap (n.largeIcon).get());
-
- if (n.tickerText.isNotEmpty())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setTicker, javaString (n.tickerText).get());
-
- if (n.ledColour != Colour())
- {
- env->CallObjectMethod (notificationBuilder,
- NotificationBuilderBase.setLights,
- n.ledColour.getARGB(),
- n.ledBlinkPattern.msToBeOn,
- n.ledBlinkPattern.msToBeOff);
- }
-
- if (! n.vibrationPattern.isEmpty())
- {
- const int size = n.vibrationPattern.size();
-
- if (size > 0)
- {
- auto array = LocalRef<jlongArray> (env->NewLongArray (size));
-
- jlong* elements = env->GetLongArrayElements (array, nullptr);
-
- for (int i = 0; i < size; ++i)
- elements[i] = (jlong) n.vibrationPattern[i];
-
- env->SetLongArrayRegion (array, 0, size, elements);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setVibrate, array.get());
- }
- }
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setProgress, n.progress.max, n.progress.current, n.progress.indeterminate);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setNumber, n.badgeNumber);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setAutoCancel, n.shouldAutoCancel);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setOngoing, n.ongoing);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setOnlyAlertOnce, n.alertOnlyOnce);
-
- if (getAndroidSDKVersion() >= 16)
- {
- if (n.subtitle.isNotEmpty())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.setSubText, javaString (n.subtitle).get());
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.setPriority, n.priority);
-
- if (getAndroidSDKVersion() < 24)
- {
- const bool useChronometer = n.timestampVisibility == PushNotifications::Notification::chronometer;
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.setUsesChronometer, useChronometer);
- }
- }
-
- if (getAndroidSDKVersion() >= 17)
- {
- const bool showTimeStamp = n.timestampVisibility != PushNotifications::Notification::off;
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi17.setShowWhen, showTimeStamp);
- }
-
- if (getAndroidSDKVersion() >= 20)
- {
- if (n.groupId.isNotEmpty())
- {
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.setGroup, javaString (n.groupId).get());
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.setGroupSummary, n.groupSummary);
- }
-
- if (n.groupSortKey.isNotEmpty())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.setSortKey, javaString (n.groupSortKey).get());
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.setLocalOnly, n.localOnly);
-
- auto extras = LocalRef<jobject> (env->NewObject (AndroidBundle, AndroidBundle.constructor));
-
- env->CallVoidMethod (extras, AndroidBundle.putBundle, javaString ("notificationData").get(),
- juceNotificationToBundle (n).get());
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.addExtras, extras.get());
- }
-
- if (getAndroidSDKVersion() >= 21)
- {
- if (n.person.isNotEmpty())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi21.addPerson, javaString (n.person).get());
-
- auto categoryString = typeToCategory (n.type);
- if (categoryString.isNotEmpty())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi21.setCategory, javaString (categoryString).get());
-
- if (n.accentColour != Colour())
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi21.setColor, n.accentColour.getARGB());
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi21.setVisibility, n.lockScreenAppearance);
- }
-
- if (getAndroidSDKVersion() >= 24)
- {
- const bool useChronometer = n.timestampVisibility == PushNotifications::Notification::chronometer;
- const bool useCountDownChronometer = n.timestampVisibility == PushNotifications::Notification::countDownChronometer;
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi24.setChronometerCountDown, useCountDownChronometer);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.setUsesChronometer, useChronometer | useCountDownChronometer);
- }
-
- if (getAndroidSDKVersion() >= 26)
- {
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi26.setBadgeIconType, n.badgeIconType);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi26.setGroupAlertBehavior, n.groupAlertBehaviour);
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi26.setTimeoutAfter, (jlong) n.timeoutAfterMs);
- }
-
- setupNotificationDeletedCallback (n, notificationBuilder);
- }
-
- static void setupNotificationDeletedCallback (const PushNotifications::Notification& n,
- LocalRef<jobject>& notificationBuilder)
- {
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- auto activityClass = LocalRef<jobject> (env->CallObjectMethod (context.get(), JavaObject.getClass));
- auto deleteIntent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructorWithContextAndClass, context.get(), activityClass.get()));
-
- auto packageNameString = LocalRef<jstring> ((jstring) (env->CallObjectMethod (context.get(), AndroidContext.getPackageName)));
- auto actionStringSuffix = javaString (".JUCE_NOTIFICATION_DELETED." + n.identifier);
- auto actionString = LocalRef<jstring> ((jstring)env->CallObjectMethod (packageNameString, JavaString.concat, actionStringSuffix.get()));
-
- env->CallObjectMethod (deleteIntent, AndroidIntent.setAction, actionString.get());
- env->CallObjectMethod (deleteIntent, AndroidIntent.putExtras, juceNotificationToBundle (n).get());
-
- auto deletePendingIntent = LocalRef<jobject> (env->CallStaticObjectMethod (AndroidPendingIntent,
- AndroidPendingIntent.getActivity,
- context.get(),
- 1002,
- deleteIntent.get(),
- 0));
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderBase.setDeleteIntent, deletePendingIntent.get());
- }
-
- static void setupActions (const PushNotifications::Notification& n, LocalRef<jobject>& notificationBuilder)
- {
- if (getAndroidSDKVersion() < 16)
- return;
-
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- int actionIndex = 0;
-
- for (const auto& action : n.actions)
- {
- auto activityClass = LocalRef<jobject> (env->CallObjectMethod (context.get(), JavaObject.getClass));
- auto notifyIntent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructorWithContextAndClass, context.get(), activityClass.get()));
-
- const bool isTextStyle = action.style == PushNotifications::Notification::Action::text;
-
- auto packageNameString = LocalRef<jstring> ((jstring) (env->CallObjectMethod (context.get(), AndroidContext.getPackageName)));
- const String notificationActionString = isTextStyle ? ".JUCE_NOTIFICATION_TEXT_INPUT_ACTION." : ".JUCE_NOTIFICATION_BUTTON_ACTION.";
- auto actionStringSuffix = javaString (notificationActionString + n.identifier + "." + String (actionIndex) + "." + action.title);
- auto actionString = LocalRef<jstring> ((jstring)env->CallObjectMethod (packageNameString, JavaString.concat, actionStringSuffix.get()));
-
- env->CallObjectMethod (notifyIntent, AndroidIntent.setAction, actionString.get());
- // Packaging entire notification into extras bundle here, so that we can retrieve all the details later on
- env->CallObjectMethod (notifyIntent, AndroidIntent.putExtras, juceNotificationToBundle (n).get());
-
- auto notifyPendingIntent = LocalRef<jobject> (env->CallStaticObjectMethod (AndroidPendingIntent,
- AndroidPendingIntent.getActivity,
- context.get(),
- 1002,
- notifyIntent.get(),
- 0));
-
- auto resources = LocalRef<jobject> (env->CallObjectMethod (context.get(), AndroidContext.getResources));
- int iconId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (action.icon).get(),
- javaString ("raw").get(), packageNameString.get());
-
- if (iconId == 0)
- iconId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (n.icon).get(),
- javaString ("raw").get(), packageNameString.get());
-
- if (getAndroidSDKVersion() >= 20)
- {
- auto actionBuilder = LocalRef<jobject> (env->NewObject (NotificationActionBuilder,
- NotificationActionBuilder.constructor,
- iconId,
- javaString (action.title).get(),
- notifyPendingIntent.get()));
-
- env->CallObjectMethod (actionBuilder, NotificationActionBuilder.addExtras,
- varToBundleWithPropertiesString (action.parameters).get());
-
- if (isTextStyle)
- {
- auto resultKey = javaString (action.title + String (actionIndex));
- auto remoteInputBuilder = LocalRef<jobject> (env->NewObject (RemoteInputBuilder,
- RemoteInputBuilder.constructor,
- resultKey.get()));
-
- if (! action.textInputPlaceholder.isEmpty())
- env->CallObjectMethod (remoteInputBuilder, RemoteInputBuilder.setLabel, javaString (action.textInputPlaceholder).get());
-
- if (! action.allowedResponses.isEmpty())
- {
- env->CallObjectMethod (remoteInputBuilder, RemoteInputBuilder.setAllowFreeFormInput, false);
-
- const int size = action.allowedResponses.size();
-
- auto array = LocalRef<jobjectArray> (env->NewObjectArray (size, env->FindClass ("java/lang/String"), nullptr));
-
- for (int i = 0; i < size; ++i)
- {
- const auto& response = action.allowedResponses[i];
- auto responseString = javaString (response);
-
- env->SetObjectArrayElement (array, i, responseString.get());
- }
-
- env->CallObjectMethod (remoteInputBuilder, RemoteInputBuilder.setChoices, array.get());
- }
-
- env->CallObjectMethod (actionBuilder, NotificationActionBuilder.addRemoteInput,
- env->CallObjectMethod (remoteInputBuilder, RemoteInputBuilder.build));
- }
-
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi20.addAction,
- env->CallObjectMethod (actionBuilder, NotificationActionBuilder.build));
- }
- else
- {
- env->CallObjectMethod (notificationBuilder, NotificationBuilderApi16.addAction,
- iconId, javaString (action.title).get(), notifyPendingIntent.get());
- }
-
- ++actionIndex;
- }
- }
-
- static LocalRef<jobject> juceUrlToAndroidUri (const URL& url)
- {
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- auto packageNameString = LocalRef<jstring> ((jstring) (env->CallObjectMethod (context.get(), AndroidContext.getPackageName)));
-
- auto resources = LocalRef<jobject> (env->CallObjectMethod (context.get(), AndroidContext.getResources));
- const int id = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (url.toString (true)).get(),
- javaString ("raw").get(), packageNameString.get());
-
- auto schemeString = javaString ("android.resource://");
- auto resourceString = javaString ("/" + String (id));
- auto uriString = LocalRef<jstring> ((jstring) env->CallObjectMethod (schemeString, JavaString.concat, packageNameString.get()));
- uriString = LocalRef<jstring> ((jstring) env->CallObjectMethod (uriString, JavaString.concat, resourceString.get()));
-
- return LocalRef<jobject> (env->CallStaticObjectMethod (AndroidUri, AndroidUri.parse, uriString.get()));
- }
-
- static LocalRef<jobject> imagetoJavaBitmap (const Image& image)
- {
- auto* env = getEnv();
-
- Image imageToUse = image.convertedToFormat (Image::PixelFormat::ARGB);
-
- auto bitmapConfig = LocalRef<jobject> (env->CallStaticObjectMethod (AndroidBitmapConfig,
- AndroidBitmapConfig.valueOf,
- javaString ("ARGB_8888").get()));
-
- auto bitmap = LocalRef<jobject> (env->CallStaticObjectMethod (AndroidBitmap,
- AndroidBitmap.createBitmap,
- image.getWidth(),
- image.getHeight(),
- bitmapConfig.get()));
-
- for (int i = 0; i < image.getWidth(); ++i)
- for (int j = 0; j < image.getHeight(); ++j)
- env->CallVoidMethod (bitmap.get(), AndroidBitmap.setPixel, i, j, image.getPixelAt (i, j).getARGB());
-
- return bitmap;
- }
-
- static String typeToCategory (PushNotifications::Notification::Type t)
- {
- switch (t)
- {
- case PushNotifications::Notification::unspecified: return {};
- case PushNotifications::Notification::alarm: return "alarm";
- case PushNotifications::Notification::call: return "call";
- case PushNotifications::Notification::email: return "email";
- case PushNotifications::Notification::error: return "err";
- case PushNotifications::Notification::event: return "event";
- case PushNotifications::Notification::message: return "msg";
- case PushNotifications::Notification::taskProgress: return "progress";
- case PushNotifications::Notification::promo: return "promo";
- case PushNotifications::Notification::recommendation: return "recommendation";
- case PushNotifications::Notification::reminder: return "reminder";
- case PushNotifications::Notification::service: return "service";
- case PushNotifications::Notification::social: return "social";
- case PushNotifications::Notification::status: return "status";
- case PushNotifications::Notification::system: return "sys";
- case PushNotifications::Notification::transport: return "transport";
- }
-
- return {};
- }
-
- static LocalRef<jobject> varToBundleWithPropertiesString (const var& varToParse)
- {
- auto* env = getEnv();
-
- auto bundle = LocalRef<jobject> (env->NewObject (AndroidBundle, AndroidBundle.constructor));
- env->CallVoidMethod (bundle, AndroidBundle.putString, javaString ("properties").get(),
- javaString (JSON::toString (varToParse, false)).get());
-
- return bundle;
- }
-
- // Gets "properties" var from bundle.
- static var bundleWithPropertiesStringToVar (const LocalRef<jobject>& bundle)
- {
- auto* env = getEnv();
-
- auto varString = LocalRef<jstring> ((jstring)env->CallObjectMethod (bundle, AndroidBundle.getString,
- javaString ("properties").get()));
-
- var resultVar;
- JSON::parse (juceString (varString.get()), resultVar);
-
- // Note: We are not checking if result of parsing was okay, because there may be no properties set at all.
- return resultVar;
- }
-
- // Reverse of juceNotificationToBundle().
- static PushNotifications::Notification localNotificationBundleToJuceNotification (const LocalRef<jobject>& bundle)
- {
- auto* env = getEnv();
-
- PushNotifications::Notification n;
-
- if (bundle.get() != nullptr)
- {
- n.identifier = getStringFromBundle (env, "identifier", bundle);
- n.title = getStringFromBundle (env, "title", bundle);
- n.body = getStringFromBundle (env, "body", bundle);
- n.subtitle = getStringFromBundle (env, "subtitle", bundle);
- n.badgeNumber = getIntFromBundle (env, "badgeNumber", bundle);
- n.soundToPlay = URL (getStringFromBundle (env, "soundToPlay", bundle));
- n.properties = getPropertiesVarFromBundle (env, "properties", bundle);
- n.tickerText = getStringFromBundle (env, "tickerText", bundle);
- n.icon = getStringFromBundle (env, "icon", bundle);
- n.channelId = getStringFromBundle (env, "channelId", bundle);
-
- PushNotifications::Notification::Progress progress;
- progress.max = getIntFromBundle (env, "progressMax", bundle);
- progress.current = getIntFromBundle (env, "progressCurrent", bundle);
- progress.indeterminate = getBoolFromBundle (env, "progressIndeterminate", bundle);
- n.progress = progress;
-
- n.person = getStringFromBundle (env, "person", bundle);
- n.type = (PushNotifications::Notification::Type) getIntFromBundle (env, "type", bundle);
- n.priority = (PushNotifications::Notification::Priority) getIntFromBundle (env, "priority", bundle);
- n.lockScreenAppearance = (PushNotifications::Notification::LockScreenAppearance) getIntFromBundle (env, "lockScreenAppearance", bundle);
- n.groupId = getStringFromBundle (env, "groupId", bundle);
- n.groupSortKey = getStringFromBundle (env, "groupSortKey", bundle);
- n.groupSummary = getBoolFromBundle (env, "groupSummary", bundle);
- n.accentColour = Colour ((uint32) getIntFromBundle (env, "accentColour", bundle));
- n.ledColour = Colour ((uint32) getIntFromBundle (env, "ledColour", bundle));
-
- PushNotifications::Notification::LedBlinkPattern ledBlinkPattern;
- ledBlinkPattern.msToBeOn = getIntFromBundle (env, "ledBlinkPatternMsToBeOn", bundle);
- ledBlinkPattern.msToBeOff = getIntFromBundle (env, "ledBlinkPatternMsToBeOff", bundle);
- n.ledBlinkPattern = ledBlinkPattern;
-
- n.vibrationPattern = getLongArrayFromBundle (env, "vibrationPattern", bundle);
-
- n.shouldAutoCancel = getBoolFromBundle (env, "shouldAutoCancel", bundle);
- n.localOnly = getBoolFromBundle (env, "localOnly", bundle);
- n.ongoing = getBoolFromBundle (env, "ongoing", bundle);
- n.alertOnlyOnce = getBoolFromBundle (env, "alertOnlyOnce", bundle);
- n.timestampVisibility = (PushNotifications::Notification::TimestampVisibility) getIntFromBundle (env, "timestampVisibility", bundle);
- n.badgeIconType = (PushNotifications::Notification::BadgeIconType) getIntFromBundle (env, "badgeIconType", bundle);
- n.groupAlertBehaviour = (PushNotifications::Notification::GroupAlertBehaviour) getIntFromBundle (env, "groupAlertBehaviour", bundle);
- n.timeoutAfterMs = getLongFromBundle (env, "timeoutAfterMs", bundle);
- }
-
- return n;
- }
-
- static String getStringFromBundle (JNIEnv* env, const String& key, const LocalRef<jobject>& bundle)
- {
- auto keyString = javaString (key);
-
- if (env->CallBooleanMethod (bundle, AndroidBundle.containsKey, keyString.get()))
- {
- auto value = LocalRef<jstring> ((jstring)env->CallObjectMethod (bundle, AndroidBundle.getString, keyString.get()));
- return juceString (value);
- }
-
- return {};
- }
-
- static int getIntFromBundle (JNIEnv* env, const String& key, const LocalRef<jobject>& bundle)
- {
- auto keyString = javaString (key);
-
- if (env->CallBooleanMethod (bundle, AndroidBundle.containsKey, keyString.get()))
- return env->CallIntMethod (bundle, AndroidBundle.getInt, keyString.get());
-
- return 0;
- }
-
- // Converting to int on purpose!
- static int getLongFromBundle (JNIEnv* env, const String& key, const LocalRef<jobject>& bundle)
- {
- auto keyString = javaString (key);
-
- if (env->CallBooleanMethod (bundle, AndroidBundle.containsKey, keyString.get()))
- return (int) env->CallLongMethod (bundle, AndroidBundle.getLong, keyString.get());
-
- return 0;
- }
-
- static var getPropertiesVarFromBundle (JNIEnv* env, const String& key, const LocalRef<jobject>& bundle)
- {
- auto keyString = javaString (key);
-
- if (env->CallBooleanMethod (bundle, AndroidBundle.containsKey, keyString.get()))
- {
- auto value = LocalRef<jobject> (env->CallObjectMethod (bundle, AndroidBundle.getBundle, keyString.get()));
- return bundleWithPropertiesStringToVar (value);
- }
-
- return {};
- }
-
- static bool getBoolFromBundle (JNIEnv* env, const String& key, const LocalRef<jobject>& bundle)
- {
- auto keyString = javaString (key);
-
- if (env->CallBooleanMethod (bundle, AndroidBundle.containsKey, keyString.get()))
- return env->CallBooleanMethod (bundle, AndroidBundle.getBoolean, keyString.get());
-
- return false;
- }
-
- static Array<int> getLongArrayFromBundle (JNIEnv* env, const String& key, const LocalRef<jobject>& bundle)
- {
- auto keyString = javaString (key);
-
- if (env->CallBooleanMethod (bundle, AndroidBundle.containsKey, keyString.get()))
- {
- auto array = LocalRef<jlongArray> ((jlongArray) env->CallObjectMethod (bundle, AndroidBundle.getLongArray, keyString.get()));
-
- const int size = env->GetArrayLength (array.get());
-
- jlong* elements = env->GetLongArrayElements (array.get(), nullptr);
-
- Array<int> resultArray;
-
- for (int i = 0; i < size; ++i)
- resultArray.add ((int) *elements++);
-
- return resultArray;
- }
-
- return {};
- }
-
- static PushNotifications::Notification javaNotificationToJuceNotification (const LocalRef<jobject>& notification)
- {
- if (getAndroidSDKVersion() < 20)
- return {};
-
- auto* env = getEnv();
-
- auto extras = LocalRef<jobject> (env->GetObjectField (notification, AndroidNotification.extras));
- auto notificationData = LocalRef<jobject> (env->CallObjectMethod (extras, AndroidBundle.getBundle,
- javaString ("notificationData").get()));
-
- if (notificationData.get() != nullptr)
- return localNotificationBundleToJuceNotification (notificationData);
-
- return remoteNotificationBundleToJuceNotification (extras);
- }
-
- static PushNotifications::Notification remoteNotificationBundleToJuceNotification (const LocalRef<jobject>& bundle)
- {
- // This will probably work only for remote notifications that get delivered to system tray
- PushNotifications::Notification n;
- n.properties = bundleToVar (bundle);
-
- return n;
- }
-
- static var bundleToVar (const LocalRef<jobject>& bundle)
- {
- if (bundle.get() == nullptr)
- {
- auto* env = getEnv();
-
- auto keySet = LocalRef<jobject> (env->CallObjectMethod (bundle, AndroidBundle.keySet));
- auto iterator = LocalRef<jobject> (env->CallObjectMethod (keySet, JavaSet.iterator));
-
- DynamicObject::Ptr dynamicObject = new DynamicObject();
-
- for (;;)
- {
- if (! env->CallBooleanMethod (iterator, JavaIterator.hasNext))
- break;
-
- auto key = LocalRef<jstring> ((jstring) env->CallObjectMethod (iterator, JavaIterator.next));
- auto object = LocalRef<jobject> (env->CallObjectMethod (bundle, AndroidBundle.get, key.get()));
-
- if (object.get() != nullptr)
- {
- auto objectAsString = LocalRef<jstring> ((jstring) env->CallObjectMethod (object, JavaObject.toString));
- auto objectClass = LocalRef<jobject> (env->CallObjectMethod (object, JavaObject.getClass));
- auto classAsString = LocalRef<jstring> ((jstring) env->CallObjectMethod (objectClass, JavaClass.getName));
-
- // Note: It seems that Firebase delivers values as strings always, so this check is rather unnecessary,
- // at least until they change the behaviour.
- var value = juceString (classAsString) == "java.lang.Bundle" ? bundleToVar (object) : var (juceString (objectAsString.get()));
- dynamicObject->setProperty (juceString (key.get()), value);
- }
- else
- {
- dynamicObject->setProperty (juceString (key.get()), {});
- }
- }
-
- return var (dynamicObject.get());
- }
-
- return {};
- }
-
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- static PushNotifications::Notification firebaseRemoteNotificationToJuceNotification (jobject remoteNotification)
- {
- auto* env = getEnv();
-
- auto collapseKey = LocalRef<jstring> ((jstring) env->CallObjectMethod (remoteNotification, RemoteMessage.getCollapseKey));
- auto from = LocalRef<jstring> ((jstring) env->CallObjectMethod (remoteNotification, RemoteMessage.getFrom));
- auto messageId = LocalRef<jstring> ((jstring) env->CallObjectMethod (remoteNotification, RemoteMessage.getMessageId));
- auto messageType = LocalRef<jstring> ((jstring) env->CallObjectMethod (remoteNotification, RemoteMessage.getMessageType));
- auto to = LocalRef<jstring> ((jstring) env->CallObjectMethod (remoteNotification, RemoteMessage.getTo));
- auto notification = LocalRef<jobject> (env->CallObjectMethod (remoteNotification, RemoteMessage.getNotification));
- auto data = LocalRef<jobject> (env->CallObjectMethod (remoteNotification, RemoteMessage.getData));
-
- const int64 sentTime = env->CallLongMethod (remoteNotification, RemoteMessage.getSentTime);
- const int ttl = env->CallIntMethod (remoteNotification, RemoteMessage.getTtl);
-
- auto keySet = LocalRef<jobject> (env->CallObjectMethod (data, JavaMap.keySet));
- auto iterator = LocalRef<jobject> (env->CallObjectMethod (keySet, JavaSet.iterator));
-
- DynamicObject::Ptr dataDynamicObject = new DynamicObject();
-
- for (;;)
- {
- if (! env->CallBooleanMethod (iterator, JavaIterator.hasNext))
- break;
-
- auto key = LocalRef<jstring> ((jstring) env->CallObjectMethod (iterator, JavaIterator.next));
- auto value = LocalRef<jstring> ((jstring) env->CallObjectMethod (data, JavaMap.get, key.get()));
-
- dataDynamicObject->setProperty (juceString (key.get()), juceString (value.get()));
- }
-
- var dataVar (dataDynamicObject.get());
-
- DynamicObject::Ptr propertiesDynamicObject = new DynamicObject();
- propertiesDynamicObject->setProperty ("collapseKey", juceString (collapseKey.get()));
- propertiesDynamicObject->setProperty ("from", juceString (from.get()));
- propertiesDynamicObject->setProperty ("messageId", juceString (messageId.get()));
- propertiesDynamicObject->setProperty ("messageType", juceString (messageType.get()));
- propertiesDynamicObject->setProperty ("to", juceString (to.get()));
- propertiesDynamicObject->setProperty ("sentTime", sentTime);
- propertiesDynamicObject->setProperty ("ttl", ttl);
- propertiesDynamicObject->setProperty ("data", dataVar);
-
- PushNotifications::Notification n;
-
- if (notification != 0)
- {
- auto body = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getBody));
- auto bodyLocalizationKey = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getBodyLocalizationKey));
- auto clickAction = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getClickAction));
- auto color = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getColor));
- auto icon = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getIcon));
- auto sound = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getSound));
- auto tag = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getTag));
- auto title = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getTitle));
- auto titleLocalizationKey = LocalRef<jstring> ((jstring) env->CallObjectMethod (notification, RemoteMessageNotification.getTitleLocalizationKey));
- auto link = LocalRef<jobject> (env->CallObjectMethod (notification, RemoteMessageNotification.getLink));
-
- auto bodyLocalizationArgs = LocalRef<jobjectArray> ((jobjectArray) env->CallObjectMethod (notification, RemoteMessageNotification.getBodyLocalizationArgs));
- auto titleLocalizationArgs = LocalRef<jobjectArray> ((jobjectArray) env->CallObjectMethod (notification, RemoteMessageNotification.getTitleLocalizationArgs));
-
- n.identifier = juceString (tag.get());
- n.title = juceString (title.get());
- n.body = juceString (body.get());
- n.soundToPlay = URL (juceString (sound.get()));
-
- auto colourString = juceString (color.get()).substring (1);
- const uint8 r = (uint8) colourString.substring (0, 2).getIntValue();
- const uint8 g = (uint8) colourString.substring (2, 4).getIntValue();
- const uint8 b = (uint8) colourString.substring (4, 6).getIntValue();
- n.accentColour = Colour (r, g, b);
-
- // Note: Ignoring the icon, because Firebase passes it as a string.
-
- propertiesDynamicObject->setProperty ("clickAction", juceString (clickAction.get()));
- propertiesDynamicObject->setProperty ("bodyLocalizationKey", juceString (bodyLocalizationKey.get()));
- propertiesDynamicObject->setProperty ("titleLocalizationKey", juceString (titleLocalizationKey.get()));
- propertiesDynamicObject->setProperty ("bodyLocalizationArgs", javaStringArrayToJuce (bodyLocalizationArgs));
- propertiesDynamicObject->setProperty ("titleLocalizationArgs", javaStringArrayToJuce (titleLocalizationArgs));
- propertiesDynamicObject->setProperty ("link", link.get() != nullptr ? juceString ((jstring) env->CallObjectMethod (link, AndroidUri.toString)) : String());
- }
-
- n.properties = var (propertiesDynamicObject.get());
-
- return n;
- }
- #endif
-
- void setupChannels (const Array<ChannelGroup>& groups, const Array<Channel>& channels)
- {
- if (getAndroidSDKVersion() < 26)
- return;
-
- auto* env = getEnv();
-
- auto notificationManager = getNotificationManager();
-
- jassert (notificationManager.get() != nullptr);
-
- if (notificationManager.get() == nullptr)
- return;
-
- for (const auto& g : groups)
- {
- // Channel group identifier and name have to be set.
- jassert (g.identifier.isNotEmpty() && g.name.isNotEmpty());
-
- if (g.identifier.isNotEmpty() && g.name.isNotEmpty())
- {
- auto group = LocalRef<jobject> (env->NewObject (NotificationChannelGroup, NotificationChannelGroup.constructor,
- javaString (g.identifier).get(), javaString (g.name).get()));
- env->CallVoidMethod (notificationManager, NotificationManagerApi26.createNotificationChannelGroup, group.get());
- }
- }
-
- for (const auto& c : channels)
- {
- // Channel identifier, name and group have to be set.
- jassert (c.identifier.isNotEmpty() && c.name.isNotEmpty() && c.groupId.isNotEmpty());
-
- if (c.identifier.isEmpty() || c.name.isEmpty() || c.groupId.isEmpty())
- continue;
-
- auto channel = LocalRef<jobject> (env->NewObject (NotificationChannel, NotificationChannel.constructor,
- javaString (c.identifier).get(), javaString (c.name).get(), c.importance));
-
- env->CallVoidMethod (channel, NotificationChannel.enableLights, c.enableLights);
- env->CallVoidMethod (channel, NotificationChannel.enableVibration, c.enableVibration);
- env->CallVoidMethod (channel, NotificationChannel.setBypassDnd, c.bypassDoNotDisturb);
- env->CallVoidMethod (channel, NotificationChannel.setDescription, javaString (c.description).get());
- env->CallVoidMethod (channel, NotificationChannel.setGroup, javaString (c.groupId).get());
- env->CallVoidMethod (channel, NotificationChannel.setImportance, c.importance);
- env->CallVoidMethod (channel, NotificationChannel.setLightColor, c.ledColour.getARGB());
- env->CallVoidMethod (channel, NotificationChannel.setLockscreenVisibility, c.lockScreenAppearance);
- env->CallVoidMethod (channel, NotificationChannel.setShowBadge, c.canShowBadge);
-
-
- const int size = c.vibrationPattern.size();
-
- if (size > 0)
- {
- auto array = LocalRef<jlongArray> (env->NewLongArray (size));
- jlong* elements = env->GetLongArrayElements (array, nullptr);
-
- for (int i = 0; i < size; ++i)
- elements[i] = (jlong) c.vibrationPattern[i];
-
- env->SetLongArrayRegion (array, 0, size, elements);
- env->CallVoidMethod (channel, NotificationChannel.setVibrationPattern, array.get());
-
- env->CallVoidMethod (channel, NotificationChannel.enableVibration, c.enableVibration);
- }
-
- LocalRef<jobject> builder (env->NewObject (AndroidAudioAttributesBuilder, AndroidAudioAttributesBuilder.constructor));
- const int contentTypeSonification = 4;
- const int usageNotification = 5;
- env->CallObjectMethod (builder.get(), AndroidAudioAttributesBuilder.setContentType, contentTypeSonification);
- env->CallObjectMethod (builder.get(), AndroidAudioAttributesBuilder.setUsage, usageNotification);
- auto audioAttributes = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAudioAttributesBuilder.build));
- env->CallVoidMethod (channel, NotificationChannel.setSound, juceUrlToAndroidUri (c.soundToPlay).get(), audioAttributes.get());
-
- env->CallVoidMethod (notificationManager, NotificationManagerApi26.createNotificationChannel, channel.get());
- }
- }
-
- void getPendingLocalNotifications() const {}
- void removePendingLocalNotification (const String&) {}
- void removeAllPendingLocalNotifications() {}
-
- static bool intentActionContainsAnyOf (jobject intent, const StringArray& strings, bool includePackageName)
- {
- auto* env = getEnv();
- LocalRef<jobject> context (getMainActivity());
-
- String packageName = includePackageName ? juceString ((jstring) env->CallObjectMethod (context.get(),
- AndroidContext.getPackageName))
- : String{};
-
- String intentAction = juceString ((jstring) env->CallObjectMethod (intent, AndroidIntent.getAction));
-
- for (const auto& string : strings)
- if (intentAction.contains (packageName + string))
- return true;
-
- return false;
- }
-
- static bool isDeleteNotificationIntent (jobject intent)
- {
- return intentActionContainsAnyOf (intent, StringArray (".JUCE_NOTIFICATION_DELETED"), true);
- }
-
- static bool isLocalNotificationIntent (jobject intent)
- {
- return intentActionContainsAnyOf (intent, { ".JUCE_NOTIFICATION.",
- ".JUCE_NOTIFICATION_BUTTON_ACTION.",
- ".JUCE_NOTIFICATION_TEXT_INPUT_ACTION." },
- true);
- }
-
- static bool isRemoteNotificationIntent (jobject intent)
- {
- auto* env = getEnv();
-
- auto categories = LocalRef<jobject> (env->CallObjectMethod (intent, AndroidIntent.getCategories));
-
- int categoriesNum = categories != nullptr
- ? env->CallIntMethod (categories, JavaSet.size)
- : 0;
-
- if (categoriesNum == 0)
- return false;
-
- if (! env->CallBooleanMethod (categories, JavaSet.contains, javaString ("android.intent.category.LAUNCHER").get()))
- return false;
-
- if (! intentActionContainsAnyOf (intent, StringArray ("android.intent.action.MAIN"), false))
- return false;
-
- auto extras = LocalRef<jobject> (env->CallObjectMethod (intent, AndroidIntent.getExtras));
-
- if (extras == nullptr)
- return false;
-
- return env->CallBooleanMethod (extras, AndroidBundle.containsKey, javaString ("google.sent_time").get())
- && env->CallBooleanMethod (extras, AndroidBundle.containsKey, javaString ("google.message_id").get());
- }
-
- PushNotifications& owner;
- };
-
- #if defined(JUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME)
- //==============================================================================
- struct JuceFirebaseInstanceIdService
- {
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- CALLBACK (tokenRefreshed, "firebaseInstanceIdTokenRefreshed", "(Ljava/lang/String;)V")
-
- DECLARE_JNI_CLASS (InstanceIdService, "com/rmsl/juce/JuceFirebaseInstanceIdService")
- #undef JNI_CLASS_MEMBERS
-
- static void JNICALL tokenRefreshed (JNIEnv*, jobject /*instanceIdService*/, void* token)
- {
- if (auto* instance = PushNotifications::getInstanceWithoutCreating())
- instance->pimpl->notifyListenersTokenRefreshed (juceString (static_cast<jstring> (token)));
- }
- };
-
- JuceFirebaseInstanceIdService::InstanceIdService_Class JuceFirebaseInstanceIdService::InstanceIdService;
- #endif
-
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- //==============================================================================
- struct JuceFirebaseMessagingService
- {
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- CALLBACK (remoteNotificationReceived, "firebaseRemoteMessageReceived", "(Lcom/google/firebase/messaging/RemoteMessage;)V") \
- CALLBACK (remoteMessagesDeleted, "firebaseRemoteMessagesDeleted", "()V") \
- CALLBACK (remoteMessageSent, "firebaseRemoteMessageSent", "(Ljava/lang/String;)V") \
- CALLBACK (remoteMessageSendError, "firebaseRemoteMessageSendError", "(Ljava/lang/String;Ljava/lang/String;)V")
-
- DECLARE_JNI_CLASS (MessagingService, "com/rmsl/juce/JuceFirebaseMessagingService")
- #undef JNI_CLASS_MEMBERS
-
- static void JNICALL remoteNotificationReceived (JNIEnv*, jobject /*messagingService*/, void* remoteMessage)
- {
- if (auto* instance = PushNotifications::getInstanceWithoutCreating())
- instance->pimpl->notifyListenersAboutRemoteNotificationFromService (LocalRef<jobject> (static_cast<jobject> (remoteMessage)));
-
- }
-
- static void JNICALL remoteMessagesDeleted()
- {
- if (auto* instance = PushNotifications::getInstanceWithoutCreating())
- instance->pimpl->notifyListenersAboutRemoteNotificationsDeleted();
- }
-
- static void JNICALL remoteMessageSent (JNIEnv*, jobject /*messagingService*/, void* messageId)
- {
- if (auto* instance = PushNotifications::getInstanceWithoutCreating())
- instance->pimpl->notifyListenersAboutUpstreamMessageSent (LocalRef<jstring> (static_cast<jstring> (messageId)));
- }
-
- static void JNICALL remoteMessageSendError (JNIEnv*, jobject /*messagingService*/, void* messageId, void* error)
- {
- if (auto* instance = PushNotifications::getInstanceWithoutCreating())
- instance->pimpl->notifyListenersAboutUpstreamMessageSendingError (LocalRef<jstring> (static_cast<jstring> (messageId)),
- LocalRef<jstring> (static_cast<jstring> (error)));
- }
- };
-
- JuceFirebaseMessagingService::MessagingService_Class JuceFirebaseMessagingService::MessagingService;
- #endif
-
- //==============================================================================
- bool juce_handleNotificationIntent (void* intent)
- {
- auto* instance = PushNotifications::getInstanceWithoutCreating();
-
- if (PushNotifications::Pimpl::isDeleteNotificationIntent ((jobject) intent))
- {
- if (instance)
- instance->pimpl->notifyListenersAboutLocalNotificationDeleted (LocalRef<jobject> ((jobject) intent));
-
- return true;
- }
- else if (PushNotifications::Pimpl::isLocalNotificationIntent ((jobject) intent))
- {
- if (instance)
- instance->pimpl->notifyListenersAboutLocalNotification (LocalRef<jobject> ((jobject) intent));
-
- return true;
- }
- #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)
- else if (PushNotifications::Pimpl::isRemoteNotificationIntent ((jobject) intent))
- {
- if (instance)
- instance->pimpl->notifyListenersAboutRemoteNotificationFromSystemTray (LocalRef<jobject> ((jobject) intent));
-
- return true;
- }
- #endif
-
- return false;
- }
-
- //==============================================================================
- struct JuceActivityNewIntentListener
- {
- #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
- CALLBACK (appNewIntent, "appNewIntent", "(Landroid/content/Intent;)V")
-
- DECLARE_JNI_CLASS (JavaActivity, JUCE_PUSH_NOTIFICATIONS_ACTIVITY)
- #undef JNI_CLASS_MEMBERS
-
- static void JNICALL appNewIntent (JNIEnv*, jobject /*activity*/, jobject intentData)
- {
- #if JUCE_PUSH_NOTIFICATIONS && JUCE_MODULE_AVAILABLE_juce_gui_extra
- juce_handleNotificationIntent(static_cast<void*>(intentData));
- #else
- juce::ignoreUnused(intentData);
- #endif
- }
- };
-
- JuceActivityNewIntentListener::JavaActivity_Class JuceActivityNewIntentListener::JavaActivity;
-
- } // namespace juce
|