| @@ -1,39 +1,37 @@ | |||||
| { | { | ||||
| "project_info": { | "project_info": { | ||||
| "project_number": "3137221487", | |||||
| "firebase_url": "https://pushnotificationsdemo-1c714.firebaseio.com", | |||||
| "project_id": "pushnotificationsdemo-1c714", | |||||
| "storage_bucket": "pushnotificationsdemo-1c714.appspot.com" | |||||
| "project_number": "50526851168", | |||||
| "firebase_url": "https://pushnotificationsdemorunner.firebaseio.com", | |||||
| "project_id": "pushnotificationsdemorunner", | |||||
| "storage_bucket": "pushnotificationsdemorunner.appspot.com" | |||||
| }, | }, | ||||
| "client": [ | "client": [ | ||||
| { | { | ||||
| "client_info": { | "client_info": { | ||||
| "mobilesdk_app_id": "1:3137221487:android:8fdcd861a33b035c", | |||||
| "mobilesdk_app_id": "1:50526851168:android:6fa3f0d4b79f1940", | |||||
| "android_client_info": { | "android_client_info": { | ||||
| "package_name": "com.juce.pushnotificationsdemo" | |||||
| "package_name": "com.juce.demorunner" | |||||
| } | } | ||||
| }, | }, | ||||
| "oauth_client": [ | "oauth_client": [ | ||||
| { | { | ||||
| "client_id": "3137221487-uftk61ukltbi07dmejslgt0d6qnml0oo.apps.googleusercontent.com", | |||||
| "client_id": "50526851168-vgn4rv0vimpc8kdm7ecmb3g95t1et0t5.apps.googleusercontent.com", | |||||
| "client_type": 3 | "client_type": 3 | ||||
| } | } | ||||
| ], | ], | ||||
| "api_key": [ | "api_key": [ | ||||
| { | { | ||||
| "current_key": "AIzaSyDPpqphjiEEYI3sJGptrebN5Z52GkOG4Wo" | |||||
| "current_key": "AIzaSyAMwLOFACFo7_SHm9iiVhoa0zCjFyMsgFc" | |||||
| } | } | ||||
| ], | ], | ||||
| "services": { | "services": { | ||||
| "analytics_service": { | |||||
| "status": 1 | |||||
| }, | |||||
| "appinvite_service": { | "appinvite_service": { | ||||
| "status": 1, | |||||
| "other_platform_oauth_client": [] | |||||
| }, | |||||
| "ads_service": { | |||||
| "status": 2 | |||||
| "other_platform_oauth_client": [ | |||||
| { | |||||
| "client_id": "50526851168-vgn4rv0vimpc8kdm7ecmb3g95t1et0t5.apps.googleusercontent.com", | |||||
| "client_type": 3 | |||||
| } | |||||
| ] | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni") | |||||
| add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | ||||
| set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | ||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=5.4.3" "-DJUCE_APP_VERSION_HEX=0x50403") | |||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY=\"com/roli/juce/JuceActivity\"" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=5.4.3" "-DJUCE_APP_VERSION_HEX=0x50403") | |||||
| include_directories( AFTER | include_directories( AFTER | ||||
| "../../../JuceLibraryCode" | "../../../JuceLibraryCode" | ||||
| @@ -86,7 +86,8 @@ android { | |||||
| main.java.srcDirs += | main.java.srcDirs += | ||||
| ["../../../../../modules/juce_core/native/javacore/init", | ["../../../../../modules/juce_core/native/javacore/init", | ||||
| "../../../../../modules/juce_core/native/javacore/app", | "../../../../../modules/juce_core/native/javacore/app", | ||||
| "../../../../../modules/juce_gui_basics/native/javacore/app"] | |||||
| "../../../../../modules/juce_gui_basics/native/javacore/app", | |||||
| "../../../../../modules/juce_gui_basics/native/javaopt/app"] | |||||
| main.res.srcDirs += | main.res.srcDirs += | ||||
| [] | [] | ||||
| @@ -13,7 +13,7 @@ | |||||
| <uses-permission android:name="android.permission.INTERNET"/> | <uses-permission android:name="android.permission.INTERNET"/> | ||||
| <uses-feature android:glEsVersion="0x00030000" android:required="true"/> | <uses-feature android:glEsVersion="0x00030000" android:required="true"/> | ||||
| <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false"> | <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false"> | ||||
| <activity android:name="android.app.Activity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| <activity android:name="com.roli.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | ||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.MAIN"/> | <action android:name="android.intent.action.MAIN"/> | ||||
| @@ -1,39 +1,37 @@ | |||||
| { | { | ||||
| "project_info": { | "project_info": { | ||||
| "project_number": "3137221487", | |||||
| "firebase_url": "https://pushnotificationsdemo-1c714.firebaseio.com", | |||||
| "project_id": "pushnotificationsdemo-1c714", | |||||
| "storage_bucket": "pushnotificationsdemo-1c714.appspot.com" | |||||
| "project_number": "50526851168", | |||||
| "firebase_url": "https://pushnotificationsdemorunner.firebaseio.com", | |||||
| "project_id": "pushnotificationsdemorunner", | |||||
| "storage_bucket": "pushnotificationsdemorunner.appspot.com" | |||||
| }, | }, | ||||
| "client": [ | "client": [ | ||||
| { | { | ||||
| "client_info": { | "client_info": { | ||||
| "mobilesdk_app_id": "1:3137221487:android:8fdcd861a33b035c", | |||||
| "mobilesdk_app_id": "1:50526851168:android:6fa3f0d4b79f1940", | |||||
| "android_client_info": { | "android_client_info": { | ||||
| "package_name": "com.juce.pushnotificationsdemo" | |||||
| "package_name": "com.juce.demorunner" | |||||
| } | } | ||||
| }, | }, | ||||
| "oauth_client": [ | "oauth_client": [ | ||||
| { | { | ||||
| "client_id": "3137221487-uftk61ukltbi07dmejslgt0d6qnml0oo.apps.googleusercontent.com", | |||||
| "client_id": "50526851168-vgn4rv0vimpc8kdm7ecmb3g95t1et0t5.apps.googleusercontent.com", | |||||
| "client_type": 3 | "client_type": 3 | ||||
| } | } | ||||
| ], | ], | ||||
| "api_key": [ | "api_key": [ | ||||
| { | { | ||||
| "current_key": "AIzaSyDPpqphjiEEYI3sJGptrebN5Z52GkOG4Wo" | |||||
| "current_key": "AIzaSyAMwLOFACFo7_SHm9iiVhoa0zCjFyMsgFc" | |||||
| } | } | ||||
| ], | ], | ||||
| "services": { | "services": { | ||||
| "analytics_service": { | |||||
| "status": 1 | |||||
| }, | |||||
| "appinvite_service": { | "appinvite_service": { | ||||
| "status": 1, | |||||
| "other_platform_oauth_client": [] | |||||
| }, | |||||
| "ads_service": { | |||||
| "status": 2 | |||||
| "other_platform_oauth_client": [ | |||||
| { | |||||
| "client_id": "50526851168-vgn4rv0vimpc8kdm7ecmb3g95t1et0t5.apps.googleusercontent.com", | |||||
| "client_type": 3 | |||||
| } | |||||
| ] | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -51,6 +51,74 @@ | |||||
| #include "../Assets/DemoUtilities.h" | #include "../Assets/DemoUtilities.h" | ||||
| /* | |||||
| To finish the setup of this demo, do the following: | |||||
| 1. Download google_services.json from your Firebase project. | |||||
| 2. Update "Remote Notifications Config File" path in Android exporter (this can be different for debug and release) | |||||
| to point to that json file. | |||||
| 3. Add image and sound resources by adding the following to "Extra Android Raw Resources" in Projucer: | |||||
| ../../Assets/Notifications/images/ic_stat_name.png | |||||
| ../../Assets/Notifications/images/ic_stat_name2.png | |||||
| ../../Assets/Notifications/images/ic_stat_name3.png | |||||
| ../../Assets/Notifications/images/ic_stat_name4.png | |||||
| ../../Assets/Notifications/images/ic_stat_name5.png | |||||
| ../../Assets/Notifications/images/ic_stat_name6.png | |||||
| ../../Assets/Notifications/images/ic_stat_name7.png | |||||
| ../../Assets/Notifications/images/ic_stat_name8.png | |||||
| ../../Assets/Notifications/images/ic_stat_name9.png | |||||
| ../../Assets/Notifications/images/ic_stat_name10.png | |||||
| ../../Assets/Notifications/sounds/demonstrative.mp3 | |||||
| ../../Assets/Notifications/sounds/isntit.mp3 | |||||
| ../../Assets/Notifications/sounds/jinglebellssms.mp3 | |||||
| ../../Assets/Notifications/sounds/served.mp3 | |||||
| ../../Assets/Notifications/sounds/solemn.mp3 | |||||
| 4. Set "Remote Notifications" to enabled in Projucer Android exporter. | |||||
| To verify that remote notifications are configured properly, go to Remote tab in the demo and press "GetDeviceToken" | |||||
| button, a dialog with your token (also printed to console in debug build) should show up. | |||||
| The following steps are only necessary if you have a custom activity defined: | |||||
| 5. Ensure that its launchMode is set to "singleTop" or "singleTask" in Android manifest. This is the default behaviour | |||||
| in JUCE so you only need to do it if you have custom Android manifest content. You can do it from Projucer by | |||||
| ensuring that "Custom Manifest XML Content" contains: | |||||
| <manifest> | |||||
| <application> | |||||
| <activity android:launchMode="singleTask"> | |||||
| </activity> | |||||
| </application> | |||||
| </manifest> | |||||
| 6. Ensure that you override onNewIntent() function in the same way as it is done in JuceActivity.java: | |||||
| package com.roli.juce; | |||||
| import android.app.Activity; | |||||
| import android.content.Intent; | |||||
| //============================================================================== | |||||
| public class JuceActivity extends Activity | |||||
| { | |||||
| //============================================================================== | |||||
| private native void appNewIntent (Intent intent); | |||||
| @Override | |||||
| protected void onNewIntent (Intent intent) | |||||
| { | |||||
| super.onNewIntent(intent); | |||||
| setIntent(intent); | |||||
| appNewIntent (intent); | |||||
| } | |||||
| } | |||||
| */ | |||||
| //============================================================================== | //============================================================================== | ||||
| class PushNotificationsDemo : public Component, | class PushNotificationsDemo : public Component, | ||||
| private ChangeListener, | private ChangeListener, | ||||
| @@ -101,11 +169,11 @@ public: | |||||
| #endif | #endif | ||||
| sendButton.onClick = [this] { sendLocalNotification(); }; | sendButton.onClick = [this] { sendLocalNotification(); }; | ||||
| auxActionsView.getDeliveredNotificationsButton .onClick = [this] | |||||
| auxActionsView.getDeliveredNotificationsButton .onClick = [] | |||||
| { PushNotifications::getInstance()->getDeliveredNotifications(); }; | { PushNotifications::getInstance()->getDeliveredNotifications(); }; | ||||
| auxActionsView.removeDeliveredNotifWithIdButton.onClick = [this] | auxActionsView.removeDeliveredNotifWithIdButton.onClick = [this] | ||||
| { PushNotifications::getInstance()->removeDeliveredNotification (auxActionsView.deliveredNotifIdentifier.getText()); }; | { PushNotifications::getInstance()->removeDeliveredNotification (auxActionsView.deliveredNotifIdentifier.getText()); }; | ||||
| auxActionsView.removeAllDeliveredNotifsButton .onClick = [this] | |||||
| auxActionsView.removeAllDeliveredNotifsButton .onClick = [] | |||||
| { PushNotifications::getInstance()->removeAllDeliveredNotifications(); }; | { PushNotifications::getInstance()->removeAllDeliveredNotifications(); }; | ||||
| #if JUCE_IOS || JUCE_MAC | #if JUCE_IOS || JUCE_MAC | ||||
| auxActionsView.getPendingNotificationsButton .onClick = [this] | auxActionsView.getPendingNotificationsButton .onClick = [this] | ||||
| @@ -116,7 +184,7 @@ public: | |||||
| { PushNotifications::getInstance()->removeAllPendingLocalNotifications(); }; | { PushNotifications::getInstance()->removeAllPendingLocalNotifications(); }; | ||||
| #endif | #endif | ||||
| remoteView.getDeviceTokenButton.onClick = [this] | |||||
| remoteView.getDeviceTokenButton.onClick = [] | |||||
| { | { | ||||
| String token = PushNotifications::getInstance()->getDeviceToken(); | String token = PushNotifications::getInstance()->getDeviceToken(); | ||||
| @@ -129,7 +197,7 @@ public: | |||||
| }; | }; | ||||
| #if JUCE_ANDROID | #if JUCE_ANDROID | ||||
| remoteView.sendRemoteMessageButton.onClick = [this] | |||||
| remoteView.sendRemoteMessageButton.onClick = [] | |||||
| { | { | ||||
| StringPairArray data; | StringPairArray data; | ||||
| data.set ("key1", "value1"); | data.set ("key1", "value1"); | ||||
| @@ -144,9 +212,9 @@ public: | |||||
| data); | data); | ||||
| }; | }; | ||||
| remoteView.subscribeToSportsButton .onClick = [this] | |||||
| remoteView.subscribeToSportsButton .onClick = [] | |||||
| { PushNotifications::getInstance()->subscribeToTopic ("sports"); }; | { PushNotifications::getInstance()->subscribeToTopic ("sports"); }; | ||||
| remoteView.unsubscribeFromSportsButton.onClick = [this] | |||||
| remoteView.unsubscribeFromSportsButton.onClick = [] | |||||
| { PushNotifications::getInstance()->unsubscribeFromTopic ("sports"); }; | { PushNotifications::getInstance()->unsubscribeFromTopic ("sports"); }; | ||||
| #endif | #endif | ||||
| @@ -164,11 +232,31 @@ public: | |||||
| PushNotifications::ChannelGroup cg { "demoGroup", "demo group" }; | PushNotifications::ChannelGroup cg { "demoGroup", "demo group" }; | ||||
| PushNotifications::getInstance()->setupChannels ({ { cg } }, getAndroidChannels()); | PushNotifications::getInstance()->setupChannels ({ { cg } }, getAndroidChannels()); | ||||
| #endif | #endif | ||||
| #if JUCE_IOS || JUCE_ANDROID | |||||
| setPortraitOrientationEnabled (true); | |||||
| #endif | |||||
| } | } | ||||
| ~PushNotificationsDemo() | ~PushNotificationsDemo() | ||||
| { | { | ||||
| PushNotifications::getInstance()->removeListener (this); | PushNotifications::getInstance()->removeListener (this); | ||||
| #if JUCE_IOS || JUCE_ANDROID | |||||
| setPortraitOrientationEnabled (false); | |||||
| #endif | |||||
| } | |||||
| void setPortraitOrientationEnabled (bool shouldBeEnabled) | |||||
| { | |||||
| auto allowedOrientations = Desktop::getInstance().getOrientationsEnabled(); | |||||
| if (shouldBeEnabled) | |||||
| allowedOrientations |= Desktop::upright; | |||||
| else | |||||
| allowedOrientations &= ~Desktop::upright; | |||||
| Desktop::getInstance().setOrientationsEnabled (allowedOrientations); | |||||
| } | } | ||||
| void paint (Graphics& g) override | void paint (Graphics& g) override | ||||
| @@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni") | |||||
| add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | ||||
| set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | ||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000") | |||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY=\"com/roli/juce/JuceActivity\"" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000") | |||||
| include_directories( AFTER | include_directories( AFTER | ||||
| "../../../JuceLibraryCode" | "../../../JuceLibraryCode" | ||||
| @@ -89,7 +89,8 @@ android { | |||||
| main.java.srcDirs += | main.java.srcDirs += | ||||
| ["../../../../../modules/juce_core/native/javacore/init", | ["../../../../../modules/juce_core/native/javacore/init", | ||||
| "../../../../../modules/juce_core/native/javacore/app", | "../../../../../modules/juce_core/native/javacore/app", | ||||
| "../../../../../modules/juce_gui_basics/native/javacore/app"] | |||||
| "../../../../../modules/juce_gui_basics/native/javacore/app", | |||||
| "../../../../../modules/juce_gui_basics/native/javaopt/app"] | |||||
| main.res.srcDirs += | main.res.srcDirs += | ||||
| [] | [] | ||||
| @@ -10,7 +10,7 @@ | |||||
| <uses-permission android:name="android.permission.BLUETOOTH"/> | <uses-permission android:name="android.permission.BLUETOOTH"/> | ||||
| <uses-permission android:name="android.permission.INTERNET"/> | <uses-permission android:name="android.permission.INTERNET"/> | ||||
| <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:hardwareAccelerated="false"> | <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:hardwareAccelerated="false"> | ||||
| <activity android:name="android.app.Activity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| <activity android:name="com.roli.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | ||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.MAIN"/> | <action android:name="android.intent.action.MAIN"/> | ||||
| @@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni") | |||||
| add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | ||||
| set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | ||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000") | |||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY=\"com/roli/juce/JuceActivity\"" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000") | |||||
| include_directories( AFTER | include_directories( AFTER | ||||
| "../../../../../modules/juce_audio_processors/format_types/VST3_SDK" | "../../../../../modules/juce_audio_processors/format_types/VST3_SDK" | ||||
| @@ -86,7 +86,8 @@ android { | |||||
| main.java.srcDirs += | main.java.srcDirs += | ||||
| ["../../../../../modules/juce_core/native/javacore/init", | ["../../../../../modules/juce_core/native/javacore/init", | ||||
| "../../../../../modules/juce_core/native/javacore/app", | "../../../../../modules/juce_core/native/javacore/app", | ||||
| "../../../../../modules/juce_gui_basics/native/javacore/app"] | |||||
| "../../../../../modules/juce_gui_basics/native/javacore/app", | |||||
| "../../../../../modules/juce_gui_basics/native/javaopt/app"] | |||||
| main.res.srcDirs += | main.res.srcDirs += | ||||
| [] | [] | ||||
| @@ -12,7 +12,7 @@ | |||||
| <uses-permission android:name="android.permission.INTERNET"/> | <uses-permission android:name="android.permission.INTERNET"/> | ||||
| <uses-feature android:glEsVersion="0x00030000" android:required="true"/> | <uses-feature android:glEsVersion="0x00030000" android:required="true"/> | ||||
| <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false"> | <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false"> | ||||
| <activity android:name="android.app.Activity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| <activity android:name="com.roli.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | ||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.MAIN"/> | <action android:name="android.intent.action.MAIN"/> | ||||
| @@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni") | |||||
| add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") | ||||
| set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression") | ||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=16" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000") | |||||
| add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=16" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY=\"com/roli/juce/JuceActivity\"" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000") | |||||
| include_directories( AFTER | include_directories( AFTER | ||||
| "../../../JuceLibraryCode" | "../../../JuceLibraryCode" | ||||
| @@ -86,7 +86,8 @@ android { | |||||
| main.java.srcDirs += | main.java.srcDirs += | ||||
| ["../../../../../modules/juce_core/native/javacore/init", | ["../../../../../modules/juce_core/native/javacore/init", | ||||
| "../../../../../modules/juce_core/native/javacore/app", | "../../../../../modules/juce_core/native/javacore/app", | ||||
| "../../../../../modules/juce_gui_basics/native/javacore/app"] | |||||
| "../../../../../modules/juce_gui_basics/native/javacore/app", | |||||
| "../../../../../modules/juce_gui_basics/native/javaopt/app"] | |||||
| main.res.srcDirs += | main.res.srcDirs += | ||||
| [] | [] | ||||
| @@ -11,7 +11,7 @@ | |||||
| <uses-permission android:name="android.permission.INTERNET"/> | <uses-permission android:name="android.permission.INTERNET"/> | ||||
| <uses-feature android:glEsVersion="0x00020000" android:required="true"/> | <uses-feature android:glEsVersion="0x00020000" android:required="true"/> | ||||
| <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false"> | <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false"> | ||||
| <activity android:name="android.app.Activity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| <activity android:name="com.roli.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize" | |||||
| android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"> | ||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.MAIN"/> | <action android:name="android.intent.action.MAIN"/> | ||||
| @@ -84,6 +84,8 @@ public: | |||||
| static const char* getName() { return "Android"; } | static const char* getName() { return "Android"; } | ||||
| static const char* getValueTreeTypeName() { return "ANDROIDSTUDIO"; } | static const char* getValueTreeTypeName() { return "ANDROIDSTUDIO"; } | ||||
| static const char* getDefaultActivityClass() { return "com.roli.juce.JuceActivity"; } | |||||
| static const char* getDefaultApplicationClass() { return "com.roli.juce.JuceApp"; } | |||||
| static AndroidProjectExporter* createForSettings (Project& project, const ValueTree& settings) | static AndroidProjectExporter* createForSettings (Project& project, const ValueTree& settings) | ||||
| { | { | ||||
| @@ -98,7 +100,7 @@ public: | |||||
| androidCustomActivityClass, androidCustomApplicationClass, androidManifestCustomXmlElements, androidVersionCode, | androidCustomActivityClass, androidCustomApplicationClass, androidManifestCustomXmlElements, androidVersionCode, | ||||
| androidMinimumSDK, androidTargetSDK, androidTheme, androidSharedLibraries, androidStaticLibraries, androidExtraAssetsFolder, | androidMinimumSDK, androidTargetSDK, androidTheme, androidSharedLibraries, androidStaticLibraries, androidExtraAssetsFolder, | ||||
| androidOboeRepositoryPath, androidInternetNeeded, androidMicNeeded, androidCameraNeeded, androidBluetoothNeeded, androidExternalReadPermission, | androidOboeRepositoryPath, androidInternetNeeded, androidMicNeeded, androidCameraNeeded, androidBluetoothNeeded, androidExternalReadPermission, | ||||
| androidExternalWritePermission, androidInAppBillingPermission, androidVibratePermission,androidOtherPermissions, | |||||
| androidExternalWritePermission, androidInAppBillingPermission, androidVibratePermission, androidOtherPermissions, | |||||
| androidEnableRemoteNotifications, androidRemoteNotificationsConfigFile, androidEnableContentSharing, androidKeyStore, | androidEnableRemoteNotifications, androidRemoteNotificationsConfigFile, androidEnableContentSharing, androidKeyStore, | ||||
| androidKeyStorePass, androidKeyAlias, androidKeyAliasPass, gradleVersion, gradleToolchain, androidPluginVersion; | androidKeyStorePass, androidKeyAlias, androidKeyAliasPass, gradleVersion, gradleToolchain, androidPluginVersion; | ||||
| @@ -111,8 +113,8 @@ public: | |||||
| androidRepositories (settings, Ids::androidRepositories, getUndoManager()), | androidRepositories (settings, Ids::androidRepositories, getUndoManager()), | ||||
| androidDependencies (settings, Ids::androidDependencies, getUndoManager()), | androidDependencies (settings, Ids::androidDependencies, getUndoManager()), | ||||
| androidScreenOrientation (settings, Ids::androidScreenOrientation, getUndoManager(), "unspecified"), | androidScreenOrientation (settings, Ids::androidScreenOrientation, getUndoManager(), "unspecified"), | ||||
| androidCustomActivityClass (settings, Ids::androidCustomActivityClass, getUndoManager()), | |||||
| androidCustomApplicationClass (settings, Ids::androidCustomApplicationClass, getUndoManager(), "com.roli.juce.JuceApp"), | |||||
| androidCustomActivityClass (settings, Ids::androidCustomActivityClass, getUndoManager(), getDefaultActivityClass()), | |||||
| androidCustomApplicationClass (settings, Ids::androidCustomApplicationClass, getUndoManager(), getDefaultApplicationClass()), | |||||
| androidManifestCustomXmlElements (settings, Ids::androidManifestCustomXmlElements, getUndoManager()), | androidManifestCustomXmlElements (settings, Ids::androidManifestCustomXmlElements, getUndoManager()), | ||||
| androidVersionCode (settings, Ids::androidVersionCode, getUndoManager(), "1"), | androidVersionCode (settings, Ids::androidVersionCode, getUndoManager(), "1"), | ||||
| androidMinimumSDK (settings, Ids::androidMinimumSDK, getUndoManager(), "16"), | androidMinimumSDK (settings, Ids::androidMinimumSDK, getUndoManager(), "16"), | ||||
| @@ -570,7 +572,7 @@ private: | |||||
| mo << " classpath 'com.android.tools.build:gradle:" << androidPluginVersion.get().toString() << "'" << newLine; | mo << " classpath 'com.android.tools.build:gradle:" << androidPluginVersion.get().toString() << "'" << newLine; | ||||
| if (androidEnableRemoteNotifications.get()) | if (androidEnableRemoteNotifications.get()) | ||||
| mo << " classpath 'com.google.gms:google-services:3.1.0'" << newLine; | |||||
| mo << " classpath 'com.google.gms:google-services:4.0.1'" << newLine; | |||||
| mo << " }" << newLine; | mo << " }" << newLine; | ||||
| mo << "}" << newLine; | mo << "}" << newLine; | ||||
| @@ -814,8 +816,8 @@ private: | |||||
| if (androidEnableRemoteNotifications.get()) | if (androidEnableRemoteNotifications.get()) | ||||
| { | { | ||||
| mo << " 'com.google.firebase:firebase-core:11.4.0'" << newLine; | |||||
| mo << " compile 'com.google.firebase:firebase-messaging:11.4.0'" << newLine; | |||||
| mo << " implementation 'com.google.firebase:firebase-core:16.0.1'" << newLine; | |||||
| mo << " implementation 'com.google.firebase:firebase-messaging:17.6.0'" << newLine; | |||||
| } | } | ||||
| mo << " }" << newLine; | mo << " }" << newLine; | ||||
| @@ -834,17 +836,32 @@ private: | |||||
| return mo.toString(); | return mo.toString(); | ||||
| } | } | ||||
| void addModuleJavaFolderToSourceSet(StringArray& javaSourceSets, const File& javacore) const | |||||
| void addModuleJavaFolderToSourceSet(StringArray& javaSourceSets, const File& source) const | |||||
| { | { | ||||
| if (javacore.isDirectory()) | |||||
| if (source.isDirectory()) | |||||
| { | { | ||||
| auto appFolder = getTargetFolder().getChildFile ("app"); | auto appFolder = getTargetFolder().getChildFile ("app"); | ||||
| RelativePath relativePath (javacore, appFolder, RelativePath::buildTargetFolder); | |||||
| RelativePath relativePath (source, appFolder, RelativePath::buildTargetFolder); | |||||
| javaSourceSets.add (relativePath.toUnixStyle()); | javaSourceSets.add (relativePath.toUnixStyle()); | ||||
| } | } | ||||
| } | } | ||||
| void addOptJavaFolderToSourceSetsForModule (StringArray& javaSourceSets, | |||||
| const OwnedArray<LibraryModule>& modules, | |||||
| const String& moduleID) const | |||||
| { | |||||
| for (auto& m : modules) | |||||
| { | |||||
| if (m->getID() == moduleID) | |||||
| { | |||||
| auto javaFolder = m->getFolder().getChildFile ("native").getChildFile ("javaopt"); | |||||
| addModuleJavaFolderToSourceSet (javaSourceSets, javaFolder.getChildFile("app")); | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| String getAndroidJavaSourceSets (const OwnedArray<LibraryModule>& modules) const | String getAndroidJavaSourceSets (const OwnedArray<LibraryModule>& modules) const | ||||
| { | { | ||||
| auto javaSourceSets = getSourceSetArrayFor (androidAdditionalJavaFolders.get().toString()); | auto javaSourceSets = getSourceSetArrayFor (androidAdditionalJavaFolders.get().toString()); | ||||
| @@ -860,6 +877,12 @@ private: | |||||
| addModuleJavaFolderToSourceSet (javaSourceSets, javaFolder.getChildFile("app")); | addModuleJavaFolderToSourceSet (javaSourceSets, javaFolder.getChildFile("app")); | ||||
| } | } | ||||
| if (androidCustomActivityClass.get() == getDefaultActivityClass()) | |||||
| addOptJavaFolderToSourceSetsForModule (javaSourceSets, modules, "juce_gui_basics"); | |||||
| if (androidEnableRemoteNotifications.get()) | |||||
| addOptJavaFolderToSourceSetsForModule (javaSourceSets, modules, "juce_gui_extra"); | |||||
| MemoryOutputStream mo; | MemoryOutputStream mo; | ||||
| mo.setNewLineString ("\n"); | mo.setNewLineString ("\n"); | ||||
| @@ -974,7 +997,9 @@ private: | |||||
| props.add (new TextPropertyComponent (androidCustomActivityClass, "Custom Android Activity", 256, false), | props.add (new TextPropertyComponent (androidCustomActivityClass, "Custom Android Activity", 256, false), | ||||
| "If not empty, specifies the Android Activity class name stored in the app's manifest which " | "If not empty, specifies the Android Activity class name stored in the app's manifest which " | ||||
| "should be used instead of Android's default Activity."); | |||||
| "should be used instead of default com.roli.juce.JuceActivity. If you specify a custom Activity " | |||||
| "then you should implement onNewIntent() function like the one in com.roli.juce.JuceActivity, if " | |||||
| "you wish to be able to handle push notification events."); | |||||
| props.add (new TextPropertyComponent (androidCustomApplicationClass, "Custom Android Application", 256, false), | props.add (new TextPropertyComponent (androidCustomApplicationClass, "Custom Android Application", 256, false), | ||||
| "If not empty, specifies the Android Application class name stored in the app's manifest which " | "If not empty, specifies the Android Application class name stored in the app's manifest which " | ||||
| @@ -1135,19 +1160,8 @@ private: | |||||
| } | } | ||||
| } | } | ||||
| String getActivityClass() const | |||||
| { | |||||
| auto customActivityClass = androidCustomActivityClass.get().toString(); | |||||
| return (customActivityClass.isEmpty()) ? "android.app.Activity" : customActivityClass; | |||||
| } | |||||
| String getApplicationClass() const | |||||
| { | |||||
| auto customApplicationClass = androidCustomApplicationClass.get().toString(); | |||||
| return (customApplicationClass.isEmpty()) ? "com.roli.juce.JuceApp" : customApplicationClass; | |||||
| } | |||||
| String getActivityClass() const { return androidCustomActivityClass.get(); } | |||||
| String getApplicationClass() const { return androidCustomApplicationClass.get(); } | |||||
| String getJNIActivityClassName() const | String getJNIActivityClassName() const | ||||
| { | { | ||||
| @@ -1374,6 +1388,7 @@ private: | |||||
| defines.set ("JUCE_ANDROID", "1"); | defines.set ("JUCE_ANDROID", "1"); | ||||
| defines.set ("JUCE_ANDROID_API_VERSION", androidMinimumSDK.get()); | defines.set ("JUCE_ANDROID_API_VERSION", androidMinimumSDK.get()); | ||||
| defines.set ("JUCE_PUSH_NOTIFICATIONS", "1"); | defines.set ("JUCE_PUSH_NOTIFICATIONS", "1"); | ||||
| defines.set ("JUCE_PUSH_NOTIFICATIONS_ACTIVITY", String::formatted("\"%s\"", getJNIActivityClassName().toUTF8())); | |||||
| if (androidInAppBillingPermission.get()) | if (androidInAppBillingPermission.get()) | ||||
| defines.set ("JUCE_IN_APP_PURCHASES", "1"); | defines.set ("JUCE_IN_APP_PURCHASES", "1"); | ||||
| @@ -1381,6 +1396,12 @@ private: | |||||
| if (supportsGLv3()) | if (supportsGLv3()) | ||||
| defines.set ("JUCE_ANDROID_GL_ES_VERSION_3_0", "1"); | defines.set ("JUCE_ANDROID_GL_ES_VERSION_3_0", "1"); | ||||
| if (androidEnableRemoteNotifications.get()) | |||||
| { | |||||
| defines.set ("JUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME", "com_roli_juce_JuceFirebaseInstanceIdService"); | |||||
| defines.set ("JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME", "com_roli_juce_JuceFirebaseMessagingService"); | |||||
| } | |||||
| return defines; | return defines; | ||||
| } | } | ||||
| @@ -1683,12 +1704,12 @@ private: | |||||
| if (androidEnableRemoteNotifications.get()) | if (androidEnableRemoteNotifications.get()) | ||||
| { | { | ||||
| auto* service = application.createNewChildElement ("service"); | auto* service = application.createNewChildElement ("service"); | ||||
| service->setAttribute ("android:name", ".JuceFirebaseMessagingService"); | |||||
| service->setAttribute ("android:name", "com.roli.juce.JuceFirebaseMessagingService"); | |||||
| auto* intentFilter = service->createNewChildElement ("intent-filter"); | auto* intentFilter = service->createNewChildElement ("intent-filter"); | ||||
| intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.MESSAGING_EVENT"); | intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.MESSAGING_EVENT"); | ||||
| service = application.createNewChildElement ("service"); | service = application.createNewChildElement ("service"); | ||||
| service->setAttribute ("android:name", ".JuceFirebaseInstanceIdService"); | |||||
| service->setAttribute ("android:name", "com.roli.juce.JuceFirebaseInstanceIdService"); | |||||
| intentFilter = service->createNewChildElement ("intent-filter"); | intentFilter = service->createNewChildElement ("intent-filter"); | ||||
| intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.INSTANCE_ID_EVENT"); | intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.INSTANCE_ID_EVENT"); | ||||
| @@ -0,0 +1,20 @@ | |||||
| package com.roli.juce; | |||||
| import android.app.Activity; | |||||
| import android.content.Intent; | |||||
| //============================================================================== | |||||
| public class JuceActivity extends Activity | |||||
| { | |||||
| //============================================================================== | |||||
| private native void appNewIntent (Intent intent); | |||||
| @Override | |||||
| protected void onNewIntent (Intent intent) | |||||
| { | |||||
| super.onNewIntent(intent); | |||||
| setIntent(intent); | |||||
| appNewIntent (intent); | |||||
| } | |||||
| } | |||||
| @@ -700,11 +700,9 @@ private: | |||||
| #if JUCE_ANDROID | #if JUCE_ANDROID | ||||
| friend bool juce_handleNotificationIntent (void*); | friend bool juce_handleNotificationIntent (void*); | ||||
| friend void juce_firebaseDeviceNotificationsTokenRefreshed (void*); | |||||
| friend void juce_firebaseRemoteNotificationReceived (void*); | |||||
| friend void juce_firebaseRemoteMessagesDeleted(); | |||||
| friend void juce_firebaseRemoteMessageSent (void*); | |||||
| friend void juce_firebaseRemoteMessageSendError (void*, void*); | |||||
| friend struct JuceFirebaseInstanceIdService; | |||||
| friend struct JuceFirebaseMessagingService; | |||||
| #endif | #endif | ||||
| #if JUCE_PUSH_NOTIFICATIONS | #if JUCE_PUSH_NOTIFICATIONS | ||||
| @@ -0,0 +1,16 @@ | |||||
| package com.roli.juce; | |||||
| import com.google.firebase.iid.*; | |||||
| public final class JuceFirebaseInstanceIdService extends FirebaseInstanceIdService | |||||
| { | |||||
| private native void firebaseInstanceIdTokenRefreshed (String token); | |||||
| @Override | |||||
| public void onTokenRefresh() | |||||
| { | |||||
| String token = FirebaseInstanceId.getInstance().getToken(); | |||||
| firebaseInstanceIdTokenRefreshed (token); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| package com.roli.juce; | |||||
| import com.google.firebase.messaging.*; | |||||
| public final class JuceFirebaseMessagingService extends FirebaseMessagingService | |||||
| { | |||||
| private native void firebaseRemoteMessageReceived (RemoteMessage message); | |||||
| private native void firebaseRemoteMessagesDeleted(); | |||||
| private native void firebaseRemoteMessageSent (String messageId); | |||||
| private native void firebaseRemoteMessageSendError (String messageId, String error); | |||||
| @Override | |||||
| public void onMessageReceived (RemoteMessage message) | |||||
| { | |||||
| firebaseRemoteMessageReceived (message); | |||||
| } | |||||
| @Override | |||||
| public void onDeletedMessages() | |||||
| { | |||||
| firebaseRemoteMessagesDeleted(); | |||||
| } | |||||
| @Override | |||||
| public void onMessageSent (String messageId) | |||||
| { | |||||
| firebaseRemoteMessageSent (messageId); | |||||
| } | |||||
| @Override | |||||
| public void onSendError (String messageId, Exception e) | |||||
| { | |||||
| firebaseRemoteMessageSendError (messageId, e.toString()); | |||||
| } | |||||
| } | |||||
| @@ -203,8 +203,8 @@ DECLARE_JNI_CLASS_WITH_MIN_SDK (RemoteInputBuilder, "android/app/RemoteInput$Bui | |||||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ | #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ | ||||
| STATICMETHOD (getInstance, "getInstance", "()Lcom/google/firebase/messaging/FirebaseMessaging;") \ | STATICMETHOD (getInstance, "getInstance", "()Lcom/google/firebase/messaging/FirebaseMessaging;") \ | ||||
| METHOD (send, "send", "(Lcom/google/firebase/messaging/RemoteMessage;)V") \ | METHOD (send, "send", "(Lcom/google/firebase/messaging/RemoteMessage;)V") \ | ||||
| METHOD (subscribeToTopic, "subscribeToTopic", "(Ljava/lang/String;)V") \ | |||||
| METHOD (unsubscribeFromTopic, "unsubscribeFromTopic", "(Ljava/lang/String;)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") | DECLARE_JNI_CLASS (FirebaseMessaging, "com/google/firebase/messaging/FirebaseMessaging") | ||||
| #undef JNI_CLASS_MEMBERS | #undef JNI_CLASS_MEMBERS | ||||
| @@ -349,7 +349,7 @@ struct PushNotifications::Pimpl | |||||
| void notifyListenersAboutLocalNotification (const LocalRef<jobject>& intent) | void notifyListenersAboutLocalNotification (const LocalRef<jobject>& intent) | ||||
| { | { | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| auto bundle = LocalRef<jobject> (env->CallObjectMethod (intent, AndroidIntent.getExtras)); | auto bundle = LocalRef<jobject> (env->CallObjectMethod (intent, AndroidIntent.getExtras)); | ||||
| @@ -461,6 +461,7 @@ struct PushNotifications::Pimpl | |||||
| #endif | #endif | ||||
| } | } | ||||
| //========================================================================== | |||||
| void subscribeToTopic (const String& topic) | void subscribeToTopic (const String& topic) | ||||
| { | { | ||||
| #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | ||||
| @@ -469,7 +470,7 @@ struct PushNotifications::Pimpl | |||||
| auto firebaseMessaging = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseMessaging, | auto firebaseMessaging = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseMessaging, | ||||
| FirebaseMessaging.getInstance)); | FirebaseMessaging.getInstance)); | ||||
| env->CallVoidMethod (firebaseMessaging, FirebaseMessaging.subscribeToTopic, javaString (topic).get()); | |||||
| env->CallObjectMethod (firebaseMessaging, FirebaseMessaging.subscribeToTopic, javaString (topic).get()); | |||||
| #else | #else | ||||
| ignoreUnused (topic); | ignoreUnused (topic); | ||||
| #endif | #endif | ||||
| @@ -483,7 +484,7 @@ struct PushNotifications::Pimpl | |||||
| auto firebaseMessaging = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseMessaging, | auto firebaseMessaging = LocalRef<jobject> (env->CallStaticObjectMethod (FirebaseMessaging, | ||||
| FirebaseMessaging.getInstance)); | FirebaseMessaging.getInstance)); | ||||
| env->CallVoidMethod (firebaseMessaging, FirebaseMessaging.unsubscribeFromTopic, javaString (topic).get()); | |||||
| env->CallObjectMethod (firebaseMessaging, FirebaseMessaging.unsubscribeFromTopic, javaString (topic).get()); | |||||
| #else | #else | ||||
| ignoreUnused (topic); | ignoreUnused (topic); | ||||
| #endif | #endif | ||||
| @@ -545,7 +546,7 @@ struct PushNotifications::Pimpl | |||||
| void notifyListenersAboutRemoteNotificationFromService (const LocalRef<jobject>& remoteNotification) | void notifyListenersAboutRemoteNotificationFromService (const LocalRef<jobject>& remoteNotification) | ||||
| { | { | ||||
| #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | ||||
| GlobalRef rn (remoteNotification.get()); | |||||
| GlobalRef rn (remoteNotification); | |||||
| MessageManager::callAsync ([this, rn] | MessageManager::callAsync ([this, rn] | ||||
| { | { | ||||
| @@ -570,7 +571,7 @@ struct PushNotifications::Pimpl | |||||
| void notifyListenersAboutUpstreamMessageSent (const LocalRef<jstring>& messageId) | void notifyListenersAboutUpstreamMessageSent (const LocalRef<jstring>& messageId) | ||||
| { | { | ||||
| #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | ||||
| GlobalRef mid (messageId); | |||||
| GlobalRef mid (LocalRef<jobject>(messageId.get())); | |||||
| MessageManager::callAsync ([this, mid] | MessageManager::callAsync ([this, mid] | ||||
| { | { | ||||
| @@ -586,7 +587,7 @@ struct PushNotifications::Pimpl | |||||
| const LocalRef<jstring>& error) | const LocalRef<jstring>& error) | ||||
| { | { | ||||
| #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) | ||||
| GlobalRef mid (messageId), e (error); | |||||
| GlobalRef mid (LocalRef<jobject>(messageId.get())), e (LocalRef<jobject>(error.get())); | |||||
| MessageManager::callAsync ([this, mid, e] | MessageManager::callAsync ([this, mid, e] | ||||
| { | { | ||||
| @@ -603,7 +604,7 @@ struct PushNotifications::Pimpl | |||||
| static LocalRef<jobject> getNotificationManager() | static LocalRef<jobject> getNotificationManager() | ||||
| { | { | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| return LocalRef<jobject> (env->CallObjectMethod (context.get(), | return LocalRef<jobject> (env->CallObjectMethod (context.get(), | ||||
| AndroidContext.getSystemService, | AndroidContext.getSystemService, | ||||
| @@ -631,7 +632,7 @@ struct PushNotifications::Pimpl | |||||
| static LocalRef<jobject> createNotificationBuilder (const PushNotifications::Notification& n) | static LocalRef<jobject> createNotificationBuilder (const PushNotifications::Notification& n) | ||||
| { | { | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| jclass builderClass = env->FindClass ("android/app/Notification$Builder"); | jclass builderClass = env->FindClass ("android/app/Notification$Builder"); | ||||
| jassert (builderClass != 0); | jassert (builderClass != 0); | ||||
| @@ -663,7 +664,7 @@ struct PushNotifications::Pimpl | |||||
| static void setupRequiredFields (const PushNotifications::Notification& n, LocalRef<jobject>& notificationBuilder) | static void setupRequiredFields (const PushNotifications::Notification& n, LocalRef<jobject>& notificationBuilder) | ||||
| { | { | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| 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())); | ||||
| @@ -902,7 +903,7 @@ struct PushNotifications::Pimpl | |||||
| LocalRef<jobject>& notificationBuilder) | LocalRef<jobject>& notificationBuilder) | ||||
| { | { | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| auto activityClass = LocalRef<jobject> (env->CallObjectMethod (context.get(), JavaObject.getClass)); | auto activityClass = LocalRef<jobject> (env->CallObjectMethod (context.get(), JavaObject.getClass)); | ||||
| auto deleteIntent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructorWithContextAndClass, context.get(), activityClass.get())); | auto deleteIntent = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructorWithContextAndClass, context.get(), activityClass.get())); | ||||
| @@ -930,7 +931,7 @@ struct PushNotifications::Pimpl | |||||
| return; | return; | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| int actionIndex = 0; | int actionIndex = 0; | ||||
| @@ -1025,7 +1026,7 @@ struct PushNotifications::Pimpl | |||||
| static LocalRef<jobject> juceUrlToAndroidUri (const URL& url) | static LocalRef<jobject> juceUrlToAndroidUri (const URL& url) | ||||
| { | { | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| auto packageNameString = LocalRef<jstring> ((jstring) (env->CallObjectMethod (context.get(), AndroidContext.getPackageName))); | auto packageNameString = LocalRef<jstring> ((jstring) (env->CallObjectMethod (context.get(), AndroidContext.getPackageName))); | ||||
| @@ -1351,7 +1352,7 @@ struct PushNotifications::Pimpl | |||||
| dataDynamicObject->setProperty (juceString (key.get()), juceString (value.get())); | dataDynamicObject->setProperty (juceString (key.get()), juceString (value.get())); | ||||
| } | } | ||||
| var dataVar (dataDynamicObject); | |||||
| var dataVar (dataDynamicObject.get()); | |||||
| DynamicObject::Ptr propertiesDynamicObject = new DynamicObject(); | DynamicObject::Ptr propertiesDynamicObject = new DynamicObject(); | ||||
| propertiesDynamicObject->setProperty ("collapseKey", juceString (collapseKey.get())); | propertiesDynamicObject->setProperty ("collapseKey", juceString (collapseKey.get())); | ||||
| @@ -1402,7 +1403,7 @@ struct PushNotifications::Pimpl | |||||
| propertiesDynamicObject->setProperty ("link", link.get() != 0 ? juceString ((jstring) env->CallObjectMethod (link, AndroidUri.toString)) : String()); | propertiesDynamicObject->setProperty ("link", link.get() != 0 ? juceString ((jstring) env->CallObjectMethod (link, AndroidUri.toString)) : String()); | ||||
| } | } | ||||
| n.properties = var (propertiesDynamicObject); | |||||
| n.properties = var (propertiesDynamicObject.get()); | |||||
| return n; | return n; | ||||
| } | } | ||||
| @@ -1492,7 +1493,7 @@ struct PushNotifications::Pimpl | |||||
| static bool intentActionContainsAnyOf (jobject intent, const StringArray& strings, bool includePackageName) | static bool intentActionContainsAnyOf (jobject intent, const StringArray& strings, bool includePackageName) | ||||
| { | { | ||||
| auto* env = getEnv(); | auto* env = getEnv(); | ||||
| LocalRef<jobject> context (getAppContext()); | |||||
| LocalRef<jobject> context (getMainActivity()); | |||||
| String packageName = includePackageName ? juceString ((jstring) env->CallObjectMethod (context.get(), | String packageName = includePackageName ? juceString ((jstring) env->CallObjectMethod (context.get(), | ||||
| AndroidContext.getPackageName)) | AndroidContext.getPackageName)) | ||||
| @@ -1551,6 +1552,70 @@ struct PushNotifications::Pimpl | |||||
| PushNotifications& owner; | 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/roli/juce/JuceFirebaseInstanceIdService") | |||||
| #undef JNI_CLASS_MEMBERS | |||||
| static void JNICALL tokenRefreshed (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/roli/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) | bool juce_handleNotificationIntent (void* intent) | ||||
| { | { | ||||
| auto* instance = PushNotifications::getInstanceWithoutCreating(); | auto* instance = PushNotifications::getInstanceWithoutCreating(); | ||||
| @@ -1582,35 +1647,25 @@ bool juce_handleNotificationIntent (void* intent) | |||||
| return false; | return false; | ||||
| } | } | ||||
| void juce_firebaseDeviceNotificationsTokenRefreshed (void* token) | |||||
| { | |||||
| if (auto* instance = PushNotifications::getInstanceWithoutCreating()) | |||||
| instance->pimpl->notifyListenersTokenRefreshed (juceString (static_cast<jstring> (token))); | |||||
| } | |||||
| void juce_firebaseRemoteNotificationReceived (void* remoteMessage) | |||||
| //============================================================================== | |||||
| struct JuceActivityNewIntentListener | |||||
| { | { | ||||
| if (auto* instance = PushNotifications::getInstanceWithoutCreating()) | |||||
| instance->pimpl->notifyListenersAboutRemoteNotificationFromService (LocalRef<jobject> (static_cast<jobject> (remoteMessage))); | |||||
| } | |||||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ | |||||
| CALLBACK (appNewIntent, "appNewIntent", "(Landroid/content/Intent;)V") | |||||
| void juce_firebaseRemoteMessagesDeleted() | |||||
| { | |||||
| if (auto* instance = PushNotifications::getInstanceWithoutCreating()) | |||||
| instance->pimpl->notifyListenersAboutRemoteNotificationsDeleted(); | |||||
| } | |||||
| DECLARE_JNI_CLASS (JavaActivity, JUCE_PUSH_NOTIFICATIONS_ACTIVITY) | |||||
| #undef JNI_CLASS_MEMBERS | |||||
| void juce_firebaseRemoteMessageSent (void* messageId) | |||||
| { | |||||
| if (auto* instance = PushNotifications::getInstanceWithoutCreating()) | |||||
| instance->pimpl->notifyListenersAboutUpstreamMessageSent (LocalRef<jstring> (static_cast<jstring> (messageId))); | |||||
| } | |||||
| 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 | |||||
| } | |||||
| }; | |||||
| void juce_firebaseRemoteMessageSendError (void* messageId, void* error) | |||||
| { | |||||
| if (auto* instance = PushNotifications::getInstanceWithoutCreating()) | |||||
| instance->pimpl->notifyListenersAboutUpstreamMessageSendingError (LocalRef<jstring> (static_cast<jstring> (messageId)), | |||||
| LocalRef<jstring> (static_cast<jstring> (error))); | |||||
| } | |||||
| JuceActivityNewIntentListener::JavaActivity_Class JuceActivityNewIntentListener::JavaActivity; | |||||
| } // namespace juce | } // namespace juce | ||||