diff --git a/flutter-hms-push/CHANGELOG.md b/flutter-hms-push/CHANGELOG.md index 21fbbbfd..1d51c962 100644 --- a/flutter-hms-push/CHANGELOG.md +++ b/flutter-hms-push/CHANGELOG.md @@ -1,3 +1,13 @@ +## 5.1.1+301 +* Updated Push SDK to the latest version 5.1.1+301. +* Added Multi-Sender API. +* Bug fixes and improvements. +* **[Breaking Changes]** + * Migrated the plugin to Null-Safety. + * Folder structure updated, all library can be imported with a single line. + * Code constant renamed as ResultCodes. + * Push.deleteToken method's result will not be returned to the stream anymore, it can be obtained directly from the method. + ## 5.0.2+304 * Updated HMSLogger. * Changed lightSettings, vibrateConfig, titleLocalizationArgs and bodyLocalizationArgs fields of RemoteMessageNotification to type List\ in order to support parsing for 3rd party integrations. diff --git a/flutter-hms-push/README.md b/flutter-hms-push/README.md index b729dcf9..9c787db4 100644 --- a/flutter-hms-push/README.md +++ b/flutter-hms-push/README.md @@ -2,32 +2,39 @@

Huawei Push Kit Flutter Plugin

+ + +

+ pub.dev version +

+ + ---- HUAWEI Push Kit is a messaging service provided by Huawei. It establishes a messaging channel from the cloud to devices. By integrating Push Kit, you can send messages to your apps on users' devices in real time. This helps you maintain closer ties with users and increases user awareness and engagement with your apps. This plugin enables communication between HUAWEI Push Kit SDK and Flutter platform. It exposes all functionality provided by HUAWEI Push Kit SDK. -[> Learn More](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/service-introduction-0000001050040060-V5) +[Learn More](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/service-introduction-0000001050040060-V5?ha_source=hms1) ## Installation -Please see [pub.dev](https://pub.dev/packages/huawei_push/install) and [AppGallery Connect Configuration](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/config-agc-0000001050178043). +Please see [pub.dev](https://pub.dev/packages/huawei_push/install) and [AppGallery Connect Configuration](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/config-agc-0000001050178043?ha_source=hms1). ## Documentation -- [Quick Start](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/basiccapabilities-0000001050417999) -- [Reference](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-References/overview-0000001057463088) +- [Quick Start](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/basiccapabilities-0000001050417999?ha_source=hms1) +- [Reference](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-References/overview-0000001057463088?ha_source=hms1) ### Additional Topics -- [Basic Capabilities](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/basiccapabilities-0000001050417999) -- [Topic-based Message Sending](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/topicbased-message-0000001050190681) -- [Receiving Data Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/receiving-data-messages-at-killed-state-0000001058199547) -- [Deep Linking with Custom Intent URIs](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/deeplinking-custom-0000001055875857) -- [Obtaining Initial Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/get-initial-notif-0000001056552970) -- [Listening to Message Tap Events](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/listen-notif-message-0000001057481400) -- [Sending Local Notification Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/send-local-notif-0000001057760996) -- [Sending Uplink Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/send-uplink-0000001057200983) +- [Basic Capabilities](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/basiccapabilities-0000001050417999?ha_source=hms1) +- [Topic-based Message Sending](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/topicbased-message-0000001050190681?ha_source=hms1) +- [Receiving Data Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/receiving-data-messages-at-killed-state-0000001058199547?ha_source=hms1) +- [Deep Linking with Custom Intent URIs](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/deeplinking-custom-0000001055875857?ha_source=hms1) +- [Obtaining Initial Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/get-initial-notif-0000001056552970?ha_source=hms1) +- [Listening to Message Tap Events](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/listen-notif-message-0000001057481400?ha_source=hms1) +- [Sending Local Notification Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/send-local-notif-0000001057760996?ha_source=hms1) +- [Sending Uplink Messages](https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/send-uplink-0000001057200983?ha_source=hms1) ## Questions or Issues @@ -35,8 +42,8 @@ If you have questions about how to use HMS samples, try the following options: - [Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services) is the best place for any programming questions. Be sure to tag your question with **huawei-mobile-services**. - [Github](https://github.com/HMS-Core/hms-flutter-plugin) is the official repository for these plugins, You can open an issue or submit your ideas. -- [Huawei Developer Forum](https://forums.developer.huawei.com/forumPortal/en/home?fid=0101187876626530001) HMS Core Module is great for general questions, or seeking recommendations and opinions. -- [Huawei Developer Docs](https://developer.huawei.com/consumer/en/doc/overview/HMS-Core-Plugin) is place to official documentation for all HMS Core Kits, you can find detailed documentations in there. +- [Huawei Developer Forum](https://forums.developer.huawei.com/forumPortal/en/home?fid=0101187876626530001?ha_source=hms1) HMS Core Module is great for general questions, or seeking recommendations and opinions. +- [Huawei Developer Docs](https://developer.huawei.com/consumer/en/doc/overview/HMS-Core-Plugin?ha_source=hms1) is place to official documentation for all HMS Core Kits, you can find detailed documentations in there. If you run into a bug in our samples, please submit an issue to the [GitHub repository](https://github.com/HMS-Core/hms-flutter-plugin). diff --git a/flutter-hms-push/android/build.gradle b/flutter-hms-push/android/build.gradle index 482c0f6c..a48b69f9 100644 --- a/flutter-hms-push/android/build.gradle +++ b/flutter-hms-push/android/build.gradle @@ -40,6 +40,7 @@ android { } dependencies { - implementation 'com.huawei.hms:push:5.0.2.300' + implementation 'com.huawei.hms:push:5.1.1.301' + implementation 'com.huawei.hms:push-fcm:5.1.1.301' implementation 'com.facebook.fresco:fresco:2.2.0' } diff --git a/flutter-hms-push/android/gradle/wrapper/gradle-wrapper.properties b/flutter-hms-push/android/gradle/wrapper/gradle-wrapper.properties index a4b44297..442d9132 100644 --- a/flutter-hms-push/android/gradle/wrapper/gradle-wrapper.properties +++ b/flutter-hms-push/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/flutter-hms-push/android/gradlew b/flutter-hms-push/android/gradlew index cccdd3d5..4f906e0c 100755 --- a/flutter-hms-push/android/gradlew +++ b/flutter-hms-push/android/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/flutter-hms-push/android/gradlew.bat b/flutter-hms-push/android/gradlew.bat index f9553162..107acd32 100644 --- a/flutter-hms-push/android/gradlew.bat +++ b/flutter-hms-push/android/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/HeadlessPushPlugin.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/HeadlessPushPlugin.java index 533c689b..4e447a57 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/HeadlessPushPlugin.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/HeadlessPushPlugin.java @@ -27,10 +27,6 @@ import com.huawei.hms.flutter.push.utils.RemoteMessageUtils; import com.huawei.hms.push.RemoteMessage; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.PluginRegistry; @@ -39,25 +35,30 @@ import io.flutter.view.FlutterNativeView; import io.flutter.view.FlutterRunArguments; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + public class HeadlessPushPlugin implements MethodChannel.MethodCallHandler { private static final String TAG = HeadlessPushPlugin.class.getSimpleName(); - public final static String KEY_HANDLER = "push_background_message_handler"; - public final static String KEY_CALLBACK = "push_background_message_callback"; + public static final String KEY_HANDLER = "push_background_message_handler"; + + public static final String KEY_CALLBACK = "push_background_message_callback"; - private static MethodChannel methodBackgroundChannel; private static PluginRegistry.PluginRegistrantCallback pluginRegistrantCallback; + private MethodChannel methodBackgroundChannel; + private Context context; - private static FlutterNativeView flutterNativeView; + private FlutterNativeView flutterNativeView; private static final AtomicBoolean SYNCHRONIZER = new AtomicBoolean(false); public HeadlessPushPlugin(Context context) { this.context = context; - if (flutterNativeView == null) - initFlutterNativeView(); + initFlutterNativeView(); // Queue events while background isolate is starting waitFlutterNativeView(); @@ -86,7 +87,6 @@ static void setPluginRegistrant(PluginRegistry.PluginRegistrantCallback callback pluginRegistrantCallback = callback; } - public void handleBackgroundMessage(Context context, RemoteMessage remoteMessage) { SharedPreferences prefs = context.getSharedPreferences(Core.PREFERENCE_NAME, Context.MODE_PRIVATE); @@ -106,15 +106,9 @@ private void initFlutterNativeView() { FlutterMain.ensureInitializationComplete(context, null); SharedPreferences prefs = context.getSharedPreferences(Core.PREFERENCE_NAME, Context.MODE_PRIVATE); - Long mCallbackHandle = prefs.getLong(KEY_HANDLER, -1); + long mCallbackHandle = prefs.getLong(KEY_HANDLER, -1); - FlutterCallbackInformation callbackInfo = FlutterCallbackInformation - .lookupCallbackInformation(mCallbackHandle); - - if (callbackInfo == null) { - Log.e(TAG, "ERROR : failed to find callback"); - return; - } + FlutterCallbackInformation callbackInfo = FlutterCallbackInformation.lookupCallbackInformation(mCallbackHandle); flutterNativeView = new FlutterNativeView(context.getApplicationContext(), true); @@ -122,8 +116,9 @@ private void initFlutterNativeView() { methodBackgroundChannel = new MethodChannel(flutterNativeView, Channel.BACKGROUND_MESSAGE_CHANNEL.id()); methodBackgroundChannel.setMethodCallHandler(this); - if (pluginRegistrantCallback == null) + if (pluginRegistrantCallback == null) { return; + } pluginRegistrantCallback.registerWith(flutterNativeView.getPluginRegistry()); diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/PushPlugin.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/PushPlugin.java index ddada4dc..3046d3af 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/PushPlugin.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/PushPlugin.java @@ -18,6 +18,7 @@ import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; import android.widget.Toast; @@ -25,22 +26,30 @@ import androidx.annotation.NonNull; import com.huawei.hms.flutter.push.constants.Channel; +import com.huawei.hms.flutter.push.constants.Code; import com.huawei.hms.flutter.push.constants.Core; import com.huawei.hms.flutter.push.constants.Method; import com.huawei.hms.flutter.push.constants.Param; -import com.huawei.hms.flutter.push.event.DataMessageStreamHandler; -import com.huawei.hms.flutter.push.event.TokenStreamHandler; -import com.huawei.hms.flutter.push.event.local.LocalNotificationClickStreamHandler; -import com.huawei.hms.flutter.push.event.local.LocalNotificationOpenStreamHandler; -import com.huawei.hms.flutter.push.event.remote.RemoteMessageCustomIntentStreamHandler; -import com.huawei.hms.flutter.push.event.remote.RemoteMessageSentDeliveredStreamHandler; +import com.huawei.hms.flutter.push.constants.PushIntent; +import com.huawei.hms.flutter.push.event.DefaultStreamHandler; import com.huawei.hms.flutter.push.hms.FlutterHmsInstanceId; import com.huawei.hms.flutter.push.hms.FlutterHmsMessaging; import com.huawei.hms.flutter.push.hms.FlutterHmsOpenDevice; +import com.huawei.hms.flutter.push.hms.FlutterHmsProfile; +import com.huawei.hms.flutter.push.hms.PluginContext; import com.huawei.hms.flutter.push.localnotification.HmsLocalNotification; import com.huawei.hms.flutter.push.logger.HMSLogger; +import com.huawei.hms.flutter.push.receiver.MultiSenderTokenReceiver; +import com.huawei.hms.flutter.push.receiver.RemoteDataMessageReceiver; +import com.huawei.hms.flutter.push.receiver.TokenReceiver; import com.huawei.hms.flutter.push.receiver.common.NotificationIntentListener; +import com.huawei.hms.flutter.push.receiver.common.NotificationOpenEventReceiver; +import com.huawei.hms.flutter.push.receiver.local.LocalNotificationClickEventReceiver; +import com.huawei.hms.flutter.push.receiver.remote.RemoteMessageNotificationIntentReceiver; +import com.huawei.hms.flutter.push.receiver.remote.RemoteMessageSentDeliveredReceiver; import com.huawei.hms.flutter.push.utils.Utils; +import com.huawei.hms.push.plugin.base.proxy.ProxySettings; +import com.huawei.hms.push.plugin.fcm.FcmPushProxy; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; @@ -52,8 +61,12 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry; -import io.flutter.plugin.common.PluginRegistry.Registrar; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; /** * class PushPlugin @@ -61,56 +74,36 @@ * @since 4.0.4 */ public class PushPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware { - private static String TAG = "HmsFlutterPush"; + private static final String TAG = "HmsFlutterPush"; private MethodChannel channel; - private static volatile Context context; - private HmsLocalNotification hmsLocalNotification; - private NotificationIntentListener notificationIntentListener; - - private Activity activity; + private Context context; - public static Context getContext() { - return PushPlugin.context; - } - - public static void setContext(Context context) { - PushPlugin.context = context; - } + private HmsLocalNotification hmsLocalNotification; - private void setStreamHandlers(BinaryMessenger messenger) { - EventChannel tokenEventChannel = new EventChannel(messenger, Channel.TOKEN_CHANNEL.id()); - tokenEventChannel.setStreamHandler(new TokenStreamHandler(context)); + private NotificationIntentListener notificationIntentListener; - EventChannel remoteMsgReceiveEventChannel = - new EventChannel(messenger, Channel.REMOTE_MESSAGE_RECEIVE_CHANNEL.id()); - remoteMsgReceiveEventChannel.setStreamHandler(new DataMessageStreamHandler(context)); + private FlutterHmsInstanceId hmsInstanceId; - EventChannel remoteMsgSentDeliveredEventChannel = - new EventChannel(messenger, Channel.REMOTE_MESSAGE_SEND_STATUS_CHANNEL.id()); - remoteMsgSentDeliveredEventChannel.setStreamHandler(new RemoteMessageSentDeliveredStreamHandler(context)); + private FlutterHmsMessaging hmsMessaging; - // For sending remote message notification's custom intent Uri events - EventChannel remoteMsgCustomIntentEventChannel = - new EventChannel(messenger, Channel.REMOTE_MESSAGE_NOTIFICATION_INTENT_CHANNEL.id()); - remoteMsgCustomIntentEventChannel.setStreamHandler(new RemoteMessageCustomIntentStreamHandler(context)); + private FlutterHmsProfile hmsProfile; - EventChannel notificationOpenEventChannel - = new EventChannel(messenger, Channel.NOTIFICATION_OPEN_CHANNEL.id()); - notificationOpenEventChannel.setStreamHandler(new LocalNotificationOpenStreamHandler(context)); + private Activity activity; - EventChannel localNotificationClickEventChannel - = new EventChannel(messenger, Channel.LOCAL_NOTIFICATION_CLICK_CHANNEL.id()); - localNotificationClickEventChannel.setStreamHandler(new LocalNotificationClickStreamHandler(context)); - } + private List eventChannels = new ArrayList<>(); public void onAttachedToEngine(BinaryMessenger messenger, Context context) { channel = new MethodChannel(messenger, Channel.METHOD_CHANNEL.id()); channel.setMethodCallHandler(this); - PushPlugin.setContext(context); - notificationIntentListener = new NotificationIntentListener(); + this.context = context; + hmsProfile = new FlutterHmsProfile(context); + hmsInstanceId = new FlutterHmsInstanceId(context); + notificationIntentListener = new NotificationIntentListener(context); hmsLocalNotification = new HmsLocalNotification(context); + hmsMessaging = new FlutterHmsMessaging(context); + PluginContext.initialize(context); setStreamHandlers(messenger); } @@ -119,25 +112,38 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin onAttachedToEngine(flutterPluginBinding.getBinaryMessenger(), flutterPluginBinding.getApplicationContext()); } - public static void registerWith(Registrar registrar) { + public static void registerWith(PluginRegistry.Registrar registrar) { PushPlugin instance = new PushPlugin(); instance.onAttachedToEngine(registrar.messenger(), registrar.context()); if (registrar.activity() != null) { registrar.addNewIntentListener(instance.notificationIntentListener); - instance.notificationIntentListener.handleIntent(registrar.activity().getIntent()); + Log.e(TAG, "registerWith: " + registrar.activity().getIntent(), null); + Intent launcherIntent = registrar.activity().getIntent(); + if (Utils.checkNotificationFlags(launcherIntent)) { + instance.notificationIntentListener.handleIntent(launcherIntent); + } } } @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - if (channel != null) channel.setMethodCallHandler(null); + if (channel != null) { + channel.setMethodCallHandler(null); + for (EventChannel e : eventChannels) { + e.setStreamHandler(null); + } + eventChannels.clear(); + } } @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { this.activity = binding.getActivity(); binding.addOnNewIntentListener(this.notificationIntentListener); - this.notificationIntentListener.handleIntent(activity.getIntent()); + Intent startupIntent = activity.getIntent(); + if (Utils.checkNotificationFlags(startupIntent)) { + this.notificationIntentListener.handleIntent(startupIntent); + } } @Override @@ -161,22 +167,23 @@ public void onDetachedFromActivity() { public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { switch (Method.valueOf(call.method)) { case getId: - FlutterHmsInstanceId.getId(result); + hmsInstanceId.getId(result); break; case getAAID: - FlutterHmsInstanceId.getAAID(result); + hmsInstanceId.getAAID(result); break; case getAppId: - FlutterHmsInstanceId.getAppId(result); + hmsInstanceId.getAppId(result); break; case getCreationTime: - FlutterHmsInstanceId.getCreationTime(result); + hmsInstanceId.getCreationTime(result); break; case deleteAAID: - FlutterHmsInstanceId.deleteAAID(result); + hmsInstanceId.deleteAAID(result); break; case registerBackgroundMessageHandler: - registerBackgroundMessageHandler((long) call.argument("rawHandle"), (long) call.argument("rawCallback"), result); + registerBackgroundMessageHandler(Objects.requireNonNull(call.argument("rawHandle")), + Objects.requireNonNull(call.argument("rawCallback")), result); break; case removeBackgroundMessageHandler: removeBackgroundMessageHandler(result); @@ -189,10 +196,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { private void onMethodCallToken(@NonNull MethodCall call, @NonNull Result result) { switch (Method.valueOf(call.method)) { case getToken: - FlutterHmsInstanceId.getToken(Utils.getStringArgument(call, Param.SCOPE.code())); + hmsInstanceId.getToken(Utils.getStringArgument(call, Param.SCOPE.code())); break; case deleteToken: - FlutterHmsInstanceId.deleteToken(Utils.getStringArgument(call, Param.SCOPE.code())); + hmsInstanceId.deleteToken(Utils.getStringArgument(call, Param.SCOPE.code()), result); break; default: onMethodCallOpenDevice(call, result); @@ -254,6 +261,9 @@ private void onMethodCallLocalNotification(@NonNull MethodCall call, @NonNull Re case cancelNotificationsWithIdTag: hmsLocalNotification.cancelNotificationsWithIdTag(call); break; + case getInitialIntent: + notificationIntentListener.getInitialIntent(result); + break; default: onMethodCallSubscribe(call, result); } @@ -262,10 +272,10 @@ private void onMethodCallLocalNotification(@NonNull MethodCall call, @NonNull Re private void onMethodCallSubscribe(@NonNull MethodCall call, @NonNull Result result) { switch (Method.valueOf(call.method)) { case subscribe: - FlutterHmsMessaging.subscribe(Utils.getStringArgument(call, Param.TOPIC.code()), result); + hmsMessaging.subscribe(Utils.getStringArgument(call, Param.TOPIC.code()), result); break; case unsubscribe: - FlutterHmsMessaging.unsubscribe(Utils.getStringArgument(call, Param.TOPIC.code()), result); + hmsMessaging.unsubscribe(Utils.getStringArgument(call, Param.TOPIC.code()), result); break; default: onMethodCallEnable(call, result); @@ -275,22 +285,22 @@ private void onMethodCallSubscribe(@NonNull MethodCall call, @NonNull Result res private void onMethodCallEnable(@NonNull MethodCall call, @NonNull Result result) { switch (Method.valueOf(call.method)) { case send: - FlutterHmsMessaging.sendRemoteMessage(result, call); + hmsMessaging.sendRemoteMessage(result, call); break; case turnOnPush: - FlutterHmsMessaging.turnOnPush(result); + hmsMessaging.turnOnPush(result); break; case turnOffPush: - FlutterHmsMessaging.turnOffPush(result); + hmsMessaging.turnOffPush(result); break; case setAutoInitEnabled: - FlutterHmsMessaging.setAutoInitEnabled(Utils.getBoolArgument(call, Param.ENABLED.code()), result); + hmsMessaging.setAutoInitEnabled(Utils.getBoolArgument(call, Param.ENABLED.code()), result); break; case isAutoInitEnabled: - FlutterHmsMessaging.isAutoInitEnabled(result); + hmsMessaging.isAutoInitEnabled(result); break; case getAgConnectValues: - FlutterHmsInstanceId.getAgConnectValues(result); + hmsInstanceId.getAgConnectValues(result); break; case showToast: Toast.makeText(context, Utils.getStringArgument(call, Param.MESSAGE.code()), Toast.LENGTH_LONG).show(); @@ -309,19 +319,59 @@ private void onMethodCallDotting(@NonNull MethodCall call, @NonNull Result resul HMSLogger.getInstance(context).disableLogger(); break; default: - onMethodCallOther(call, result); + onMethodCallHmsProfile(call, result); } } - private void onMethodCallOther(@NonNull MethodCall call, @NonNull Result result) { - if (Method.valueOf(call.method) == Method.getInitialIntent) { - notificationIntentListener.getInitialIntent(result); - } else result.notImplemented(); + private void onMethodCallHmsProfile(@NonNull MethodCall call, @NonNull Result result) { + switch (Method.valueOf(call.method)) { + case isSupportProfile: + hmsProfile.isSupportProfile(result); + break; + case addProfile: + hmsProfile.addProfile(call, result); + break; + case addMultiSenderProfile: + hmsProfile.addMultiSenderProfile(call, result); + break; + case deleteProfile: + hmsProfile.deleteProfile(call, result); + break; + case deleteMultiSenderProfile: + hmsProfile.deleteMultiSenderProfile(call, result); + break; + case getMultiSenderToken: + hmsInstanceId.getMultiSenderToken(Utils.getStringArgument(call, Param.SUBJECT_ID.code())); + break; + case deleteMultiSenderToken: + hmsInstanceId.deleteMultiSenderToken(Utils.getStringArgument(call, Param.SUBJECT_ID.code()), result); + break; + default: + onMethodCallProxy(call, result); + break; + } } + private void onMethodCallProxy(final @NonNull MethodCall call, final @NonNull Result result) { + switch (Method.valueOf(call.method)) { + case setCountryCode: + HMSLogger.getInstance(context).startMethodExecutionTimer(Method.setCountryCode.name()); + ProxySettings.setCountryCode(context, call.argument("countryCode")); + result.success(Code.RESULT_SUCCESS.code()); + HMSLogger.getInstance(context).sendSingleEvent(Method.setCountryCode.name()); + break; + case initFcmPushProxy: + HMSLogger.getInstance(context).startMethodExecutionTimer(Method.initFcmPushProxy.name()); + result.success(FcmPushProxy.init(context)); + HMSLogger.getInstance(context).sendSingleEvent(Method.initFcmPushProxy.name()); + break; + default: + result.notImplemented(); + break; + } + } private void registerBackgroundMessageHandler(long handlerRaw, long callbackRaw, Result result) { - try { SharedPreferences prefs = context.getSharedPreferences(Core.PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); @@ -337,12 +387,10 @@ private void registerBackgroundMessageHandler(long handlerRaw, long callbackRaw, } private void removeBackgroundMessageHandler(Result result) { - SharedPreferences prefs = context.getSharedPreferences(Core.PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putLong(HeadlessPushPlugin.KEY_HANDLER, -1); editor.putLong(HeadlessPushPlugin.KEY_CALLBACK, -1); - editor.apply(); Log.i(TAG, "BackgroundMessageHandler removed ✔"); @@ -353,4 +401,39 @@ public static void setPluginRegistrant(PluginRegistry.PluginRegistrantCallback c HeadlessPushPlugin.setPluginRegistrant(callback); } + private void setStreamHandlers(BinaryMessenger messenger) { + Map streams = new ConcurrentHashMap<>(); + streams.put(Channel.TOKEN_CHANNEL.id(), + new DefaultStreamHandler(context, TokenReceiver::new, PushIntent.TOKEN_INTENT_ACTION)); + + streams.put(Channel.MULTI_SENDER_TOKEN_CHANNEL.id(), + new DefaultStreamHandler(context, MultiSenderTokenReceiver::new, + PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION)); + + streams.put(Channel.REMOTE_MESSAGE_RECEIVE_CHANNEL.id(), + new DefaultStreamHandler(context, RemoteDataMessageReceiver::new, + PushIntent.REMOTE_DATA_MESSAGE_INTENT_ACTION)); + + streams.put(Channel.REMOTE_MESSAGE_SEND_STATUS_CHANNEL.id(), + new DefaultStreamHandler(context, RemoteMessageSentDeliveredReceiver::new, + PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION)); + + // For sending remote message notification's custom intent Uri events + streams.put(Channel.REMOTE_MESSAGE_NOTIFICATION_INTENT_CHANNEL.id(), + new DefaultStreamHandler(context, RemoteMessageNotificationIntentReceiver::new, + PushIntent.REMOTE_MESSAGE_NOTIFICATION_INTENT_ACTION)); + + streams.put(Channel.NOTIFICATION_OPEN_CHANNEL.id(), + new DefaultStreamHandler(context, NotificationOpenEventReceiver::new, PushIntent.NOTIFICATION_OPEN_ACTION)); + + streams.put(Channel.LOCAL_NOTIFICATION_CLICK_CHANNEL.id(), + new DefaultStreamHandler(context, LocalNotificationClickEventReceiver::new, + PushIntent.LOCAL_NOTIFICATION_CLICK_ACTION)); + + for (Map.Entry entry : streams.entrySet()) { + EventChannel eventChannel = new EventChannel(messenger, entry.getKey()); + eventChannel.setStreamHandler(entry.getValue()); + eventChannels.add(eventChannel); + } + } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/config/NotificationAttributes.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/config/NotificationAttributes.java index 2214ef5c..365c7038 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/config/NotificationAttributes.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/config/NotificationAttributes.java @@ -28,50 +28,85 @@ import com.huawei.hms.flutter.push.utils.BundleUtils; import com.huawei.hms.flutter.push.utils.Utils; +import io.flutter.plugin.common.MethodCall; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; -import io.flutter.plugin.common.MethodCall; - public class NotificationAttributes { private final String id; + private final String message; + private final double fireDate; + private final String importance; + private final String title; + private final String ticker; + private final boolean showWhen; + private final boolean autoCancel; + private final String largeIcon; + private final String largeIconUrl; + private final String smallIcon; + private final String bigText; + private final String subText; + private final String bigPictureUrl; + private final String shortcutId; + private final String number; + private final String channelId; + private final String channelName; + private final String channelDescription; + private final String sound; + private final String soundName; + private final String color; + private final String group; + private final boolean groupSummary; + private final boolean userInteraction; + private final boolean playSound; + private final boolean vibrate; + private final double vibrateDuration; + private final String actions; + private final boolean invokeApp; + private final String tag; + private final String repeatType; + private final double repeatTime; + private final boolean ongoing; + private final boolean allowWhileIdle; + private final boolean dontNotifyInForeground; public NotificationAttributes(Bundle bundle) { @@ -115,78 +150,74 @@ public NotificationAttributes(Bundle bundle) { private NotificationAttributes(JSONObject json) { try { - id = json.has(NotificationConstants.ID) ? - json.getString(NotificationConstants.ID) : null; - message = json.has(NotificationConstants.MESSAGE) ? - json.getString(NotificationConstants.MESSAGE) : Core.DEFAULT_MESSAGE; - fireDate = json.has(NotificationConstants.FIRE_DATE) ? - json.getDouble(NotificationConstants.FIRE_DATE) : 0.0; - importance = json.has(NotificationConstants.IMPORTANCE) ? - json.getString(NotificationConstants.IMPORTANCE) : LocalNotification.Importance.MAX; - title = json.has(NotificationConstants.TITLE) ? - json.getString(NotificationConstants.TITLE) : null; - ticker = json.has(NotificationConstants.TICKER) ? - json.getString(NotificationConstants.TICKER) : null; - showWhen = !json.has(NotificationConstants.SHOW_WHEN) || - json.getBoolean(NotificationConstants.SHOW_WHEN); - autoCancel = !json.has(NotificationConstants.AUTO_CANCEL) || - json.getBoolean(NotificationConstants.AUTO_CANCEL); - largeIcon = json.has(NotificationConstants.LARGE_ICON) ? - json.getString(NotificationConstants.LARGE_ICON) : null; - largeIconUrl = json.has(NotificationConstants.LARGE_ICON_URL) ? - json.getString(NotificationConstants.LARGE_ICON_URL) : null; - smallIcon = json.has(NotificationConstants.SMALL_ICON) ? - json.getString(NotificationConstants.SMALL_ICON) : null; - bigText = json.has(NotificationConstants.BIG_TEXT) ? - json.getString(NotificationConstants.BIG_TEXT) : null; - subText = json.has(NotificationConstants.SUB_TEXT) ? - json.getString(NotificationConstants.SUB_TEXT) : null; - bigPictureUrl = json.has(NotificationConstants.BIG_PICTURE_URL) ? - json.getString(NotificationConstants.BIG_PICTURE_URL) : null; - shortcutId = json.has(NotificationConstants.SHORTCUT_ID) ? - json.getString(NotificationConstants.SHORTCUT_ID) : null; - number = json.has(NotificationConstants.NUMBER) ? - json.getString(NotificationConstants.NUMBER) : null; - channelId = json.has(NotificationConstants.CHANNEL_ID) ? - json.getString(NotificationConstants.CHANNEL_ID) : null; - channelName = json.has(NotificationConstants.CHANNEL_NAME) ? - json.getString(NotificationConstants.CHANNEL_NAME) : null; - channelDescription = json.has(NotificationConstants.CHANNEL_DESCRIPTION) ? - json.getString(NotificationConstants.CHANNEL_DESCRIPTION) : null; - sound = json.has(NotificationConstants.SOUND) ? - json.getString(NotificationConstants.SOUND) : null; - soundName = json.has(NotificationConstants.SOUND_NAME) ? - json.getString(NotificationConstants.SOUND_NAME) : null; - color = json.has(NotificationConstants.COLOR) ? - json.getString(NotificationConstants.COLOR) : null; - group = json.has(NotificationConstants.GROUP) ? - json.getString(NotificationConstants.GROUP) : null; - groupSummary = json.has(NotificationConstants.GROUP_SUMMARY) && - json.getBoolean(NotificationConstants.GROUP_SUMMARY); - userInteraction = json.has(NotificationConstants.USER_INTERACTION) && - json.getBoolean(NotificationConstants.USER_INTERACTION); - playSound = !json.has(NotificationConstants.PLAY_SOUND) || - json.getBoolean(NotificationConstants.PLAY_SOUND); - vibrate = !json.has(NotificationConstants.VIBRATE) || - json.getBoolean(NotificationConstants.VIBRATE); - vibrateDuration = json.has(NotificationConstants.VIBRATE_DURATION) ? - json.getDouble(NotificationConstants.VIBRATE_DURATION) : 1000; - actions = json.has(NotificationConstants.ACTIONS) ? - json.getString(NotificationConstants.ACTIONS) : null; - invokeApp = !json.has(NotificationConstants.INVOKE_APP) || - json.getBoolean(NotificationConstants.INVOKE_APP); - tag = json.has(NotificationConstants.TAG) ? - json.getString(NotificationConstants.TAG) : null; - repeatType = json.has(NotificationConstants.REPEAT_TYPE) ? - json.getString(NotificationConstants.REPEAT_TYPE) : null; - repeatTime = json.has(NotificationConstants.REPEAT_TIME) ? - json.getDouble(NotificationConstants.REPEAT_TIME) : 0.0; - ongoing = json.has(NotificationConstants.ONGOING) && - json.getBoolean(NotificationConstants.ONGOING); - allowWhileIdle = json.has(NotificationConstants.ALLOW_WHILE_IDLE) && - json.getBoolean(NotificationConstants.ALLOW_WHILE_IDLE); - dontNotifyInForeground = json.has(NotificationConstants.DONT_NOTIFY_IN_FOREGROUND) && - json.getBoolean(NotificationConstants.DONT_NOTIFY_IN_FOREGROUND); + id = json.has(NotificationConstants.ID) ? json.getString(NotificationConstants.ID) : null; + message = json.has(NotificationConstants.MESSAGE) + ? json.getString(NotificationConstants.MESSAGE) + : Core.DEFAULT_MESSAGE; + fireDate = json.has(NotificationConstants.FIRE_DATE) + ? json.getDouble(NotificationConstants.FIRE_DATE) + : 0.0; + importance = json.has(NotificationConstants.IMPORTANCE) + ? json.getString(NotificationConstants.IMPORTANCE) + : LocalNotification.Importance.MAX; + title = json.has(NotificationConstants.TITLE) ? json.getString(NotificationConstants.TITLE) : null; + ticker = json.has(NotificationConstants.TICKER) ? json.getString(NotificationConstants.TICKER) : null; + showWhen = !json.has(NotificationConstants.SHOW_WHEN) || json.getBoolean(NotificationConstants.SHOW_WHEN); + autoCancel = !json.has(NotificationConstants.AUTO_CANCEL) || json.getBoolean( + NotificationConstants.AUTO_CANCEL); + largeIcon = json.has(NotificationConstants.LARGE_ICON) + ? json.getString(NotificationConstants.LARGE_ICON) + : null; + largeIconUrl = json.has(NotificationConstants.LARGE_ICON_URL) ? json.getString( + NotificationConstants.LARGE_ICON_URL) : null; + smallIcon = json.has(NotificationConstants.SMALL_ICON) + ? json.getString(NotificationConstants.SMALL_ICON) + : null; + bigText = json.has(NotificationConstants.BIG_TEXT) ? json.getString(NotificationConstants.BIG_TEXT) : null; + subText = json.has(NotificationConstants.SUB_TEXT) ? json.getString(NotificationConstants.SUB_TEXT) : null; + bigPictureUrl = json.has(NotificationConstants.BIG_PICTURE_URL) ? json.getString( + NotificationConstants.BIG_PICTURE_URL) : null; + shortcutId = json.has(NotificationConstants.SHORTCUT_ID) + ? json.getString(NotificationConstants.SHORTCUT_ID) + : null; + number = json.has(NotificationConstants.NUMBER) ? json.getString(NotificationConstants.NUMBER) : null; + channelId = json.has(NotificationConstants.CHANNEL_ID) + ? json.getString(NotificationConstants.CHANNEL_ID) + : null; + channelName = json.has(NotificationConstants.CHANNEL_NAME) ? json.getString( + NotificationConstants.CHANNEL_NAME) : null; + channelDescription = json.has(NotificationConstants.CHANNEL_DESCRIPTION) ? json.getString( + NotificationConstants.CHANNEL_DESCRIPTION) : null; + sound = json.has(NotificationConstants.SOUND) ? json.getString(NotificationConstants.SOUND) : null; + soundName = json.has(NotificationConstants.SOUND_NAME) + ? json.getString(NotificationConstants.SOUND_NAME) + : null; + color = json.has(NotificationConstants.COLOR) ? json.getString(NotificationConstants.COLOR) : null; + group = json.has(NotificationConstants.GROUP) ? json.getString(NotificationConstants.GROUP) : null; + groupSummary = json.has(NotificationConstants.GROUP_SUMMARY) && json.getBoolean( + NotificationConstants.GROUP_SUMMARY); + userInteraction = json.has(NotificationConstants.USER_INTERACTION) && json.getBoolean( + NotificationConstants.USER_INTERACTION); + playSound = !json.has(NotificationConstants.PLAY_SOUND) || json.getBoolean( + NotificationConstants.PLAY_SOUND); + vibrate = !json.has(NotificationConstants.VIBRATE) || json.getBoolean(NotificationConstants.VIBRATE); + vibrateDuration = json.has(NotificationConstants.VIBRATE_DURATION) ? json.getDouble( + NotificationConstants.VIBRATE_DURATION) : 1000; + actions = json.has(NotificationConstants.ACTIONS) ? json.getString(NotificationConstants.ACTIONS) : null; + invokeApp = !json.has(NotificationConstants.INVOKE_APP) || json.getBoolean( + NotificationConstants.INVOKE_APP); + tag = json.has(NotificationConstants.TAG) ? json.getString(NotificationConstants.TAG) : null; + repeatType = json.has(NotificationConstants.REPEAT_TYPE) + ? json.getString(NotificationConstants.REPEAT_TYPE) + : null; + repeatTime = json.has(NotificationConstants.REPEAT_TIME) + ? json.getDouble(NotificationConstants.REPEAT_TIME) + : 0.0; + ongoing = json.has(NotificationConstants.ONGOING) && json.getBoolean(NotificationConstants.ONGOING); + allowWhileIdle = json.has(NotificationConstants.ALLOW_WHILE_IDLE) && json.getBoolean( + NotificationConstants.ALLOW_WHILE_IDLE); + dontNotifyInForeground = json.has(NotificationConstants.DONT_NOTIFY_IN_FOREGROUND) && json.getBoolean( + NotificationConstants.DONT_NOTIFY_IN_FOREGROUND); } catch (IllegalStateException | JSONException | NumberFormatException | NullPointerException e) { throw new IllegalStateException(Code.RESULT_ERROR.code(), e); } @@ -198,79 +229,83 @@ public static NotificationAttributes fromJson(String json) throws JSONException return new NotificationAttributes(jsonObject); } - public NotificationAttributes(MethodCall call) throws JSONException { - id = call.hasArgument(NotificationConstants.ID) ? - (String) call.argument(NotificationConstants.ID) : null; - message = call.hasArgument(NotificationConstants.MESSAGE) ? - (String) call.argument(NotificationConstants.MESSAGE) : Core.DEFAULT_MESSAGE; - fireDate = call.hasArgument(NotificationConstants.FIRE_DATE) ? - Utils.getDoubleArgument(call, NotificationConstants.FIRE_DATE) : 0.0; - importance = call.hasArgument(NotificationConstants.IMPORTANCE) ? - (String) call.argument(NotificationConstants.IMPORTANCE) : LocalNotification.Importance.MAX; - title = call.hasArgument(NotificationConstants.TITLE) ? - (String) call.argument(NotificationConstants.TITLE) : null; - ticker = call.hasArgument(NotificationConstants.TICKER) ? - (String) call.argument(NotificationConstants.TICKER) : null; - showWhen = !call.hasArgument(NotificationConstants.SHOW_WHEN) || - Utils.getBoolArgument(call, NotificationConstants.SHOW_WHEN); - autoCancel = !call.hasArgument(NotificationConstants.AUTO_CANCEL) || - Utils.getBoolArgument(call, NotificationConstants.AUTO_CANCEL); - largeIcon = call.hasArgument(NotificationConstants.LARGE_ICON) ? - (String) call.argument(NotificationConstants.LARGE_ICON) : null; - largeIconUrl = call.hasArgument(NotificationConstants.LARGE_ICON_URL) ? - (String) call.argument(NotificationConstants.LARGE_ICON_URL) : null; - smallIcon = call.hasArgument(NotificationConstants.SMALL_ICON) ? - (String) call.argument(NotificationConstants.SMALL_ICON) : null; - bigText = call.hasArgument(NotificationConstants.BIG_TEXT) ? - (String) call.argument(NotificationConstants.BIG_TEXT) : null; - subText = call.hasArgument(NotificationConstants.SUB_TEXT) ? - (String) call.argument(NotificationConstants.SUB_TEXT) : null; - bigPictureUrl = call.hasArgument(NotificationConstants.BIG_PICTURE_URL) ? - (String) call.argument(NotificationConstants.BIG_PICTURE_URL) : null; - shortcutId = call.hasArgument(NotificationConstants.SHORTCUT_ID) ? - (String) call.argument(NotificationConstants.SHORTCUT_ID) : null; - number = call.hasArgument(NotificationConstants.NUMBER) ? - (String) call.argument(NotificationConstants.NUMBER) : null; - channelId = call.hasArgument(NotificationConstants.CHANNEL_ID) ? - (String) call.argument(NotificationConstants.CHANNEL_ID) : null; - channelName = call.hasArgument(NotificationConstants.CHANNEL_NAME) ? - (String) call.argument(NotificationConstants.CHANNEL_NAME) : null; - channelDescription = call.hasArgument(NotificationConstants.CHANNEL_DESCRIPTION) ? - (String) call.argument(NotificationConstants.CHANNEL_DESCRIPTION) : null; - sound = call.hasArgument(NotificationConstants.SOUND) ? - (String) call.argument(NotificationConstants.SOUND) : null; - soundName = call.hasArgument(NotificationConstants.SOUND_NAME) ? - (String) call.argument(NotificationConstants.SOUND_NAME) : null; - color = call.hasArgument(NotificationConstants.COLOR) ? - (String) call.argument(NotificationConstants.COLOR) : null; - group = call.hasArgument(NotificationConstants.GROUP) ? - (String) call.argument(NotificationConstants.GROUP) : null; - groupSummary = call.hasArgument(NotificationConstants.GROUP_SUMMARY) && - Utils.getBoolArgument(call, NotificationConstants.GROUP_SUMMARY); - userInteraction = call.hasArgument(NotificationConstants.USER_INTERACTION) && - Utils.getBoolArgument(call, NotificationConstants.USER_INTERACTION); - playSound = !call.hasArgument(NotificationConstants.PLAY_SOUND) || - Utils.getBoolArgument(call, NotificationConstants.PLAY_SOUND); - vibrate = !call.hasArgument(NotificationConstants.VIBRATE) || - Utils.getBoolArgument(call, NotificationConstants.VIBRATE); - vibrateDuration = call.hasArgument(NotificationConstants.VIBRATE_DURATION) ? - Utils.getDoubleArgument(call , NotificationConstants.VIBRATE_DURATION) : 1000; - actions = call.hasArgument(NotificationConstants.ACTIONS) ? - new JSONArray((ArrayList) call.argument(NotificationConstants.ACTIONS)).toString() : null; - invokeApp = !call.hasArgument(NotificationConstants.INVOKE_APP) || - Utils.getBoolArgument(call, NotificationConstants.INVOKE_APP); - tag = call.hasArgument(NotificationConstants.TAG) ? - (String) call.argument(NotificationConstants.TAG) : null; - repeatType = call.hasArgument(NotificationConstants.REPEAT_TYPE) ? - (String) call.argument(NotificationConstants.REPEAT_TYPE) : null; - repeatTime = call.hasArgument(NotificationConstants.REPEAT_TIME) ? - Utils.getDoubleArgument(call , NotificationConstants.REPEAT_TIME) : 0.0; - ongoing = call.hasArgument(NotificationConstants.ONGOING) && - Utils.getBoolArgument(call, NotificationConstants.ONGOING); - allowWhileIdle = call.hasArgument(NotificationConstants.ALLOW_WHILE_IDLE) && - Utils.getBoolArgument(call, NotificationConstants.ALLOW_WHILE_IDLE); - dontNotifyInForeground = call.hasArgument(NotificationConstants.DONT_NOTIFY_IN_FOREGROUND) && - Utils.getBoolArgument(call, NotificationConstants.DONT_NOTIFY_IN_FOREGROUND); + public NotificationAttributes(MethodCall call) { + id = call.hasArgument(NotificationConstants.ID) ? (String) call.argument(NotificationConstants.ID) : null; + message = call.hasArgument(NotificationConstants.MESSAGE) ? (String) call.argument( + NotificationConstants.MESSAGE) : Core.DEFAULT_MESSAGE; + fireDate = call.hasArgument(NotificationConstants.FIRE_DATE) ? Utils.getDoubleArgument(call, + NotificationConstants.FIRE_DATE) : 0.0; + importance = call.hasArgument(NotificationConstants.IMPORTANCE) ? (String) call.argument( + NotificationConstants.IMPORTANCE) : LocalNotification.Importance.MAX; + title = call.hasArgument(NotificationConstants.TITLE) + ? (String) call.argument(NotificationConstants.TITLE) + : null; + ticker = call.hasArgument(NotificationConstants.TICKER) + ? (String) call.argument(NotificationConstants.TICKER) + : null; + showWhen = !call.hasArgument(NotificationConstants.SHOW_WHEN) || Utils.getBoolArgument(call, + NotificationConstants.SHOW_WHEN); + autoCancel = !call.hasArgument(NotificationConstants.AUTO_CANCEL) || Utils.getBoolArgument(call, + NotificationConstants.AUTO_CANCEL); + largeIcon = call.hasArgument(NotificationConstants.LARGE_ICON) ? (String) call.argument( + NotificationConstants.LARGE_ICON) : null; + largeIconUrl = call.hasArgument(NotificationConstants.LARGE_ICON_URL) ? (String) call.argument( + NotificationConstants.LARGE_ICON_URL) : null; + smallIcon = call.hasArgument(NotificationConstants.SMALL_ICON) ? (String) call.argument( + NotificationConstants.SMALL_ICON) : null; + bigText = call.hasArgument(NotificationConstants.BIG_TEXT) ? (String) call.argument( + NotificationConstants.BIG_TEXT) : null; + subText = call.hasArgument(NotificationConstants.SUB_TEXT) ? (String) call.argument( + NotificationConstants.SUB_TEXT) : null; + bigPictureUrl = call.hasArgument(NotificationConstants.BIG_PICTURE_URL) ? (String) call.argument( + NotificationConstants.BIG_PICTURE_URL) : null; + shortcutId = call.hasArgument(NotificationConstants.SHORTCUT_ID) ? (String) call.argument( + NotificationConstants.SHORTCUT_ID) : null; + number = call.hasArgument(NotificationConstants.NUMBER) + ? (String) call.argument(NotificationConstants.NUMBER) + : null; + channelId = call.hasArgument(NotificationConstants.CHANNEL_ID) ? (String) call.argument( + NotificationConstants.CHANNEL_ID) : null; + channelName = call.hasArgument(NotificationConstants.CHANNEL_NAME) ? (String) call.argument( + NotificationConstants.CHANNEL_NAME) : null; + channelDescription = call.hasArgument(NotificationConstants.CHANNEL_DESCRIPTION) ? (String) call.argument( + NotificationConstants.CHANNEL_DESCRIPTION) : null; + sound = call.hasArgument(NotificationConstants.SOUND) + ? (String) call.argument(NotificationConstants.SOUND) + : null; + soundName = call.hasArgument(NotificationConstants.SOUND_NAME) ? (String) call.argument( + NotificationConstants.SOUND_NAME) : null; + color = call.hasArgument(NotificationConstants.COLOR) + ? (String) call.argument(NotificationConstants.COLOR) + : null; + group = call.hasArgument(NotificationConstants.GROUP) + ? (String) call.argument(NotificationConstants.GROUP) + : null; + groupSummary = call.hasArgument(NotificationConstants.GROUP_SUMMARY) && Utils.getBoolArgument(call, + NotificationConstants.GROUP_SUMMARY); + userInteraction = call.hasArgument(NotificationConstants.USER_INTERACTION) && Utils.getBoolArgument(call, + NotificationConstants.USER_INTERACTION); + playSound = !call.hasArgument(NotificationConstants.PLAY_SOUND) || Utils.getBoolArgument(call, + NotificationConstants.PLAY_SOUND); + vibrate = !call.hasArgument(NotificationConstants.VIBRATE) || Utils.getBoolArgument(call, + NotificationConstants.VIBRATE); + vibrateDuration = call.hasArgument(NotificationConstants.VIBRATE_DURATION) ? Utils.getDoubleArgument(call, + NotificationConstants.VIBRATE_DURATION) : 1000; + actions = call.hasArgument(NotificationConstants.ACTIONS) ? new JSONArray( + (ArrayList) call.argument(NotificationConstants.ACTIONS)).toString() : null; + invokeApp = !call.hasArgument(NotificationConstants.INVOKE_APP) || Utils.getBoolArgument(call, + NotificationConstants.INVOKE_APP); + tag = call.hasArgument(NotificationConstants.TAG) ? (String) call.argument(NotificationConstants.TAG) : null; + repeatType = call.hasArgument(NotificationConstants.REPEAT_TYPE) ? (String) call.argument( + NotificationConstants.REPEAT_TYPE) : null; + repeatTime = call.hasArgument(NotificationConstants.REPEAT_TIME) ? Utils.getDoubleArgument(call, + NotificationConstants.REPEAT_TIME) : 0.0; + ongoing = call.hasArgument(NotificationConstants.ONGOING) && Utils.getBoolArgument(call, + NotificationConstants.ONGOING); + allowWhileIdle = call.hasArgument(NotificationConstants.ALLOW_WHILE_IDLE) && Utils.getBoolArgument(call, + NotificationConstants.ALLOW_WHILE_IDLE); + dontNotifyInForeground = call.hasArgument(NotificationConstants.DONT_NOTIFY_IN_FOREGROUND) + && Utils.getBoolArgument(call, NotificationConstants.DONT_NOTIFY_IN_FOREGROUND); } public Bundle toBundle() { diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Channel.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Channel.java index 98334944..bbff23cd 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Channel.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Channel.java @@ -19,6 +19,7 @@ public enum Channel { TOKEN_CHANNEL("com.huawei.flutter.push/token"), + MULTI_SENDER_TOKEN_CHANNEL("com.huawei.flutter.push/multi_sender_token"), REMOTE_MESSAGE_RECEIVE_CHANNEL("com.huawei.flutter.push/remote_message_receive"), REMOTE_MESSAGE_SEND_STATUS_CHANNEL("com.huawei.flutter.push/remote_message_send_status"), REMOTE_MESSAGE_NOTIFICATION_INTENT_CHANNEL("com.huawei.flutter.push/remote_message_notification_intent"), diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Method.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Method.java index 0d982b97..3224230f 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Method.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Method.java @@ -25,11 +25,13 @@ public enum Method { getAAID, getAppId, getToken, + getMultiSenderToken, getCreationTime, getOdid, deleteAAID, deleteToken, + deleteMultiSenderToken, subscribe, unsubscribe, @@ -57,6 +59,15 @@ public enum Method { cancelNotificationsWithId, cancelNotificationsWithIdTag, + isSupportProfile, + addProfile, + addMultiSenderProfile, + deleteProfile, + deleteMultiSenderProfile, + + setCountryCode, + initFcmPushProxy, + enableLogger, disableLogger, diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Param.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Param.java index 72bee782..c191cedc 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Param.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/Param.java @@ -21,7 +21,8 @@ public enum Param { TOPIC("topic"), ENABLED("enabled"), SCOPE("scope"), - MESSAGE("msg"); + MESSAGE("msg"), + SUBJECT_ID("subjectId"); private String code; diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/PushIntent.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/PushIntent.java index a52d10ac..a6c47790 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/PushIntent.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/constants/PushIntent.java @@ -19,9 +19,12 @@ public enum PushIntent { TOKEN_INTENT_ACTION("hms.intent.action.TOKEN"), + MULTI_SENDER_TOKEN_INTENT_ACTION("hms.intent.action.MULTI_SENDER_TOKEN"), TOKEN_ERROR("TOKEN_ERROR"), + MULTI_SENDER_TOKEN_ERROR("MULTI_SENDER_TOKEN_ERROR"), TOKEN("TOKEN"), - DATA_MESSAGE_INTENT_ACTION("hms.intent.action.DATA_MESSAGE"), + MULTI_SENDER_TOKEN("MULTI_SENDER_TOKEN"), + REMOTE_DATA_MESSAGE_INTENT_ACTION("hms.intent.action.DATA_MESSAGE"), DATA_MESSAGE("DATA_MESSAGE"), REMOTE_MESSAGE_SENT_DELIVERED_ACTION("hms.intent.action.REMOTE_MESSAGE_SENT_DELIVERED"), REMOTE_MESSAGE_NOTIFICATION_INTENT_ACTION("hms.intent.action.REMOTE_MESSAGE_NOTIFICATION_INTENT"), diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/CreateBroadcastReceiverCallback.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/CreateBroadcastReceiverCallback.java new file mode 100644 index 00000000..a6d115a3 --- /dev/null +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/CreateBroadcastReceiverCallback.java @@ -0,0 +1,36 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.huawei.hms.flutter.push.event; + +import android.content.BroadcastReceiver; + +import io.flutter.plugin.common.EventChannel; + +/** + * Interface that is used as a callback for creating a {@link BroadcastReceiver} + * + * @since 5.1.1 + */ +public interface CreateBroadcastReceiverCallback { + /** + * Creates a BroadcastReceiver. + * + * @param events Events from the assigned stream handler. + * @return A BroadcastReceiver Object + */ + BroadcastReceiver createBroadcastReceiver(EventChannel.EventSink events); +} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/DataMessageStreamHandler.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/DataMessageStreamHandler.java deleted file mode 100644 index d72afbb2..00000000 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/DataMessageStreamHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License") - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package com.huawei.hms.flutter.push.event; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.IntentFilter; - -import com.huawei.hms.flutter.push.constants.PushIntent; -import com.huawei.hms.flutter.push.receiver.DataMessageReceiver; - -import io.flutter.plugin.common.EventChannel.EventSink; -import io.flutter.plugin.common.EventChannel.StreamHandler; - -public class DataMessageStreamHandler implements StreamHandler { - - private Context context; - private BroadcastReceiver dataMessageEventBroadcastReceiver; - - public DataMessageStreamHandler(Context context) { - this.context = context; - } - - @Override - public void onListen(Object arguments, EventSink events) { - dataMessageEventBroadcastReceiver = createDataMessageEventBroadcastReceiver(events); - context.registerReceiver(dataMessageEventBroadcastReceiver, - new IntentFilter(PushIntent.DATA_MESSAGE_INTENT_ACTION.id())); - } - - @Override - public void onCancel(Object arguments) { - context.unregisterReceiver(dataMessageEventBroadcastReceiver); - } - - private BroadcastReceiver createDataMessageEventBroadcastReceiver(final EventSink events) { - return new DataMessageReceiver(events); - } -} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/TokenStreamHandler.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/DefaultStreamHandler.java similarity index 55% rename from flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/TokenStreamHandler.java rename to flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/DefaultStreamHandler.java index 7274273d..3ce9cb8e 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/TokenStreamHandler.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/DefaultStreamHandler.java @@ -21,33 +21,33 @@ import android.content.IntentFilter; import com.huawei.hms.flutter.push.constants.PushIntent; -import com.huawei.hms.flutter.push.receiver.TokenReceiver; -import io.flutter.plugin.common.EventChannel.EventSink; -import io.flutter.plugin.common.EventChannel.StreamHandler; +import io.flutter.plugin.common.EventChannel; -public class TokenStreamHandler implements StreamHandler { +public class DefaultStreamHandler implements EventChannel.StreamHandler { private Context context; - private BroadcastReceiver tokenEventBroadcastReceiver; - public TokenStreamHandler(Context context) { + private BroadcastReceiver broadcastReceiver; + + private CreateBroadcastReceiverCallback cb; + + private PushIntent intentAction; + + public DefaultStreamHandler(Context context, CreateBroadcastReceiverCallback cb, PushIntent intentAction) { this.context = context; + this.cb = cb; + this.intentAction = intentAction; } @Override - public void onListen(Object arguments, EventSink events) { - tokenEventBroadcastReceiver = createTokenEventBroadcastReceiver(events); - context.registerReceiver(tokenEventBroadcastReceiver, - new IntentFilter(PushIntent.TOKEN_INTENT_ACTION.id())); + public void onListen(Object arguments, EventChannel.EventSink events) { + broadcastReceiver = cb.createBroadcastReceiver(events); + context.registerReceiver(broadcastReceiver, new IntentFilter(intentAction.id())); } @Override public void onCancel(Object arguments) { - context.unregisterReceiver(tokenEventBroadcastReceiver); - } - - private BroadcastReceiver createTokenEventBroadcastReceiver(final EventSink events) { - return new TokenReceiver(events); + context.unregisterReceiver(broadcastReceiver); } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/local/LocalNotificationClickStreamHandler.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/local/LocalNotificationClickStreamHandler.java deleted file mode 100644 index 5da4d523..00000000 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/local/LocalNotificationClickStreamHandler.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License") - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package com.huawei.hms.flutter.push.event.local; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.IntentFilter; - -import com.huawei.hms.flutter.push.constants.PushIntent; -import com.huawei.hms.flutter.push.receiver.local.LocalNotificationClickEventReceiver; - -import io.flutter.plugin.common.EventChannel; - -/** - * Handles local notification button click events - **/ -public class LocalNotificationClickStreamHandler implements EventChannel.StreamHandler { - private Context context; - private BroadcastReceiver localNotificationClickEventReceiver; - - public LocalNotificationClickStreamHandler(Context ctx) { - this.context = ctx; - } - - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - localNotificationClickEventReceiver = createClickEventReceiver(events); - context.registerReceiver(localNotificationClickEventReceiver, - new IntentFilter(PushIntent.LOCAL_NOTIFICATION_CLICK_ACTION.id())); - } - - @Override - public void onCancel(Object arguments) { - context.unregisterReceiver(localNotificationClickEventReceiver); - } - - private BroadcastReceiver createClickEventReceiver(final EventChannel.EventSink events) { - return new LocalNotificationClickEventReceiver(events); - } - -} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/local/LocalNotificationOpenStreamHandler.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/local/LocalNotificationOpenStreamHandler.java deleted file mode 100644 index db27f700..00000000 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/local/LocalNotificationOpenStreamHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License") - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package com.huawei.hms.flutter.push.event.local; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.IntentFilter; - -import com.huawei.hms.flutter.push.constants.PushIntent; -import com.huawei.hms.flutter.push.receiver.common.NotificationOpenEventReceiver; - -import io.flutter.plugin.common.EventChannel; - -/** - * class LocalNotificationOpenStreamHandler - * - * Description: Handles local notification open events - * - * @since 5.0.2 - **/ -public class LocalNotificationOpenStreamHandler implements EventChannel.StreamHandler { - private Context context; - private BroadcastReceiver localNotificationOpenEventReceiver; - - public LocalNotificationOpenStreamHandler(Context ctx) { - this.context = ctx; - } - - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - localNotificationOpenEventReceiver = createOpenEventReceiver(events); - context.registerReceiver(localNotificationOpenEventReceiver, - new IntentFilter(PushIntent.NOTIFICATION_OPEN_ACTION.id())); - } - - @Override - public void onCancel(Object arguments) { - context.unregisterReceiver(localNotificationOpenEventReceiver); - } - - private BroadcastReceiver createOpenEventReceiver(final EventChannel.EventSink events) { - return new NotificationOpenEventReceiver(events); - } - -} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/remote/RemoteMessageCustomIntentStreamHandler.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/remote/RemoteMessageCustomIntentStreamHandler.java deleted file mode 100644 index 57b7db00..00000000 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/remote/RemoteMessageCustomIntentStreamHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License") - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package com.huawei.hms.flutter.push.event.remote; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.IntentFilter; - -import com.huawei.hms.flutter.push.constants.PushIntent; -import com.huawei.hms.flutter.push.receiver.remote.RemoteMessageNotificationIntentReceiver; - -import io.flutter.plugin.common.EventChannel; - -public class RemoteMessageCustomIntentStreamHandler implements EventChannel.StreamHandler { - private Context context; - private BroadcastReceiver rmNotificationIntentBroadcastReceiver; - - public RemoteMessageCustomIntentStreamHandler(Context ctx) { - this.context = ctx; - } - - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - rmNotificationIntentBroadcastReceiver = createRemoteMessageEventBroadcastReceiver(events); - context.registerReceiver(rmNotificationIntentBroadcastReceiver, - new IntentFilter(PushIntent.REMOTE_MESSAGE_NOTIFICATION_INTENT_ACTION.id())); - } - - @Override - public void onCancel(Object arguments) { - context.unregisterReceiver(rmNotificationIntentBroadcastReceiver); - } - - private BroadcastReceiver createRemoteMessageEventBroadcastReceiver(final EventChannel.EventSink events) { - return new RemoteMessageNotificationIntentReceiver(events); - } - -} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/remote/RemoteMessageSentDeliveredStreamHandler.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/remote/RemoteMessageSentDeliveredStreamHandler.java deleted file mode 100644 index 0d42d5fe..00000000 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/event/remote/RemoteMessageSentDeliveredStreamHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License") - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package com.huawei.hms.flutter.push.event.remote; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.IntentFilter; - -import com.huawei.hms.flutter.push.constants.PushIntent; -import com.huawei.hms.flutter.push.receiver.remote.RemoteMessageSentDeliveredReceiver; - -import io.flutter.plugin.common.EventChannel; -import io.flutter.plugin.common.EventChannel.StreamHandler; - -public class RemoteMessageSentDeliveredStreamHandler implements StreamHandler { - private Context context; - private BroadcastReceiver remoteMsgSentDeliveredEventBroadcastListener; - - public RemoteMessageSentDeliveredStreamHandler(Context ctx) { - this.context = ctx; - } - - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - remoteMsgSentDeliveredEventBroadcastListener = createRemoteMessageEventBroadcastReceiver(events); - context.registerReceiver(remoteMsgSentDeliveredEventBroadcastListener, - new IntentFilter(PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION.id())); - } - - @Override - public void onCancel(Object arguments) { - context.unregisterReceiver(remoteMsgSentDeliveredEventBroadcastListener); - } - - private BroadcastReceiver createRemoteMessageEventBroadcastReceiver(final EventChannel.EventSink events) { - return new RemoteMessageSentDeliveredReceiver(events); - } - -} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsInstanceId.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsInstanceId.java index 4fd66fbc..e5fd7a01 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsInstanceId.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsInstanceId.java @@ -16,22 +16,23 @@ package com.huawei.hms.flutter.push.hms; +import android.content.Context; import android.util.Log; import com.huawei.agconnect.config.AGConnectServicesConfig; +import com.huawei.hmf.tasks.Task; +import com.huawei.hms.aaid.HmsInstanceId; +import com.huawei.hms.aaid.entity.AAIDResult; +import com.huawei.hms.common.ApiException; import com.huawei.hms.flutter.push.constants.Code; import com.huawei.hms.flutter.push.constants.Core; import com.huawei.hms.flutter.push.constants.PushIntent; -import com.huawei.hmf.tasks.Task; -import com.huawei.hms.aaid.entity.AAIDResult; -import com.huawei.hms.aaid.HmsInstanceId; +import com.huawei.hms.flutter.push.logger.HMSLogger; +import com.huawei.hms.flutter.push.utils.Utils; import io.flutter.plugin.common.MethodChannel.Result; -import com.huawei.hms.flutter.push.PushPlugin; -import com.huawei.hms.flutter.push.logger.HMSLogger; -import com.huawei.hms.flutter.push.utils.Utils; -import com.huawei.hms.common.ApiException; +import org.json.JSONObject; import java.util.HashMap; import java.util.Map; @@ -42,47 +43,58 @@ * @since 4.0.4 */ public class FlutterHmsInstanceId { - private static String TAG = FlutterHmsInstanceId.class.getSimpleName(); + private static final String TAG = FlutterHmsInstanceId.class.getSimpleName(); + + private HMSLogger hmsLogger; - private static HMSLogger hmsLogger = HMSLogger.getInstance(PushPlugin.getContext()); + private Context context; - public static void getId(final Result result) { + public FlutterHmsInstanceId(Context context) { + this.context = context; + hmsLogger = HMSLogger.getInstance(context); + } + + public void getId(final Result result) { hmsLogger.startMethodExecutionTimer("getId"); - String instanceId = HmsInstanceId.getInstance(PushPlugin.getContext()).getId(); + String instanceId = HmsInstanceId.getInstance(context).getId(); hmsLogger.sendSingleEvent("getId"); - Log.d(TAG, "id"); result.success(instanceId); } - public static void getAAID(final Result result) { + public void getAAID(final Result result) { hmsLogger.startMethodExecutionTimer("getAAID"); - Task aaidResultTask = HmsInstanceId.getInstance(PushPlugin.getContext()).getAAID(); + Task aaidResultTask = HmsInstanceId.getInstance(context).getAAID(); aaidResultTask.addOnSuccessListener(aaidResult -> { String aaid = aaidResult.getId(); hmsLogger.sendSingleEvent("getAAID"); - Log.d(TAG, "aaid"); result.success(aaid); }).addOnFailureListener(e -> { if (e instanceof ApiException) { ApiException ex = ((ApiException) e); + result.error(String.valueOf(ex.getStatusCode()), ex.getMessage(), null); hmsLogger.sendSingleEvent("getAAID", String.valueOf(ex.getStatusCode())); } else { + result.error("-1", e.getMessage(), null); hmsLogger.sendSingleEvent("getAAID", Code.RESULT_UNKNOWN.code()); } Log.d("FlutterHmsInstanceId", "getAAID failed"); }); } - public static void getAppId(final Result result) { - String appId = AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString(Core.CLIENT_APP_ID); - if (Utils.isEmpty(appId)) appId = ""; + public void getAppId(final Result result) { + String appId = AGConnectServicesConfig.fromContext(context).getString(Core.CLIENT_APP_ID); + if (Utils.isEmpty(appId)) { + appId = ""; + } result.success(appId); } - public static void getToken(final String scope) { + public void getToken(final String scope) { new Thread(() -> { - String appId = AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString(Core.CLIENT_APP_ID); - if (Utils.isEmpty(appId)) appId = ""; + String appId = AGConnectServicesConfig.fromContext(context).getString(Core.CLIENT_APP_ID); + if (Utils.isEmpty(appId)) { + appId = ""; + } String token = ""; hmsLogger.startMethodExecutionTimer("getToken"); try { @@ -90,74 +102,113 @@ public static void getToken(final String scope) { if (defaultScope.trim().isEmpty()) { defaultScope = Core.DEFAULT_TOKEN_SCOPE; } - token = HmsInstanceId.getInstance(PushPlugin.getContext()).getToken(appId, defaultScope); + token = HmsInstanceId.getInstance(context).getToken(appId, defaultScope); hmsLogger.sendSingleEvent("getToken"); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN, token); + Utils.sendIntent(context, PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN, token); } catch (ApiException e) { hmsLogger.sendSingleEvent("getToken", String.valueOf(e.getStatusCode())); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, e.getLocalizedMessage()); + Utils.sendIntent(context, PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, + e.getLocalizedMessage()); } catch (Exception e) { hmsLogger.sendSingleEvent("getToken", Code.RESULT_UNKNOWN.code()); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, e.getLocalizedMessage()); + Utils.sendIntent(context, PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, + e.getLocalizedMessage()); + } + }).start(); + } + + public void getMultiSenderToken(final String subjectId) { + new Thread(() -> { + String token = ""; + hmsLogger.startMethodExecutionTimer("getMultiSenderToken"); + try { + token = HmsInstanceId.getInstance(context).getToken(subjectId); + hmsLogger.sendSingleEvent("getMultiSenderToken"); + JSONObject result = new JSONObject(); + result.putOpt("multiSenderToken", token); + Utils.sendIntent(context, PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION, PushIntent.MULTI_SENDER_TOKEN, + result.toString()); + } catch (ApiException e) { + hmsLogger.sendSingleEvent("getMultiSenderToken", String.valueOf(e.getStatusCode())); + Utils.sendIntent(context, PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION, + PushIntent.MULTI_SENDER_TOKEN_ERROR, e.getLocalizedMessage()); + } catch (Exception e) { + hmsLogger.sendSingleEvent("getMultiSenderToken", Code.RESULT_UNKNOWN.code()); + Utils.sendIntent(context, PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION, + PushIntent.MULTI_SENDER_TOKEN_ERROR, e.getLocalizedMessage()); } }).start(); } - public static void getCreationTime(final Result result) { + public void getCreationTime(final Result result) { hmsLogger.startMethodExecutionTimer("getCreationTime"); - String createTime = String.valueOf(HmsInstanceId.getInstance(PushPlugin.getContext()).getCreationTime()); - Log.d(TAG, "createTime"); + String createTime = String.valueOf(HmsInstanceId.getInstance(context).getCreationTime()); hmsLogger.sendSingleEvent("getCreationTime"); result.success(createTime); } - public static void deleteAAID(final Result result) { - hmsLogger.startMethodExecutionTimer("deleteAAID"); - try { - HmsInstanceId.getInstance(PushPlugin.getContext()).deleteAAID(); - hmsLogger.sendSingleEvent("deleteAAID"); - } catch (ApiException e) { - result.error(Code.RESULT_UNKNOWN.code(), e.getMessage(), e.getCause()); - hmsLogger.sendSingleEvent("deleteAAID", String.valueOf(e.getStatusCode())); - } - result.success(Code.RESULT_SUCCESS.code()); + public void deleteAAID(final Result result) { + new Thread(() -> { + hmsLogger.startMethodExecutionTimer("deleteAAID"); + try { + HmsInstanceId.getInstance(context).deleteAAID(); + Utils.handleSuccessOnUIThread(result); + hmsLogger.sendSingleEvent("deleteAAID"); + } catch (ApiException e) { + Utils.handleErrorOnUIThread(result, String.valueOf(e.getStatusCode()), e.getMessage(), ""); + hmsLogger.sendSingleEvent("deleteAAID", String.valueOf(e.getStatusCode())); + } + }).start(); + } - public static void deleteToken(final String scope) { - // Since operation on main thread is prohibited for this method, results will be returned on - // token event channel's onError callback + public void deleteToken(final String scope, final Result result) { new Thread(() -> { - String appId = AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString(Core.CLIENT_APP_ID); - if (Utils.isEmpty(appId)) appId = ""; + String appId = AGConnectServicesConfig.fromContext(context).getString(Core.CLIENT_APP_ID); + if (Utils.isEmpty(appId)) { + appId = ""; + } hmsLogger.startMethodExecutionTimer("deleteToken"); try { String defaultScope = scope == null ? Core.DEFAULT_TOKEN_SCOPE : scope; if (defaultScope.trim().isEmpty()) { defaultScope = Core.DEFAULT_TOKEN_SCOPE; } - HmsInstanceId.getInstance(PushPlugin.getContext()).deleteToken(appId, defaultScope); + HmsInstanceId.getInstance(context).deleteToken(appId, defaultScope); hmsLogger.sendSingleEvent("deleteToken"); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, Code.RESULT_SUCCESS.code()); + Utils.handleSuccessOnUIThread(result); } catch (ApiException e) { hmsLogger.sendSingleEvent("deleteToken", String.valueOf(e.getStatusCode())); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, e.getLocalizedMessage()); - } catch (Exception e) { - hmsLogger.sendSingleEvent("deleteToken", Code.RESULT_UNKNOWN.code()); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, e.getLocalizedMessage()); + Utils.handleErrorOnUIThread(result, String.valueOf(e.getStatusCode()), e.getMessage(), ""); + } + }).start(); + } + + public void deleteMultiSenderToken(final String subjectId, final Result result) { + final String methodName = "deleteMultiSenderToken"; + new Thread(() -> { + hmsLogger.startMethodExecutionTimer(methodName); + try { + HmsInstanceId.getInstance(context).deleteToken(subjectId); + hmsLogger.sendSingleEvent(methodName); + Utils.handleSuccessOnUIThread(result); + } catch (ApiException e) { + hmsLogger.sendSingleEvent(methodName, String.valueOf(e.getStatusCode())); + Utils.handleErrorOnUIThread(result, String.valueOf(e.getStatusCode()), e.getMessage(), ""); } }).start(); } - public static void getAgConnectValues(final Result result) { + public void getAgConnectValues(final Result result) { HashMap agconnect = new HashMap<>(); - agconnect.put("app_id", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("client/app_id")); - agconnect.put("cp_id", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("client/cp_id")); - agconnect.put("client_id", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("client/client_id")); - agconnect.put("product_id", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("client/product_id")); - agconnect.put("package_name", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("client/package_name")); - agconnect.put("api_key", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("client/api_key")); - agconnect.put("client_secret", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("client/client_secret")); - agconnect.put("agcw_url", AGConnectServicesConfig.fromContext(PushPlugin.getContext()).getString("agcgw/url")); + agconnect.put("app_id", AGConnectServicesConfig.fromContext(context).getString("client/app_id")); + agconnect.put("cp_id", AGConnectServicesConfig.fromContext(context).getString("client/cp_id")); + agconnect.put("client_id", AGConnectServicesConfig.fromContext(context).getString("client/client_id")); + agconnect.put("product_id", AGConnectServicesConfig.fromContext(context).getString("client/product_id")); + agconnect.put("package_name", AGConnectServicesConfig.fromContext(context).getString("client/package_name")); + agconnect.put("api_key", AGConnectServicesConfig.fromContext(context).getString("client/api_key")); + agconnect.put("client_secret", AGConnectServicesConfig.fromContext(context).getString("client/client_secret")); + agconnect.put("agcw_url", AGConnectServicesConfig.fromContext(context).getString("agcgw/url")); StringBuilder sb = new StringBuilder(); for (Map.Entry entry : agconnect.entrySet()) { diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessageService.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessageService.java index 8f37d9cd..e7b20336 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessageService.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessageService.java @@ -18,20 +18,22 @@ import android.content.Context; import android.content.Intent; +import android.os.Bundle; import android.util.Log; -import com.huawei.hms.flutter.push.PushPlugin; import com.huawei.hms.flutter.push.constants.Param; +import com.huawei.hms.flutter.push.constants.PushIntent; import com.huawei.hms.flutter.push.logger.HMSLogger; import com.huawei.hms.flutter.push.receiver.BackgroundMessageBroadcastReceiver; -import com.huawei.hms.flutter.push.constants.PushIntent; import com.huawei.hms.flutter.push.utils.ApplicationUtils; +import com.huawei.hms.flutter.push.utils.MapUtils; import com.huawei.hms.flutter.push.utils.RemoteMessageUtils; import com.huawei.hms.flutter.push.utils.Utils; import com.huawei.hms.push.HmsMessageService; import com.huawei.hms.push.RemoteMessage; import com.huawei.hms.push.SendException; +import org.json.JSONException; import org.json.JSONObject; /** @@ -45,19 +47,65 @@ public class FlutterHmsMessageService extends HmsMessageService { @Override public void onNewToken(String token) { super.onNewToken(token); - if (PushPlugin.getContext() != null) { - HMSLogger.getInstance(PushPlugin.getContext()).sendPeriodicEvent("onNewToken"); + if (PluginContext.getContext() != null) { + HMSLogger.getInstance(PluginContext.getContext()).sendPeriodicEvent("onNewToken"); Log.d(TAG, "Token received"); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN, token); + Utils.sendIntent(PluginContext.getContext(), PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN, token); + } + } + + /** + * Called when the token is obtained from the Push Kit server through the getToken(String subjectId) method of + * HmsInstanceId in the multi-sender scenario. + * Bundle contains some extra return data, which can be obtained through key values such as HmsMessageService.SUBJECT_ID. + * + * @param token Token returned by the HMS Core Push SDK. + * @param bundle Other data returned by the Push SDK except tokens. + */ + @Override + public void onNewToken(String token, Bundle bundle) { + super.onNewToken(token, bundle); + if (PluginContext.getContext() != null) { + HMSLogger.getInstance(PluginContext.getContext()).sendPeriodicEvent("onMultiSenderNewToken"); + Log.d(TAG, "Multi-Sender Token received"); + JSONObject result = new JSONObject(); + try { + result.put("multiSenderToken", token); + result.put("bundle", MapUtils.bundleToMap(bundle)); + Utils.sendIntent(PluginContext.getContext(), PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION, + PushIntent.MULTI_SENDER_TOKEN, result.toString()); + } catch (JSONException e) { + Utils.sendIntent(PluginContext.getContext(), PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION, + PushIntent.MULTI_SENDER_TOKEN_ERROR, e.getMessage()); + } } } @Override public void onTokenError(Exception e) { super.onTokenError(e); - if (PushPlugin.getContext() != null) { - HMSLogger.getInstance(PushPlugin.getContext()).sendPeriodicEvent("onTokenError"); - Utils.sendIntent(PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, "Token Error: " + e.getMessage()); + if (PluginContext.getContext() != null) { + HMSLogger.getInstance(PluginContext.getContext()).sendPeriodicEvent("onTokenError"); + Utils.sendIntent(PluginContext.getContext(), PushIntent.TOKEN_INTENT_ACTION, PushIntent.TOKEN_ERROR, + "Token Error: " + e.getMessage()); + } + } + + /** + * Called when applying for a token fails from the Push Kit server through the getToken(String subjectId) method of + * HmsInstanceId in the multi-sender scenario. + * + * @param e Exception of the BaseException type, which is returned when the app fails to call the getToken method to apply for a token. + * @param bundle Other data returned by the Push SDK except tokens. + */ + @Override + public void onTokenError(Exception e, Bundle bundle) { + super.onTokenError(e, bundle); + if (PluginContext.getContext() != null) { + HMSLogger.getInstance(PluginContext.getContext()).sendPeriodicEvent("onMultiSenderTokenError"); + Utils.sendIntent(PluginContext.getContext(), PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION, + PushIntent.MULTI_SENDER_TOKEN_ERROR, + "Token Error: " + e.getMessage() + "Bundle: " + MapUtils.bundleToMap(bundle).toString()); } } @@ -71,64 +119,65 @@ public void onTokenError(Exception e) { public void onMessageReceived(RemoteMessage remoteMessage) { super.onMessageReceived(remoteMessage); - Context context = getApplicationContext(); - boolean isApplicationInForeground = ApplicationUtils.isApplicationInForeground(context); + Context applicationContext = getApplicationContext(); + boolean isApplicationInForeground = ApplicationUtils.isApplicationInForeground(applicationContext); if (isApplicationInForeground) { - HMSLogger.getInstance(PushPlugin.getContext()).sendPeriodicEvent("onMessageReceived"); + HMSLogger.getInstance(PluginContext.getContext()).sendPeriodicEvent("onMessageReceived"); if (remoteMessage != null) { JSONObject jsonObject = new JSONObject(RemoteMessageUtils.toMap(remoteMessage)); - Utils.sendIntent(PushIntent.DATA_MESSAGE_INTENT_ACTION, PushIntent.DATA_MESSAGE, jsonObject.toString()); + Utils.sendIntent(PluginContext.getContext(), PushIntent.REMOTE_DATA_MESSAGE_INTENT_ACTION, + PushIntent.DATA_MESSAGE, jsonObject.toString()); } } else { - HMSLogger.getInstance(context).sendPeriodicEvent("onMessageReceived"); - Intent intent = new Intent(context, BackgroundMessageBroadcastReceiver.class); + HMSLogger.getInstance(applicationContext).sendPeriodicEvent("onMessageReceived"); + Intent intent = new Intent(applicationContext, BackgroundMessageBroadcastReceiver.class); intent.setAction(BackgroundMessageBroadcastReceiver.BACKGROUND_REMOTE_MESSAGE); intent.putExtra(Param.MESSAGE.code(), remoteMessage); - context.sendBroadcast(intent); - + applicationContext.sendBroadcast(intent); } - } @Override public void onMessageSent(String msgID) { super.onMessageSent(msgID); - HMSLogger.getInstance(PushPlugin.getContext()).sendSingleEvent("onMessageSent"); + HMSLogger.getInstance(PluginContext.getContext()).sendSingleEvent("onMessageSent"); Log.d(TAG, "RemoteMessage sent successfully"); - Utils.sendIntent(PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, PushIntent.REMOTE_MESSAGE, - "Sent Remote message with id: " + msgID); + Utils.sendIntent(PluginContext.getContext(), PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, + PushIntent.REMOTE_MESSAGE, "Sent Remote message with id: " + msgID); } @Override public void onSendError(String msgId, Exception e) { super.onSendError(msgId, e); - HMSLogger.getInstance(PushPlugin.getContext()).sendSingleEvent("onSendError"); + HMSLogger.getInstance(PluginContext.getContext()).sendSingleEvent("onSendError"); int errCode = ((SendException) e).getErrorCode(); String errInfo = e.getMessage(); Log.d(TAG, "RemoteMessage sent error, msgid: " + msgId + ", exception: " + e.getMessage()); - Utils.sendIntent(PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, PushIntent.REMOTE_MESSAGE_ERROR, + Utils.sendIntent(PluginContext.getContext(), PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, + PushIntent.REMOTE_MESSAGE_ERROR, "onSendError for msgId: " + msgId + ", Error Code: " + errCode + ", Error Info: " + errInfo); } @Override public void onMessageDelivered(String msgId, Exception e) { super.onMessageDelivered(msgId, e); - HMSLogger.getInstance(PushPlugin.getContext()).sendSingleEvent("onMessageDelivered"); + HMSLogger.getInstance(PluginContext.getContext()).sendSingleEvent("onMessageDelivered"); if (e == null) { Log.d(TAG, "RemoteMessage delivered successfully"); - Utils.sendIntent(PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, PushIntent.REMOTE_MESSAGE, - "Delivered remote message with id: " + msgId); + Utils.sendIntent(PluginContext.getContext(), PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, + PushIntent.REMOTE_MESSAGE, "Delivered remote message with id: " + msgId); } else { int errCode = ((SendException) e).getErrorCode(); if (errCode == 0) { // 0 => RESULT_SUCCESS Log.d(TAG, "RemoteMessage delivered successfully"); - Utils.sendIntent(PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, PushIntent.REMOTE_MESSAGE, - "Delivered remote message with id: " + msgId); + Utils.sendIntent(PluginContext.getContext(), PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, + PushIntent.REMOTE_MESSAGE, "Delivered remote message with id: " + msgId); } else { Log.d(TAG, "RemoteMessage deliver error, msgid " + msgId + ", exception " + e.getMessage() + ", code " + errCode); - Utils.sendIntent(PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, PushIntent.REMOTE_MESSAGE, + Utils.sendIntent(PluginContext.getContext(), PushIntent.REMOTE_MESSAGE_SENT_DELIVERED_ACTION, + PushIntent.REMOTE_MESSAGE, "RemoteMessage deliver error, msgid " + msgId + ", exception " + e.getMessage() + ", code " + errCode); } @@ -138,7 +187,7 @@ public void onMessageDelivered(String msgId, Exception e) { @Override public void onDeletedMessages() { super.onDeletedMessages(); - HMSLogger.getInstance(PushPlugin.getContext()).sendPeriodicEvent("onDeletedMessages"); + HMSLogger.getInstance(PluginContext.getContext()).sendPeriodicEvent("onDeletedMessages"); Log.d(TAG, "onDeletedMessages"); } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessaging.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessaging.java index 690ab85f..b0360b08 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessaging.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsMessaging.java @@ -16,7 +16,10 @@ package com.huawei.hms.flutter.push.hms; -import com.huawei.hms.flutter.push.PushPlugin; +import android.content.Context; + +import androidx.annotation.NonNull; + import com.huawei.hms.flutter.push.constants.Code; import com.huawei.hms.flutter.push.logger.HMSLogger; import com.huawei.hms.flutter.push.utils.RemoteMessageUtils; @@ -34,103 +37,103 @@ */ public class FlutterHmsMessaging { - private static HMSLogger hmsLogger = HMSLogger.getInstance(PushPlugin.getContext()); + private HMSLogger hmsLogger; - public static void turnOnPush(final Result result) { + private Context context; + + public FlutterHmsMessaging(@NonNull Context context) { + this.context = context; + hmsLogger = HMSLogger.getInstance(context); + } + + public void turnOnPush(final Result result) { try { hmsLogger.startMethodExecutionTimer("turnOnPush"); - HmsMessaging.getInstance(PushPlugin.getContext()).turnOnPush().addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - hmsLogger.sendSingleEvent("turnOnPush"); - result.success(Code.RESULT_SUCCESS.code()); - } else { - hmsLogger.sendSingleEvent("turnOnPush", Code.RESULT_UNKNOWN.code()); - result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), - task.getException().getCause()); - } - }); + HmsMessaging.getInstance(context).turnOnPush().addOnCompleteListener(task -> { + if (task.isSuccessful()) { + hmsLogger.sendSingleEvent("turnOnPush"); + result.success(Code.RESULT_SUCCESS.code()); + } else { + hmsLogger.sendSingleEvent("turnOnPush", Code.RESULT_UNKNOWN.code()); + result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), + task.getException().getCause()); + } + }); } catch (Exception e) { hmsLogger.sendSingleEvent("turnOnPush", Code.RESULT_UNKNOWN.code()); result.error(Code.RESULT_UNKNOWN.code(), e.getMessage(), e.getCause()); } } - public static void turnOffPush(final Result result) { + public void turnOffPush(final Result result) { try { hmsLogger.startMethodExecutionTimer("turnOffPush"); - HmsMessaging.getInstance(PushPlugin.getContext()).turnOffPush().addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - hmsLogger.sendSingleEvent("turnOffPush"); - result.success(Code.RESULT_SUCCESS.code()); - } else { - hmsLogger.sendSingleEvent("turnOffPush", Code.RESULT_UNKNOWN.code()); - result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), - task.getException().getCause()); - } + HmsMessaging.getInstance(context).turnOffPush().addOnCompleteListener(task -> { + if (task.isSuccessful()) { + hmsLogger.sendSingleEvent("turnOffPush"); + result.success(Code.RESULT_SUCCESS.code()); + } else { + hmsLogger.sendSingleEvent("turnOffPush", Code.RESULT_UNKNOWN.code()); + result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), + task.getException().getCause()); } - ); + }); } catch (Exception e) { hmsLogger.sendSingleEvent("turnOffPush", Code.RESULT_UNKNOWN.code()); result.error(Code.RESULT_UNKNOWN.code(), e.getMessage(), e.getCause()); } } - public static void subscribe(String topic, final Result result) { + public void subscribe(String topic, final Result result) { if (Utils.isEmpty(topic)) { result.error(Code.ERROR_INVALID_PARAMETERS.code(), "topic is empty!", "topic is empty!"); return; } try { hmsLogger.startMethodExecutionTimer("subscribe"); - HmsMessaging.getInstance(PushPlugin.getContext()).subscribe(topic).addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - hmsLogger.sendSingleEvent("subscribe"); - result.success(Code.RESULT_SUCCESS.code()); - } else { - hmsLogger.sendSingleEvent("subscribe", Code.RESULT_UNKNOWN.code()); - result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), - task.getException().getCause()); - } + HmsMessaging.getInstance(context).subscribe(topic).addOnCompleteListener(task -> { + if (task.isSuccessful()) { + hmsLogger.sendSingleEvent("subscribe"); + result.success(Code.RESULT_SUCCESS.code()); + } else { + hmsLogger.sendSingleEvent("subscribe", Code.RESULT_UNKNOWN.code()); + result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), + task.getException().getCause()); } - ); + }); } catch (Exception e) { hmsLogger.sendSingleEvent("subscribe", Code.RESULT_UNKNOWN.code()); result.error(Code.RESULT_UNKNOWN.code(), e.getMessage(), e.getCause()); } } - public static void unsubscribe(String topic, final Result result) { + public void unsubscribe(String topic, final Result result) { if (Utils.isEmpty(topic)) { result.error(Code.ERROR_INVALID_PARAMETERS.code(), "topic is empty!", "topic is empty!"); return; } try { hmsLogger.startMethodExecutionTimer("unsubscribe"); - HmsMessaging.getInstance(PushPlugin.getContext()).unsubscribe(topic).addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - hmsLogger.sendSingleEvent("unsubscribe"); - result.success(Code.RESULT_SUCCESS.code()); - } else { - hmsLogger.sendSingleEvent("unsubscribe", Code.RESULT_UNKNOWN.code()); - result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), - task.getException().getCause()); - } - } - ); + HmsMessaging.getInstance(context).unsubscribe(topic).addOnCompleteListener(task -> { + if (task.isSuccessful()) { + hmsLogger.sendSingleEvent("unsubscribe"); + result.success(Code.RESULT_SUCCESS.code()); + } else { + hmsLogger.sendSingleEvent("unsubscribe", Code.RESULT_UNKNOWN.code()); + result.error(Code.RESULT_UNKNOWN.code(), task.getException().getMessage(), + task.getException().getCause()); + } + }); } catch (Exception e) { hmsLogger.sendSingleEvent("unsubscribe", Code.RESULT_UNKNOWN.code()); result.error(Code.RESULT_UNKNOWN.code(), e.getMessage(), e.getCause()); } } - public static void setAutoInitEnabled(boolean enabled, final Result result) { + public void setAutoInitEnabled(boolean enabled, final Result result) { try { hmsLogger.startMethodExecutionTimer("setAutoInitEnabled"); - HmsMessaging.getInstance(PushPlugin.getContext()).setAutoInitEnabled(enabled); + HmsMessaging.getInstance(context).setAutoInitEnabled(enabled); hmsLogger.sendSingleEvent("setAutoInitEnabled"); result.success(Code.RESULT_SUCCESS.code()); } catch (Exception e) { @@ -139,10 +142,10 @@ public static void setAutoInitEnabled(boolean enabled, final Result result) { } } - public static void isAutoInitEnabled(final Result result) { + public void isAutoInitEnabled(final Result result) { try { hmsLogger.startMethodExecutionTimer("isAutoInitEnabled"); - String autoInit = String.valueOf(HmsMessaging.getInstance(PushPlugin.getContext()).isAutoInitEnabled()); + String autoInit = String.valueOf(HmsMessaging.getInstance(context).isAutoInitEnabled()); hmsLogger.sendSingleEvent("isAutoInitEnabled"); boolean val = Boolean.parseBoolean(autoInit); result.success(val); @@ -152,11 +155,11 @@ public static void isAutoInitEnabled(final Result result) { } } - public static void sendRemoteMessage(final Result result, MethodCall call) { + public void sendRemoteMessage(final Result result, MethodCall call) { try { hmsLogger.startMethodExecutionTimer("send"); RemoteMessage remoteMessage = RemoteMessageUtils.callArgsToRemoteMsg(call); - HmsMessaging.getInstance(PushPlugin.getContext()).send(remoteMessage); + HmsMessaging.getInstance(context).send(remoteMessage); hmsLogger.sendSingleEvent("send"); hmsLogger.startMethodExecutionTimer("onMessageSent"); hmsLogger.startMethodExecutionTimer("onSendError"); diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsOpenDevice.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsOpenDevice.java index a94d8f47..9ec4968a 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsOpenDevice.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsOpenDevice.java @@ -20,7 +20,6 @@ import com.huawei.hmf.tasks.Task; import com.huawei.hms.common.ApiException; -import com.huawei.hms.flutter.push.PushPlugin; import com.huawei.hms.flutter.push.constants.Code; import com.huawei.hms.flutter.push.logger.HMSLogger; import com.huawei.hms.opendevice.OpenDevice; @@ -29,22 +28,25 @@ import io.flutter.plugin.common.MethodChannel; public class FlutterHmsOpenDevice { + private FlutterHmsOpenDevice() { + } + public static void getOdid(final MethodChannel.Result result) { - HMSLogger.getInstance(PushPlugin.getContext()).startMethodExecutionTimer("getOdid"); - Task odidResultTask = OpenDevice.getOpenDeviceClient(PushPlugin.getContext()).getOdid(); + HMSLogger.getInstance(PluginContext.getContext()).startMethodExecutionTimer("getOdid"); + Task odidResultTask = OpenDevice.getOpenDeviceClient(PluginContext.getContext()).getOdid(); odidResultTask.addOnSuccessListener(ooidRes -> { String ooid = ooidRes.getId(); - HMSLogger.getInstance(PushPlugin.getContext()).sendSingleEvent("getOdid"); + HMSLogger.getInstance(PluginContext.getContext()).sendSingleEvent("getOdid"); Log.d("FlutterHmsInstanceId", "Odid"); result.success(ooid); }).addOnFailureListener(e -> { if (e instanceof ApiException) { ApiException apiException = (ApiException) e; - HMSLogger.getInstance(PushPlugin.getContext()) - .sendSingleEvent("getOdid", String.valueOf(apiException.getStatusCode())); + HMSLogger.getInstance(PluginContext.getContext()) + .sendSingleEvent("getOdid", String.valueOf(apiException.getStatusCode())); } else { - HMSLogger.getInstance(PushPlugin.getContext()) - .sendSingleEvent("getOdid", Code.RESULT_UNKNOWN.code()); + HMSLogger.getInstance(PluginContext.getContext()) + .sendSingleEvent("getOdid", Code.RESULT_UNKNOWN.code()); } Log.e("FlutterHmsOpenDevice", "getOdid failed. Error message: " + e.getMessage()); }); diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsProfile.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsProfile.java new file mode 100644 index 00000000..f32a0c6c --- /dev/null +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/FlutterHmsProfile.java @@ -0,0 +1,100 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.huawei.hms.flutter.push.hms; + +import android.content.Context; + +import com.huawei.hms.flutter.push.constants.Code; +import com.huawei.hms.flutter.push.logger.HMSLogger; +import com.huawei.hms.push.HmsProfile; + +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel.Result; + +import java.util.Objects; + +public class FlutterHmsProfile { + + private HmsProfile hmsProfile; + + private HMSLogger hmsLogger; + + public FlutterHmsProfile(Context context) { + hmsProfile = HmsProfile.getInstance(context); + hmsLogger = HMSLogger.getInstance(context); + } + + public void isSupportProfile(final Result result) { + result.success(hmsProfile.isSupportProfile()); + } + + public void addProfile(final MethodCall call, final Result result) { + final String methodName = "addProfile"; + hmsLogger.startMethodExecutionTimer(methodName); + int type = Objects.requireNonNull(call.argument("type")); + String profileId = call.argument("profileId"); + hmsProfile.addProfile(type, profileId).addOnSuccessListener(aVoid -> { + result.success(true); + hmsLogger.sendSingleEvent(methodName); + }).addOnFailureListener(e -> { + result.error(Code.RESULT_ERROR.code(), "AddProfile failed: " + e.getMessage(), null); + hmsLogger.sendSingleEvent(methodName, Code.RESULT_ERROR.code()); + }); + } + + public void addMultiSenderProfile(final MethodCall call, final Result result) { + final String methodName = "addMultiSenderProfile"; + hmsLogger.startMethodExecutionTimer(methodName); + String subjectId = call.argument("subjectId"); + int type = Objects.requireNonNull(call.argument("type")); + String profileId = call.argument("profileId"); + hmsProfile.addProfile(subjectId, type, profileId).addOnSuccessListener(aVoid -> { + result.success(true); + hmsLogger.sendSingleEvent(methodName); + }).addOnFailureListener(e -> { + result.error(Code.RESULT_ERROR.code(), "AddMultiSenderProfile failed: " + e.getMessage(), null); + hmsLogger.sendSingleEvent(methodName, Code.RESULT_ERROR.code()); + }); + } + + public void deleteProfile(final MethodCall call, final Result result) { + final String methodName = "deleteProfile"; + hmsLogger.startMethodExecutionTimer(methodName); + String profileId = call.argument("profileId"); + hmsProfile.deleteProfile(profileId).addOnSuccessListener(aVoid -> { + result.success(true); + hmsLogger.sendSingleEvent(methodName); + }).addOnFailureListener(e -> { + result.error(Code.RESULT_ERROR.code(), "DeleteProfile failed: " + e.getMessage(), null); + hmsLogger.sendSingleEvent(methodName, Code.RESULT_ERROR.code()); + }); + } + + public void deleteMultiSenderProfile(final MethodCall call, final Result result) { + final String methodName = "deleteMultiSenderProfile"; + hmsLogger.startMethodExecutionTimer(methodName); + String subjectId = call.argument("subjectId"); + String profileId = call.argument("profileId"); + hmsProfile.deleteProfile(subjectId, profileId).addOnSuccessListener(aVoid -> { + result.success(true); + hmsLogger.sendSingleEvent(methodName); + }).addOnFailureListener(e -> { + result.error(Code.RESULT_ERROR.code(), "DeleteMultiSenderProfile failed: " + e.getMessage(), null); + hmsLogger.sendSingleEvent(methodName, Code.RESULT_ERROR.code()); + }); + } +} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/PluginContext.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/PluginContext.java new file mode 100644 index 00000000..abddfb31 --- /dev/null +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/hms/PluginContext.java @@ -0,0 +1,38 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.huawei.hms.flutter.push.hms; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import java.lang.ref.WeakReference; + +public class PluginContext { + private static WeakReference weakReference; + + private PluginContext() { + } + + public static void initialize(@NonNull Context context) { + weakReference = new WeakReference<>(context); + } + + public static Context getContext() { + return weakReference.get(); + } +} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotification.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotification.java index 82136f36..39a0acdb 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotification.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotification.java @@ -24,15 +24,14 @@ import com.huawei.hms.flutter.push.receiver.common.NotificationIntentListener; import com.huawei.hms.flutter.push.utils.LocalNotificationUtils; import com.huawei.hms.flutter.push.utils.NotificationConfigUtils; -import com.huawei.hms.flutter.push.utils.RemoteMessageUtils; - -import java.util.ArrayList; -import java.util.HashMap; import io.flutter.Log; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel.Result; +import java.util.ArrayList; +import java.util.HashMap; + public class HmsLocalNotification { private static String TAG = HmsLocalNotification.class.getSimpleName(); @@ -44,7 +43,7 @@ public HmsLocalNotification(Context context) { } public void localNotification(MethodCall call, final Result result) { - Bundle bundle = LocalNotificationUtils.callArgsToBundle(call, result); + Bundle bundle = LocalNotificationUtils.callArgsToBundle(call); if (bundle == null) { result.error(Code.NULL_BUNDLE.code(), "Arguments are wrong or empty", ""); return; @@ -54,13 +53,17 @@ public void localNotification(MethodCall call, final Result result) { } public void localNotificationSchedule(MethodCall call, final Result result) { - Bundle bundle = LocalNotificationUtils.callArgsToBundle(call, result); + Bundle bundle = LocalNotificationUtils.callArgsToBundle(call); if (bundle == null) { result.error(Code.NULL_BUNDLE.code(), "Arguments are wrong or empty", ""); return; } NotificationConfigUtils.configId(bundle); - hmsLocalNotificationController.localNotificationSchedule(bundle, result); + String localNotif = hmsLocalNotificationController.localNotificationSchedule(bundle, result); + if (localNotif.isEmpty()) { + return; + } + result.success(localNotif); } public void getInitialNotification(final Result result) { diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotificationController.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotificationController.java index 81356340..967fda68 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotificationController.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/localnotification/HmsLocalNotificationController.java @@ -37,6 +37,7 @@ import androidx.annotation.RequiresApi; import androidx.core.app.NotificationCompat; +import com.huawei.hms.flutter.push.HeadlessPushPlugin; import com.huawei.hms.flutter.push.config.NotificationAttributes; import com.huawei.hms.flutter.push.constants.Code; import com.huawei.hms.flutter.push.constants.Core; @@ -48,6 +49,8 @@ import com.huawei.hms.flutter.push.utils.BundleUtils; import com.huawei.hms.flutter.push.utils.NotificationConfigUtils; +import io.flutter.plugin.common.MethodChannel; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -58,12 +61,11 @@ import java.util.List; import java.util.Map; -import io.flutter.plugin.common.MethodChannel; - public class HmsLocalNotificationController { private final String TAG = HmsLocalNotificationController.class.getSimpleName(); private Context context; + private final SharedPreferences sharedPreferences; public HmsLocalNotificationController(Context context) { @@ -98,26 +100,32 @@ public void createDefaultChannel() { Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); String channelId = Core.NOTIFICATION_CHANNEL_ID + "-" + importance; - createChannel(notificationManager, channelId, Core.NOTIFICATION_CHANNEL_NAME, - Core.NOTIFICATION_CHANNEL_DESC, soundUri, importance, new long[]{0, Core.DEFAULT_VIBRATE_DURATION}); + createChannel(notificationManager, channelId, Core.NOTIFICATION_CHANNEL_NAME, Core.NOTIFICATION_CHANNEL_DESC, + soundUri, importance, new long[] {0, Core.DEFAULT_VIBRATE_DURATION}); } - private void createChannel(NotificationManager notificationManager, String channelId, - String channelName, String channelDescription, Uri soundUri, int importance, long[] vibratePattern) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) + private void createChannel(NotificationManager notificationManager, String channelId, String channelName, + String channelDescription, Uri soundUri, int importance, long[] vibratePattern) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { return; - if (notificationManager == null) + } + if (notificationManager == null) { return; + } NotificationChannel notificationChannel = notificationManager.getNotificationChannel(channelId); - if (notificationChannel != null) return; + if (notificationChannel != null) { + return; + } - if (channelName == null) + if (channelName == null) { channelName = Core.NOTIFICATION_CHANNEL_NAME; + } - if (channelDescription == null) + if (channelDescription == null) { channelDescription = Core.NOTIFICATION_CHANNEL_DESC; + } notificationChannel = new NotificationChannel(channelId, channelName, importance); @@ -127,10 +135,8 @@ private void createChannel(NotificationManager notificationManager, String chann notificationChannel.setVibrationPattern(vibratePattern); if (soundUri != null) { - AudioAttributes audioAttributes = new AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setUsage(AudioAttributes.USAGE_NOTIFICATION) - .build(); + AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType( + AudioAttributes.CONTENT_TYPE_SONIFICATION).setUsage(AudioAttributes.USAGE_NOTIFICATION).build(); notificationChannel.setSound(soundUri, audioAttributes); } else { @@ -140,21 +146,23 @@ private void createChannel(NotificationManager notificationManager, String chann } public void localNotificationNow(final Bundle bundle, final MethodChannel.Result result) { - HmsLocalNotificationPicturesLoader notificationPicturesLoader = - new HmsLocalNotificationPicturesLoader((largeIconImage, bigPictureImage, res) -> - localNotificationNowPicture(bundle, largeIconImage, bigPictureImage, res)); + HmsLocalNotificationPicturesLoader notificationPicturesLoader = new HmsLocalNotificationPicturesLoader( + (largeIconImage, bigPictureImage, res) -> localNotificationNowPicture(bundle, largeIconImage, + bigPictureImage, res)); notificationPicturesLoader.setFlutterResult(result); - notificationPicturesLoader - .setLargeIconUrl(context, BundleUtils.get(bundle, NotificationConstants.LARGE_ICON_URL)); - notificationPicturesLoader - .setBigPictureUrl(context, BundleUtils.get(bundle, NotificationConstants.BIG_PICTURE_URL)); + notificationPicturesLoader.setLargeIconUrl(context, + BundleUtils.get(bundle, NotificationConstants.LARGE_ICON_URL)); + notificationPicturesLoader.setBigPictureUrl(context, + BundleUtils.get(bundle, NotificationConstants.BIG_PICTURE_URL)); } public void invokeApp(Bundle bundle) { String packageName = context.getPackageName(); Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName); - if (launchIntent == null) return; + if (launchIntent == null) { + return; + } try { String className = launchIntent.getComponent().getClassName(); @@ -174,30 +182,34 @@ public void invokeApp(Bundle bundle) { } } - public void checkRequiredParams(Bundle bundle, final MethodChannel.Result result, String type) { - if (getMainActivityClass() == null) { - if (result != null) + public boolean invalidRequiredParams(Bundle bundle, final MethodChannel.Result result, String type) { + if (result != null) { + if (getMainActivityClass() == null) { result.error(Code.RESULT_ERROR.code(), "No activity class", ""); - } - if (BundleUtils.get(bundle, NotificationConstants.MESSAGE) == null) { - if (result != null) + return true; + } + if (BundleUtils.get(bundle, NotificationConstants.MESSAGE) == null) { result.error(Code.RESULT_ERROR.code(), "Notification Message is required", ""); - } - if (BundleUtils.get(bundle, NotificationConstants.ID) == null) { - if (result != null) + return true; + } + if (BundleUtils.get(bundle, NotificationConstants.ID) == null) { result.error(Code.RESULT_ERROR.code(), "Notification ID is null", ""); - } - if (type.equals(Core.NotificationType.SCHEDULED)) { - if (BundleUtils.getD(bundle, NotificationConstants.FIRE_DATE) == 0) { - if (result != null) - result.error(Code.RESULT_ERROR.code(), "FireDate is null", ""); + return true; + } + if (type.equals(Core.NotificationType.SCHEDULED) + && BundleUtils.getD(bundle, NotificationConstants.FIRE_DATE) == 0) { + result.error(Code.RESULT_ERROR.code(), "FireDate is null", ""); + return true; } } + return false; } - public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, - Bitmap bigPictureBitmap, MethodChannel.Result result) { - checkRequiredParams(bundle, result, Core.NotificationType.NOW); + public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, Bitmap bigPictureBitmap, + MethodChannel.Result result) { + if (invalidRequiredParams(bundle, result, Core.NotificationType.NOW)) { + return; + } try { String title = NotificationConfigUtils.configTitle(bundle, context); int priority = NotificationConfigUtils.configPriority(bundle); @@ -206,14 +218,14 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, String channelId = Core.NOTIFICATION_CHANNEL_ID + "-" + importance; - NotificationCompat.Builder notification = new NotificationCompat.Builder(context, "") - .setChannelId(channelId) - .setContentTitle(title) - .setTicker(BundleUtils.get(bundle, NotificationConstants.TICKER)) - .setVisibility(visibility) - .setPriority(priority) - .setAutoCancel(BundleUtils.getB(bundle, NotificationConstants.AUTO_CANCEL, true)) - .setOnlyAlertOnce(BundleUtils.getB(bundle, NotificationConstants.ONLY_ALERT_ONCE, false)); + NotificationCompat.Builder notification = new NotificationCompat.Builder(context, "").setChannelId( + channelId) + .setContentTitle(title) + .setTicker(BundleUtils.get(bundle, NotificationConstants.TICKER)) + .setVisibility(visibility) + .setPriority(priority) + .setAutoCancel(BundleUtils.getB(bundle, NotificationConstants.AUTO_CANCEL, true)) + .setOnlyAlertOnce(BundleUtils.getB(bundle, NotificationConstants.ONLY_ALERT_ONCE, false)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { boolean showWhen = BundleUtils.getB(bundle, NotificationConstants.SHOW_WHEN, true); @@ -231,8 +243,8 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, notification.setGroup(group); } - if (BundleUtils.contains(bundle, NotificationConstants.GROUP_SUMMARY) || - BundleUtils.getB(bundle, NotificationConstants.GROUP_SUMMARY)) { + if (BundleUtils.contains(bundle, NotificationConstants.GROUP_SUMMARY) || BundleUtils.getB(bundle, + NotificationConstants.GROUP_SUMMARY)) { notification.setGroupSummary(BundleUtils.getB(bundle, NotificationConstants.GROUP_SUMMARY)); } } @@ -242,8 +254,9 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, String subText = BundleUtils.get(bundle, NotificationConstants.SUB_TEXT); - if (subText != null) + if (subText != null) { notification.setSubText(subText); + } String bigText = BundleUtils.get(bundle, NotificationConstants.BIG_TEXT); bigText = bigText == null ? message : bigText; @@ -264,10 +277,9 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, NotificationCompat.Style style; if (bigPictureBitmap != null) { - style = new NotificationCompat.BigPictureStyle() - .bigPicture(bigPictureBitmap) - .setBigContentTitle(title) - .setSummaryText(message); + style = new NotificationCompat.BigPictureStyle().bigPicture(bigPictureBitmap) + .setBigContentTitle(title) + .setSummaryText(message); } else { style = new NotificationCompat.BigTextStyle().bigText(bigText); } @@ -283,8 +295,8 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, Uri soundUri = null; - if (!BundleUtils.contains(bundle, NotificationConstants.PLAY_SOUND) || - BundleUtils.getB(bundle, NotificationConstants.PLAY_SOUND)) { + if (!BundleUtils.contains(bundle, NotificationConstants.PLAY_SOUND) || BundleUtils.getB(bundle, + NotificationConstants.PLAY_SOUND)) { soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); String soundName = BundleUtils.get(bundle, NotificationConstants.SOUND_NAME); @@ -292,7 +304,8 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, if (soundName != null) { if (!Core.Resource.DEFAULT.equalsIgnoreCase(soundName)) { int resId; - if (context.getResources().getIdentifier(soundName, Core.RAW, context.getPackageName()) == 0) { + if (context.getResources().getIdentifier(soundName, Core.RAW, context.getPackageName()) == 0 + && soundName.contains(".")) { soundName = soundName.substring(0, soundName.lastIndexOf('.')); } resId = context.getResources().getIdentifier(soundName, Core.RAW, context.getPackageName()); @@ -314,8 +327,8 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, notification.setSound(null); } - if (BundleUtils.contains(bundle, NotificationConstants.ONGOING) || - BundleUtils.getB(bundle, NotificationConstants.ONGOING)) { + if (BundleUtils.contains(bundle, NotificationConstants.ONGOING) || BundleUtils.getB(bundle, + NotificationConstants.ONGOING)) { notification.setOngoing(BundleUtils.getB(bundle, NotificationConstants.ONGOING)); } @@ -331,22 +344,24 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, int notificationID = Integer.parseInt(BundleUtils.get(bundle, NotificationConstants.ID)); PendingIntent pendingIntent = PendingIntent.getActivity(context, notificationID, intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT); NotificationManager notificationManager = notificationManager(); - long[] vibratePattern = new long[]{0}; + long[] vibratePattern = new long[] {0}; - if (!BundleUtils.contains(bundle, NotificationConstants.VIBRATE) || - BundleUtils.getB(bundle, NotificationConstants.VIBRATE)) { - long vibrateDuration = BundleUtils.contains(bundle, NotificationConstants.VIBRATE_DURATION) ? - BundleUtils.getL(bundle, NotificationConstants.VIBRATE_DURATION) : Core.DEFAULT_VIBRATE_DURATION; - if (vibrateDuration == 0) + if (!BundleUtils.contains(bundle, NotificationConstants.VIBRATE) || BundleUtils.getB(bundle, + NotificationConstants.VIBRATE)) { + long vibrateDuration = BundleUtils.contains(bundle, NotificationConstants.VIBRATE_DURATION) + ? BundleUtils.getL(bundle, NotificationConstants.VIBRATE_DURATION) + : Core.DEFAULT_VIBRATE_DURATION; + if (vibrateDuration == 0) { vibrateDuration = Core.DEFAULT_VIBRATE_DURATION; + } channelId = channelId + "-" + vibrateDuration; - vibratePattern = new long[]{0, vibrateDuration}; + vibratePattern = new long[] {0, vibrateDuration}; notification.setVibrate(vibratePattern); } @@ -367,19 +382,21 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, String channelName = BundleUtils.get(bundle, NotificationConstants.CHANNEL_NAME); String channelDescription = BundleUtils.get(bundle, NotificationConstants.CHANNEL_DESCRIPTION); - createChannel(notificationManager, channelId, channelName, channelDescription, - soundUri, importance, vibratePattern); + createChannel(notificationManager, channelId, channelName, channelDescription, soundUri, importance, + vibratePattern); notification.setChannelId(channelId); notification.setContentIntent(pendingIntent); JSONArray actionArr = null; try { - actionArr = BundleUtils.get(bundle, NotificationConstants.ACTIONS) != null ? - new JSONArray(BundleUtils.get(bundle, NotificationConstants.ACTIONS)) : null; + actionArr = BundleUtils.get(bundle, NotificationConstants.ACTIONS) != null ? new JSONArray( + BundleUtils.get(bundle, NotificationConstants.ACTIONS)) : null; } catch (Exception e) { - if (result != null) + if (result != null) { result.error(Code.RESULT_ERROR.code(), e.getMessage(), e.getCause()); + return; + } } if (actionArr != null) { @@ -402,11 +419,11 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, actionIntent.setPackage(context.getPackageName()); PendingIntent pendingActionIntent = PendingIntent.getBroadcast(context, notificationID, - actionIntent, PendingIntent.FLAG_UPDATE_CURRENT); + actionIntent, PendingIntent.FLAG_UPDATE_CURRENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - notification.addAction(new NotificationCompat.Action - .Builder(icon, action, pendingActionIntent).build()); + notification.addAction( + new NotificationCompat.Action.Builder(icon, action, pendingActionIntent).build()); } else { notification.addAction(icon, action, pendingActionIntent); } @@ -420,8 +437,8 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, editor.apply(); } - if (!(ApplicationUtils.isApplicationInForeground(context) && - BundleUtils.getB(bundle, NotificationConstants.DONT_NOTIFY_IN_FOREGROUND))) { + if (!(ApplicationUtils.isApplicationInForeground(context) && BundleUtils.getB(bundle, + NotificationConstants.DONT_NOTIFY_IN_FOREGROUND))) { Notification builtNotification = notification.build(); builtNotification.defaults |= Notification.DEFAULT_LIGHTS; @@ -441,22 +458,27 @@ public void localNotificationNowPicture(Bundle bundle, Bitmap largeIconBitmap, } this.localNotificationRepeat(bundle); } catch (NullPointerException | IllegalArgumentException | IllegalStateException e) { - if (result != null) + if (result != null) { result.error(Code.RESULT_ERROR.code(), e.getMessage(), e.getCause()); + } } } private void localNotificationRepeat(Bundle bundle) { long newFireDate = NotificationConfigUtils.configNextFireDate(bundle); - if (newFireDate == 0) return; + if (newFireDate == 0) { + return; + } bundle.putDouble(NotificationConstants.FIRE_DATE, newFireDate); this.localNotificationSchedule(bundle, null); } - public void localNotificationSchedule(Bundle bundle, MethodChannel.Result result) { - checkRequiredParams(bundle, result, Core.NotificationType.SCHEDULED); + public String localNotificationSchedule(Bundle bundle, MethodChannel.Result result) { + if (invalidRequiredParams(bundle, result, Core.NotificationType.SCHEDULED)) { + return ""; + } NotificationAttributes notificationAttributes = new NotificationAttributes(bundle); String id = notificationAttributes.getId(); @@ -467,8 +489,7 @@ public void localNotificationSchedule(Bundle bundle, MethodChannel.Result result localNotificationScheduleSetAlarm(bundle); - if (result != null) - result.success(new NotificationAttributes(bundle).toJson().toString()); + return new NotificationAttributes(bundle).toJson().toString(); } public void localNotificationScheduleSetAlarm(Bundle bundle) { @@ -481,7 +502,9 @@ public void localNotificationScheduleSetAlarm(Bundle bundle) { PendingIntent pendingIntent = buildScheduleNotificationIntent(bundle); - if (pendingIntent == null) return; + if (pendingIntent == null) { + return; + } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { getAlarmManager().set(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent); @@ -515,13 +538,16 @@ public boolean isChannelBlocked(String channelId) { return false; } - if (channelId == null) return false; + if (channelId == null) { + return false; + } try { NotificationChannel channel = notificationManager().getNotificationChannel(channelId); - if (channel == null) + if (channel == null) { return false; + } return NotificationManager.IMPORTANCE_NONE == channel.getImportance(); } catch (Exception e) { @@ -554,8 +580,8 @@ public void deleteChannel(String channelId, MethodChannel.Result result) { result.success(Code.RESULT_SUCCESS.code()); } catch (Exception e) { Log.e(TAG, Code.RESULT_ERROR.code(), e); - result.error(Code.RESULT_ERROR.code(), - "Exception on deleting the channel, message: " + e.getMessage(), e.getStackTrace()); + result.error(Code.RESULT_ERROR.code(), "Exception on deleting the channel, message: " + e.getMessage(), + e.getStackTrace()); } } @@ -608,6 +634,10 @@ public ArrayList getScheduledNotifications() { for (Map.Entry entry : scheduledNotifications.entrySet()) { try { + if (entry.getKey().equals(HeadlessPushPlugin.KEY_CALLBACK) || entry.getKey() + .equals(HeadlessPushPlugin.KEY_HANDLER)) { + continue; + } NotificationAttributes notification = NotificationAttributes.fromJson(entry.getValue().toString()); scheduledNotificationList.add(notification.toJson().toString()); } catch (JSONException e) { @@ -632,7 +662,9 @@ public void cancelNotification(String tag, int id) { public void cancelNotificationsWithId(ArrayList ids) { for (int idx = 0; idx < ids.size(); idx++) { Integer id = ids.get(idx); - if (id != null) cancelNotification(id); + if (id != null) { + cancelNotification(id); + } } } @@ -640,7 +672,9 @@ public void cancelNotificationsWithIdTag(HashMap idTags) { for (Map.Entry entry : idTags.entrySet()) { Integer id = entry.getKey(); String tag = entry.getValue(); - if (tag != null) cancelNotification(tag, id); + if (tag != null) { + cancelNotification(tag, id); + } } } @@ -657,7 +691,9 @@ public void cancelNotificationsWithTag(String tag) { public void cancelScheduledNotifications() { for (String id : sharedPreferences.getAll().keySet()) { - cancelScheduledNotification(id); + if (!id.equals(HeadlessPushPlugin.KEY_CALLBACK) && !id.equals(HeadlessPushPlugin.KEY_HANDLER)) { + cancelScheduledNotification(id); + } } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/logger/HMSLogger.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/logger/HMSLogger.java index f1eac9b6..94b8da52 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/logger/HMSLogger.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/logger/HMSLogger.java @@ -40,7 +40,7 @@ public final class HMSLogger { private static final String PLATFORM = "Flutter"; - private static final String VERSION = "5.0.2.304"; + private static final String VERSION = "5.1.1.301"; private static final String SERVICE = "Cross-Platform"; diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/BackgroundMessageBroadcastReceiver.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/BackgroundMessageBroadcastReceiver.java index 49712b5a..818f8c40 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/BackgroundMessageBroadcastReceiver.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/BackgroundMessageBroadcastReceiver.java @@ -31,7 +31,8 @@ public class BackgroundMessageBroadcastReceiver extends BroadcastReceiver { private static final String TAG = BackgroundMessageBroadcastReceiver.class.getSimpleName(); - public static final String BACKGROUND_REMOTE_MESSAGE = "com.huawei.hms.flutter.push.receiver.BACKGROUND_REMOTE_MESSAGE"; + public static final String BACKGROUND_REMOTE_MESSAGE + = "com.huawei.hms.flutter.push.receiver.BACKGROUND_REMOTE_MESSAGE"; @Override public void onReceive(Context context, Intent intent) { @@ -40,7 +41,7 @@ public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BACKGROUND_REMOTE_MESSAGE.equals(action)) { Bundle result = intent.getExtras(); - Log.d("Receiver-java", intent.getExtras().toString()); + Log.d(TAG, result != null ? result.toString() : ""); if (result != null) { HeadlessPushPlugin headLess = new HeadlessPushPlugin(context); headLess.handleBackgroundMessage(context, (RemoteMessage) result.get(Param.MESSAGE.code())); diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/MultiSenderTokenReceiver.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/MultiSenderTokenReceiver.java new file mode 100644 index 00000000..d651d6fb --- /dev/null +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/MultiSenderTokenReceiver.java @@ -0,0 +1,49 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.huawei.hms.flutter.push.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.huawei.hms.flutter.push.constants.Code; +import com.huawei.hms.flutter.push.constants.PushIntent; + +import io.flutter.plugin.common.EventChannel; + +import java.util.Objects; + +public class MultiSenderTokenReceiver extends BroadcastReceiver { + final EventChannel.EventSink events; + + public MultiSenderTokenReceiver(EventChannel.EventSink events) { + this.events = events; + } + + @Override + public void onReceive(Context context, Intent intent) { + if (Objects.requireNonNull(intent.getAction()).equals(PushIntent.MULTI_SENDER_TOKEN_INTENT_ACTION.id())) { + String err = intent.getStringExtra(PushIntent.MULTI_SENDER_TOKEN_ERROR.id()); + if (err == null) { + String res = intent.getStringExtra(PushIntent.MULTI_SENDER_TOKEN.id()); + this.events.success(res); + } else { + this.events.error(Code.RESULT_ERROR.code(), err, ""); + } + } + } +} diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/DataMessageReceiver.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/RemoteDataMessageReceiver.java similarity index 89% rename from flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/DataMessageReceiver.java rename to flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/RemoteDataMessageReceiver.java index fd17e8c9..d9b0e67e 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/DataMessageReceiver.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/RemoteDataMessageReceiver.java @@ -24,10 +24,10 @@ import io.flutter.plugin.common.EventChannel; -public class DataMessageReceiver extends BroadcastReceiver { +public class RemoteDataMessageReceiver extends BroadcastReceiver { final EventChannel.EventSink events; - public DataMessageReceiver(EventChannel.EventSink events) { + public RemoteDataMessageReceiver(EventChannel.EventSink events) { this.events = events; } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/common/NotificationIntentListener.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/common/NotificationIntentListener.java index ccb77421..11f43076 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/common/NotificationIntentListener.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/common/NotificationIntentListener.java @@ -16,6 +16,7 @@ package com.huawei.hms.flutter.push.receiver.common; +import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -26,15 +27,15 @@ import com.huawei.hms.flutter.push.utils.Utils; import com.huawei.hms.push.RemoteMessage; +import io.flutter.Log; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.PluginRegistry.NewIntentListener; + import org.json.JSONObject; import java.util.HashMap; import java.util.Map; -import io.flutter.Log; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.PluginRegistry.NewIntentListener; - /** * class NotificationIntentListener *

@@ -47,13 +48,21 @@ public class NotificationIntentListener implements NewIntentListener { private String initialIntent; + private Context context; + + public NotificationIntentListener(Context context) { + this.context = context; + } + @Override public boolean onNewIntent(Intent intent) { - handleIntent(intent); + if (Utils.checkNotificationFlags(intent)) { + handleIntent(intent); + } return false; } - public static Map getInitialNotification() { + public static synchronized Map getInitialNotification() { return NotificationIntentListener.initialNotification; } @@ -75,16 +84,20 @@ public void handleIntent(Intent intent) { if (bundleExtras != null) { RemoteMessage remoteMessage = new RemoteMessage(bundleExtras); map.put("remoteMessage", RemoteMessageUtils.toMap(remoteMessage)); - Map extras = MapUtils.toMap(BundleUtils.convertJSONObject(bundleExtras)); + Map extras = MapUtils.toMap(BundleUtils.convertJSONObject(bundleExtras)); map.put("extras", extras); } if (Intent.ACTION_VIEW.equals(action)) { initialIntent = dataString; - Utils.sendIntent(PushIntent.REMOTE_MESSAGE_NOTIFICATION_INTENT_ACTION, PushIntent.CUSTOM_INTENT, - initialIntent); - if (bundleExtras != null) sendNotificationOpenedAppEvent(map); + Utils.sendIntent(context, PushIntent.REMOTE_MESSAGE_NOTIFICATION_INTENT_ACTION, PushIntent.CUSTOM_INTENT, + initialIntent); + if (bundleExtras != null) { + sendNotificationOpenedAppEvent(map); + } } else if (Intent.ACTION_MAIN.equals(action) || PushIntent.LOCAL_NOTIFICATION_ACTION.name().equals(action)) { - if (bundleExtras != null) sendNotificationOpenedAppEvent(map); + if (bundleExtras != null) { + sendNotificationOpenedAppEvent(map); + } } else { Log.i("NotificationIntentListener", "Unsupported action intent:" + action); } @@ -93,7 +106,8 @@ public void handleIntent(Intent intent) { private void sendNotificationOpenedAppEvent(Map initialNotification) { setInitialNotification(initialNotification); JSONObject jsonObject = new JSONObject(initialNotification); - Utils.sendIntent(PushIntent.NOTIFICATION_OPEN_ACTION, PushIntent.NOTIFICATION_OPEN, jsonObject.toString()); + Utils.sendIntent(context, PushIntent.NOTIFICATION_OPEN_ACTION, PushIntent.NOTIFICATION_OPEN, + jsonObject.toString()); } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationActionsReceiver.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationActionsReceiver.java index 68dfd90c..4d4dfd1a 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationActionsReceiver.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationActionsReceiver.java @@ -16,7 +16,6 @@ package com.huawei.hms.flutter.push.receiver.local; -import android.app.Application; import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -33,15 +32,20 @@ public class HmsLocalNotificationActionsReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { String intentActionPrefix = context.getPackageName() + ".ACTION_"; - if (intent.getAction() == null || !intent.getAction().startsWith(intentActionPrefix)) + if (intent.getAction() == null || !intent.getAction().startsWith(intentActionPrefix)) { return; + } final Bundle bundle = intent.getBundleExtra(NotificationConstants.NOTIFICATION); - if (bundle == null) return; + if (bundle == null) { + return; + } - NotificationManager notificationManager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager == null) return; + NotificationManager notificationManager = (NotificationManager) context.getSystemService( + Context.NOTIFICATION_SERVICE); + if (notificationManager == null) { + return; + } int id = Integer.parseInt(BundleUtils.get(bundle, NotificationConstants.ID)); @@ -55,12 +59,12 @@ public void onReceive(final Context context, Intent intent) { } if (BundleUtils.getB(bundle, NotificationConstants.INVOKE_APP, true)) { - HmsLocalNotificationController hmsLocalNotificationController = - new HmsLocalNotificationController((Application) context.getApplicationContext()); + HmsLocalNotificationController hmsLocalNotificationController = new HmsLocalNotificationController( + context.getApplicationContext()); hmsLocalNotificationController.invokeApp(bundle); } else { - Utils.sendIntent(PushIntent.LOCAL_NOTIFICATION_CLICK_ACTION, PushIntent.LOCAL_NOTIFICATION_CLICK, - BundleUtils.convertJSON(bundle)); + Utils.sendIntent(context, PushIntent.LOCAL_NOTIFICATION_CLICK_ACTION, PushIntent.LOCAL_NOTIFICATION_CLICK, + BundleUtils.convertJSON(bundle)); } } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationBootEventReceiver.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationBootEventReceiver.java index b4aff667..16e0547e 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationBootEventReceiver.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/receiver/local/HmsLocalNotificationBootEventReceiver.java @@ -31,13 +31,16 @@ import java.util.Set; public class HmsLocalNotificationBootEventReceiver extends BroadcastReceiver { - private final String TAG = HmsLocalNotificationBootEventReceiver.class.getSimpleName(); + private static final String TAG = HmsLocalNotificationBootEventReceiver.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction() == null) return; - if (!intent.getAction().equals(Core.ScheduledPublisher.BOOT_EVENT)) + if (intent.getAction() == null) { return; + } + if (!intent.getAction().equals(Core.ScheduledPublisher.BOOT_EVENT)) { + return; + } Log.i(TAG, "Loading scheduled notifications...."); @@ -45,22 +48,21 @@ public void onReceive(Context context, Intent intent) { Set ids = sharedPreferences.getAll().keySet(); Application applicationContext = (Application) context.getApplicationContext(); - HmsLocalNotificationController hmsLocalNotificationController = - new HmsLocalNotificationController(applicationContext); + HmsLocalNotificationController hmsLocalNotificationController = new HmsLocalNotificationController( + applicationContext); for (String id : ids) { try { String notificationAttributesJson = sharedPreferences.getString(id, null); if (notificationAttributesJson != null) { - NotificationAttributes notificationAttributes = - NotificationAttributes.fromJson(notificationAttributesJson); + NotificationAttributes notificationAttributes = NotificationAttributes.fromJson( + notificationAttributesJson); if (notificationAttributes.getFireDate() < System.currentTimeMillis()) { - hmsLocalNotificationController - .localNotificationNow(notificationAttributes.toBundle(), null); + hmsLocalNotificationController.localNotificationNow(notificationAttributes.toBundle(), null); } else { - hmsLocalNotificationController - .localNotificationScheduleSetAlarm(notificationAttributes.toBundle()); + hmsLocalNotificationController.localNotificationScheduleSetAlarm( + notificationAttributes.toBundle()); } } } catch (Exception e) { diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/ApplicationUtils.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/ApplicationUtils.java index 43252646..b6b3eeb2 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/ApplicationUtils.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/ApplicationUtils.java @@ -21,7 +21,7 @@ import java.util.List; -public class ApplicationUtils { +public final class ApplicationUtils { private ApplicationUtils() { throw new IllegalStateException("Utility class"); @@ -32,12 +32,16 @@ public static boolean isApplicationInForeground(Context context) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List processInfos = activityManager.getRunningAppProcesses(); - if (processInfos == null) return false; + if (processInfos == null) { + return false; + } for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) { - if (processInfo.pkgList.length < 1) return false; + if (processInfo.pkgList.length < 1) { + return false; + } if (processInfo.processName.equals(context.getPackageName()) - && processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { + && processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/LocalNotificationUtils.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/LocalNotificationUtils.java index ac5a6123..6c156459 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/LocalNotificationUtils.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/LocalNotificationUtils.java @@ -19,10 +19,8 @@ import android.os.Bundle; import com.huawei.hms.flutter.push.config.NotificationAttributes; -import com.huawei.hms.flutter.push.constants.Code; import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; public class LocalNotificationUtils { @@ -30,11 +28,7 @@ private LocalNotificationUtils() { throw new IllegalStateException("Utility class"); } - public static Bundle callArgsToBundle(MethodCall call, MethodChannel.Result result) { - if (call.arguments == null) { - result.error(Code.NULL_BUNDLE.code(), "Arguments are empty", ""); - return null; - } + public static Bundle callArgsToBundle(MethodCall call) { try { return new NotificationAttributes(call).toBundle(); } catch (Exception e) { diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/MapUtils.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/MapUtils.java index e0461a0f..60432b67 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/MapUtils.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/MapUtils.java @@ -16,6 +16,8 @@ package com.huawei.hms.flutter.push.utils; +import android.os.Bundle; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -23,6 +25,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Set; public class MapUtils { @@ -30,12 +33,13 @@ private MapUtils() { throw new IllegalStateException("Utility class"); } - public static Map toMap(JSONObject jsonObject) { Map map = new HashMap<>(); - if (jsonObject == null) return map; + if (jsonObject == null) { + return map; + } Iterator iterator = jsonObject.keys(); try { @@ -60,4 +64,19 @@ public static Map toMap(JSONObject jsonObject) { } + public static Map bundleToMap(Bundle bundle) { + Map map = new HashMap<>(); + if (bundle != null) { + Set keys = bundle.keySet(); + for (String key : keys) { + Object value = bundle.get(key); + if (value instanceof Bundle) { + map.put(key, bundleToMap((Bundle) value)); + } else { + map.put(key, value); + } + } + } + return map; + } } diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/RemoteMessageUtils.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/RemoteMessageUtils.java index 6e39ddd1..f76f69e5 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/RemoteMessageUtils.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/RemoteMessageUtils.java @@ -20,13 +20,14 @@ import com.huawei.hms.flutter.push.constants.RemoteMessageAttributes; import com.huawei.hms.push.RemoteMessage; +import io.flutter.plugin.common.MethodCall; + import org.json.JSONObject; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import io.flutter.plugin.common.MethodCall; - public class RemoteMessageUtils { private RemoteMessageUtils() { @@ -55,62 +56,38 @@ public static Map toMap(RemoteMessage message) { if (message.getNotification() != null) { RemoteMessage.Notification notification = message.getNotification(); - notificationContent.put(RemoteMessageAttributes.TITLE, - notification.getTitle()); + notificationContent.put(RemoteMessageAttributes.TITLE, notification.getTitle()); notificationContent.put(RemoteMessageAttributes.TITLE_LOCALIZATION_KEY, - notification.getTitleLocalizationKey()); + notification.getTitleLocalizationKey()); notificationContent.put(RemoteMessageAttributes.TITLE_LOCALIZATION_ARGS, - notification.getTitleLocalizationArgs()); + Arrays.asList(notification.getTitleLocalizationArgs())); notificationContent.put(RemoteMessageAttributes.BODY_LOCALIZATION_KEY, - notification.getBodyLocalizationKey()); + notification.getBodyLocalizationKey()); notificationContent.put(RemoteMessageAttributes.BODY_LOCALIZATION_ARGS, - notification.getBodyLocalizationArgs()); - notificationContent.put(RemoteMessageAttributes.BODY, - notification.getBody()); - notificationContent.put(RemoteMessageAttributes.ICON, - notification.getIcon()); - notificationContent.put(RemoteMessageAttributes.SOUND, - notification.getSound()); - notificationContent.put(RemoteMessageAttributes.TAG, - notification.getTag()); - notificationContent.put(RemoteMessageAttributes.COLOR, - notification.getColor()); - notificationContent.put(RemoteMessageAttributes.CLICK_ACTION, - notification.getClickAction()); - notificationContent.put(RemoteMessageAttributes.CHANNEL_ID, - notification.getChannelId()); - notificationContent.put(RemoteMessageAttributes.IMAGE_URL, - notification.getImageUrl() + ""); - notificationContent.put(RemoteMessageAttributes.LINK, - notification.getLink() + ""); - notificationContent.put(RemoteMessageAttributes.NOTIFY_ID, - notification.getNotifyId()); - notificationContent.put(RemoteMessageAttributes.WHEN, - notification.getWhen()); - notificationContent.put(RemoteMessageAttributes.LIGHT_SETTINGS, - notification.getLightSettings()); - notificationContent.put(RemoteMessageAttributes.BADGE_NUMBER, - notification.getBadgeNumber()); - notificationContent.put(RemoteMessageAttributes.IMPORTANCE, - notification.getImportance()); - notificationContent.put(RemoteMessageAttributes.TICKER, - notification.getTicker()); - notificationContent.put(RemoteMessageAttributes.VIBRATE_CONFIG, - notification.getVibrateConfig()); - notificationContent.put(RemoteMessageAttributes.VISIBILITY, - notification.getVisibility()); - notificationContent.put(RemoteMessageAttributes.INTENT_URI, - notification.getIntentUri()); - notificationContent.put(RemoteMessageAttributes.IS_AUTO_CANCEL, - notification.isAutoCancel()); - notificationContent.put(RemoteMessageAttributes.IS_LOCAL_ONLY, - notification.isLocalOnly()); - notificationContent.put(RemoteMessageAttributes.IS_DEFAULT_LIGHT, - notification.isDefaultLight()); - notificationContent.put(RemoteMessageAttributes.IS_DEFAULT_SOUND, - notification.isDefaultSound()); - notificationContent.put(RemoteMessageAttributes.IS_DEFAULT_VIBRATE, - notification.isDefaultVibrate()); + Arrays.asList(notification.getBodyLocalizationArgs())); + notificationContent.put(RemoteMessageAttributes.BODY, notification.getBody()); + notificationContent.put(RemoteMessageAttributes.ICON, notification.getIcon()); + notificationContent.put(RemoteMessageAttributes.SOUND, notification.getSound()); + notificationContent.put(RemoteMessageAttributes.TAG, notification.getTag()); + notificationContent.put(RemoteMessageAttributes.COLOR, notification.getColor()); + notificationContent.put(RemoteMessageAttributes.CLICK_ACTION, notification.getClickAction()); + notificationContent.put(RemoteMessageAttributes.CHANNEL_ID, notification.getChannelId()); + notificationContent.put(RemoteMessageAttributes.IMAGE_URL, notification.getImageUrl() + ""); + notificationContent.put(RemoteMessageAttributes.LINK, notification.getLink() + ""); + notificationContent.put(RemoteMessageAttributes.NOTIFY_ID, notification.getNotifyId()); + notificationContent.put(RemoteMessageAttributes.WHEN, notification.getWhen()); + notificationContent.put(RemoteMessageAttributes.LIGHT_SETTINGS, notification.getLightSettings()); + notificationContent.put(RemoteMessageAttributes.BADGE_NUMBER, notification.getBadgeNumber()); + notificationContent.put(RemoteMessageAttributes.IMPORTANCE, notification.getImportance()); + notificationContent.put(RemoteMessageAttributes.TICKER, notification.getTicker()); + notificationContent.put(RemoteMessageAttributes.VIBRATE_CONFIG, notification.getVibrateConfig()); + notificationContent.put(RemoteMessageAttributes.VISIBILITY, notification.getVisibility()); + notificationContent.put(RemoteMessageAttributes.INTENT_URI, notification.getIntentUri()); + notificationContent.put(RemoteMessageAttributes.IS_AUTO_CANCEL, notification.isAutoCancel()); + notificationContent.put(RemoteMessageAttributes.IS_LOCAL_ONLY, notification.isLocalOnly()); + notificationContent.put(RemoteMessageAttributes.IS_DEFAULT_LIGHT, notification.isDefaultLight()); + notificationContent.put(RemoteMessageAttributes.IS_DEFAULT_SOUND, notification.isDefaultSound()); + notificationContent.put(RemoteMessageAttributes.IS_DEFAULT_VIBRATE, notification.isDefaultVibrate()); content.put(RemoteMessageAttributes.NOTIFICATION, notificationContent); } @@ -120,31 +97,34 @@ public static Map toMap(RemoteMessage message) { public static RemoteMessage callArgsToRemoteMsg(MethodCall call) { String to = call.argument(RemoteMessageAttributes.TO); - if (to == null || to.equals("")) to = Core.REMOTE_MESSAGE_UPLINK_TO; + if (to == null || to.equals("")) { + to = Core.REMOTE_MESSAGE_UPLINK_TO; + } RemoteMessage.Builder builder = new RemoteMessage.Builder(to); - String messageId = call.hasArgument(RemoteMessageAttributes.MESSAGE_ID) ? - (String) call.argument(RemoteMessageAttributes.MESSAGE_ID) : - NotificationConfigUtils.generateNotificationId(); - String messageType = call.hasArgument(RemoteMessageAttributes.MESSAGE_TYPE) ? - (String) call.argument(RemoteMessageAttributes.MESSAGE_TYPE) : "hms"; - int ttl = call.hasArgument(RemoteMessageAttributes.TTL) ? - (int) call.argument(RemoteMessageAttributes.TTL) : 120; - String collapseKey = call.hasArgument(RemoteMessageAttributes.COLLAPSE_KEY) ? - (String) call.argument(RemoteMessageAttributes.COLLAPSE_KEY) : "-1"; - int receiptMode = call.hasArgument(RemoteMessageAttributes.RECEIPT_MODE) ? - (int) call.argument(RemoteMessageAttributes.RECEIPT_MODE) : 1; // Default Mode is 0 - int sendMode = call.hasArgument(RemoteMessageAttributes.SEND_MODE) ? - (int) call.argument(RemoteMessageAttributes.SEND_MODE) : 1; // Default Mode is 0 + String messageId = call.hasArgument(RemoteMessageAttributes.MESSAGE_ID) ? (String) call.argument( + RemoteMessageAttributes.MESSAGE_ID) : NotificationConfigUtils.generateNotificationId(); + String messageType = call.hasArgument(RemoteMessageAttributes.MESSAGE_TYPE) ? (String) call.argument( + RemoteMessageAttributes.MESSAGE_TYPE) : "hms"; + int ttl = call.hasArgument(RemoteMessageAttributes.TTL) + ? (int) call.argument(RemoteMessageAttributes.TTL) + : 120; + String collapseKey = call.hasArgument(RemoteMessageAttributes.COLLAPSE_KEY) ? (String) call.argument( + RemoteMessageAttributes.COLLAPSE_KEY) : "-1"; + int receiptMode = call.hasArgument(RemoteMessageAttributes.RECEIPT_MODE) ? (int) call.argument( + RemoteMessageAttributes.RECEIPT_MODE) : 1; // Default Mode is 0 + int sendMode = call.hasArgument(RemoteMessageAttributes.SEND_MODE) ? (int) call.argument( + RemoteMessageAttributes.SEND_MODE) : 1; // Default Mode is 0 HashMap map = null; - if (call.hasArgument(RemoteMessageAttributes.DATA) && - call.argument(RemoteMessageAttributes.DATA) instanceof HashMap) { + if (call.hasArgument(RemoteMessageAttributes.DATA) && call.argument( + RemoteMessageAttributes.DATA) instanceof HashMap) { map = call.argument(RemoteMessageAttributes.DATA); } - if (map != null) + if (map != null) { builder.setData(map); + } builder.setCollapseKey(collapseKey); builder.setMessageId(messageId); diff --git a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/Utils.java b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/Utils.java index 8f13169f..32658f11 100644 --- a/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/Utils.java +++ b/flutter-hms-push/android/src/main/java/com/huawei/hms/flutter/push/utils/Utils.java @@ -16,17 +16,22 @@ package com.huawei.hms.flutter.push.utils; +import android.content.Context; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import android.util.Log; -import com.huawei.hms.flutter.push.PushPlugin; +import com.huawei.hms.flutter.push.constants.Code; +import com.huawei.hms.flutter.push.constants.NotificationConstants; import com.huawei.hms.flutter.push.constants.PushIntent; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; + import java.io.InvalidClassException; import java.util.Objects; -import io.flutter.plugin.common.MethodCall; - /** * class Utils * @@ -38,7 +43,7 @@ private Utils() { throw new IllegalStateException("Utility class"); } - private static String TAG = "FlutterHmsUtils"; + private static final String TAG = "FlutterHmsUtils"; public static boolean isEmpty(Object str) { return str == null || str.toString().trim().length() == 0; @@ -77,12 +82,40 @@ public static double getDoubleArgument(MethodCall call, String argument) { } } - public static void sendIntent(PushIntent action, PushIntent extraName, String result) { + public static void sendIntent(Context context, PushIntent action, PushIntent extraName, String result) { Intent intent = new Intent(); - intent.setPackage(PushPlugin.getContext().getPackageName()); + intent.setPackage(context.getPackageName()); intent.setAction(action.id()); intent.putExtra(extraName.id(), result); - PushPlugin.getContext().sendBroadcast(intent); + context.sendBroadcast(intent); + } + + /** + * Checks if the intent is a tapped notification. + * + * @param intent The intent object to be checked. + * @return true if the intent is identified as a notification, false otherwise. + */ + public static boolean checkNotificationFlags(Intent intent) { + int flagNumber = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_RECEIVER_REPLACE_PENDING + | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT; + int flagNumberAndBroughtToFront = flagNumber | Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT; + return intent.getFlags() == flagNumber || intent.getFlags() == flagNumberAndBroughtToFront + || intent.getBundleExtra(NotificationConstants.NOTIFICATION) != null || intent.getDataString() != null; + } + + public static void handleSuccessOnUIThread(final MethodChannel.Result result) { + new Handler(Looper.getMainLooper()).post(() -> result.success(Code.RESULT_SUCCESS.code())); + } + + public static void handleErrorOnUIThread(final MethodChannel.Result result, final String errorMessage) { + new Handler(Looper.getMainLooper()).post(() -> result.error(Code.RESULT_ERROR.code(), errorMessage, "")); + } + + public static void handleErrorOnUIThread(final MethodChannel.Result result, final String errorCode, + final String errorMessage, final String errorDetails) { + new Handler(Looper.getMainLooper()).post( + () -> result.error(errorCode, errorMessage, errorDetails != null ? errorDetails : "")); } } diff --git a/flutter-hms-push/example/.gitignore b/flutter-hms-push/example/.gitignore index 1ba9c339..55d320e6 100644 --- a/flutter-hms-push/example/.gitignore +++ b/flutter-hms-push/example/.gitignore @@ -29,6 +29,7 @@ .pub-cache/ .pub/ /build/ +*.lock # Web related lib/generated_plugin_registrant.dart diff --git a/flutter-hms-push/example/android/gradle/wrapper/gradle-wrapper.properties b/flutter-hms-push/example/android/gradle/wrapper/gradle-wrapper.properties index a4b44297..442d9132 100644 --- a/flutter-hms-push/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/flutter-hms-push/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/flutter-hms-push/example/android/gradlew b/flutter-hms-push/example/android/gradlew index cccdd3d5..4f906e0c 100644 --- a/flutter-hms-push/example/android/gradlew +++ b/flutter-hms-push/example/android/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/flutter-hms-push/example/android/gradlew.bat b/flutter-hms-push/example/android/gradlew.bat index f9553162..107acd32 100644 --- a/flutter-hms-push/example/android/gradlew.bat +++ b/flutter-hms-push/example/android/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/flutter-hms-push/example/lib/local_notification.dart b/flutter-hms-push/example/lib/local_notification_page.dart similarity index 86% rename from flutter-hms-push/example/lib/local_notification.dart rename to flutter-hms-push/example/lib/local_notification_page.dart index d1394f7a..93b9fb92 100644 --- a/flutter-hms-push/example/lib/local_notification.dart +++ b/flutter-hms-push/example/lib/local_notification_page.dart @@ -16,11 +16,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:huawei_push/local_notification/local_notification.dart'; -import 'package:huawei_push/push.dart'; +import 'package:huawei_push/huawei_push_library.dart'; class LocalNotificationPage extends StatefulWidget { - LocalNotificationPage({Key key}) : super(key: key); + LocalNotificationPage({Key? key}) : super(key: key); @override _LocalNotificationPageState createState() => _LocalNotificationPageState(); @@ -41,7 +40,7 @@ class _LocalNotificationPageState extends State { TextEditingController tagTextController = TextEditingController(); TextEditingController logTextController = TextEditingController(); - Map receivedNotification; + late Map receivedNotification; Map defaultNotification = { HMSLocalNotificationAttr.TITLE: 'Notification Title', HMSLocalNotificationAttr.MESSAGE: 'Notification Message', @@ -83,33 +82,39 @@ class _LocalNotificationPageState extends State { onError: _onLocalNotificationClickErr); } - _onLocalNotificationClickEvent(Map event) { + void _onLocalNotificationClickEvent(Map event) { receivedNotification = event; if (mounted) { // Check if widget is still mounted to call setState showResult( "onLocalNotificationClickEvent", receivedNotification.toString()); } - Push.showToast("Clicked: " + receivedNotification['action'] ?? " "); + Push.showToast("Clicked: " + receivedNotification['action']); if (receivedNotification[HMSLocalNotificationAttr.ACTION] == "Yes") { int id = int.parse(receivedNotification[HMSLocalNotificationAttr.ID]); - String tag = receivedNotification[HMSLocalNotificationAttr.TAG]; - Push.cancelNotificationsWithIdTag({id: tag}).then((_) => showResult( - "cancelNotificationsWithIdTag", - "Cancelled, Notification with id: $id, and tag: $tag")); + String? tag = receivedNotification[HMSLocalNotificationAttr.TAG]; + if (tag != null) { + Push.cancelNotificationsWithIdTag({id: tag}).then((_) => showResult( + "cancelNotificationsWithIdTag", + "Cancelled, Notification with id: $id, and tag: $tag")); + } else { + Push.cancelNotificationsWithId([id]).then((_) => showResult( + "cancelNotificationsWithId", + "Cancelled, Notification with id: $id")); + } } } - _onLocalNotificationClickErr(dynamic err) => + void _onLocalNotificationClickErr(dynamic err) => showResult("onLocalNotificationClickError", err.toString()); - _clearLog() { + void _clearLog() { setState(() { logTextController.text = ""; }); } - _localNotification() async { + void _localNotification() async { try { Map notification = _constructNotificationMap(); Map response = @@ -120,7 +125,7 @@ class _LocalNotificationPageState extends State { } } - _localNotificationOngoing() async { + void _localNotificationOngoing() async { try { Map ongoingNotification = _constructNotificationMap(); ongoingNotification[HMSLocalNotificationAttr.ONGOING] = true; @@ -132,7 +137,7 @@ class _LocalNotificationPageState extends State { } } - _localNotificationSound() async { + void _localNotificationSound() async { try { Map soundNotification = _constructNotificationMap(); soundNotification[HMSLocalNotificationAttr.PLAY_SOUND] = true; @@ -146,7 +151,7 @@ class _LocalNotificationPageState extends State { } } - _localNotificationVibrate() async { + void _localNotificationVibrate() async { try { Map vibrateNotification = _constructNotificationMap(); vibrateNotification[HMSLocalNotificationAttr.VIBRATE] = true; @@ -159,7 +164,7 @@ class _LocalNotificationPageState extends State { } } - _localNotificationBigImage() async { + void _localNotificationBigImage() async { try { Map bigImgNotification = _constructNotificationMap(); bigImgNotification[HMSLocalNotificationAttr.BIG_PICTURE_URL] = @@ -172,7 +177,7 @@ class _LocalNotificationPageState extends State { } } - _localNotificationRepeat() async { + void _localNotificationRepeat() async { try { Map repeatedNotification = _constructNotificationMap(); repeatedNotification[HMSLocalNotificationAttr.REPEAT_TYPE] = @@ -185,7 +190,7 @@ class _LocalNotificationPageState extends State { } } - _localNotificationScheduled() async { + void _localNotificationScheduled() async { try { Map scheduledNotification = _constructNotificationMap(); scheduledNotification[HMSLocalNotificationAttr.FIRE_DATE] = @@ -199,30 +204,30 @@ class _LocalNotificationPageState extends State { } } - _channelBlocked() async { + void _channelBlocked() async { bool blocked = await Push.channelBlocked( 'huawei-hms-flutter-push-channel-id-4-default'); showResult("channelBlocked", blocked.toString()); } - _channelExists() async { + void _channelExists() async { bool exists = await Push.channelExists( 'huawei-hms-flutter-push-channel-id-4-default'); showResult("channelExists", exists.toString()); } - _getChannels() async { + void _getChannels() async { List channels = await Push.getChannels(); showResult("getChannels", channels.toString()); } - _deleteChannel() async { + void _deleteChannel() async { String result = await Push.deleteChannel( "huawei-hms-flutter-push-channel-id-4-default"); showResult("deleteChannel", result); } - _getNotifications() async { + void _getNotifications() async { List notifications = await Push.getNotifications(); showResult( "getNotifications", @@ -232,7 +237,7 @@ class _LocalNotificationPageState extends State { print("getNotification result: " + notifications.toString()); } - _getScheduledNotifications() async { + void _getScheduledNotifications() async { List scheduledNotifications = await Push.getScheduledNotifications(); showResult("getScheduledNotifications", scheduledNotifications.length.toString() + " scheduled notifications"); @@ -240,12 +245,13 @@ class _LocalNotificationPageState extends State { scheduledNotifications.toString()); } - showResult(String name, [String msg = "Button pressed."]) { + void showResult(String name, [String msg = "Button pressed."]) { appendLog("[" + name + "]" + ": " + msg); + print("[" + name + "]" + ": " + msg); if (msg.isNotEmpty) Push.showToast(msg); } - appendLog([String msg = "Button pressed."]) { + void appendLog([String msg = "Button pressed."]) { setState(() { logTextController.text = msg + "\n" + logTextController.text; }); @@ -258,7 +264,7 @@ class _LocalNotificationPageState extends State { } Widget customTextField(TextEditingController controller, String hintText, - {EdgeInsets customPadding}) { + {EdgeInsets? customPadding}) { return Padding( padding: customPadding ?? padding, child: Container( @@ -295,18 +301,19 @@ class _LocalNotificationPageState extends State { ); } - Widget customButton(String label, Function callback, {Color color}) { + Widget customButton(String label, Function() callback, {Color? color}) { return Expanded( flex: 5, child: Padding( padding: padding.copyWith(top: 0.0, bottom: 0.0), - child: RaisedButton( - padding: EdgeInsets.zero, - color: color, + child: ElevatedButton( onPressed: callback, + style: ElevatedButton.styleFrom( + primary: color ?? Colors.grey.shade300, + ), child: Text( label, - style: TextStyle(fontSize: 12), + style: TextStyle(fontSize: 12, color: Colors.black87), ), ), ), @@ -401,8 +408,8 @@ class _LocalNotificationPageState extends State { children: [ customButton( 'cancelAllNotifications', - () => Push.cancelAllNotifications() - .then((_) => showResult("cancelAllNotifications", ""))), + () => Push.cancelAllNotifications().then( + (_) => showResult("cancelAllNotifications", "Success"))), customButton('getNotifications', () => _getNotifications()), ], ), @@ -410,8 +417,8 @@ class _LocalNotificationPageState extends State { children: [ customButton( 'cancelScheduledNotifications', - () => Push.cancelScheduledNotifications().then( - (_) => showResult("cancelScheduledNotifications", ""))), + () => Push.cancelScheduledNotifications().then((_) => + showResult("cancelScheduledNotifications", "Success"))), customButton('getScheduledNotifications', () => _getScheduledNotifications()), ], @@ -420,8 +427,8 @@ class _LocalNotificationPageState extends State { children: [ customButton( 'cancelNotificationsWithTag', - () => Push.cancelNotificationsWithTag('hms_tag').then( - (_) => showResult("cancelNotificationsWithTag", ""))), + () => Push.cancelNotificationsWithTag('hms_tag').then((_) => + showResult("cancelNotificationsWithTag", "Success"))), customButton('getChannels', () => _getChannels()), ], ), @@ -429,8 +436,8 @@ class _LocalNotificationPageState extends State { children: [ customButton( 'cancelNotifications', - () => Push.cancelNotifications() - .then((_) => showResult("cancelNotifications", ""))), + () => Push.cancelNotifications().then( + (_) => showResult("cancelNotifications", "Success"))), customButton('deleteChannel', () => _deleteChannel()), ], ), diff --git a/flutter-hms-push/example/lib/main.dart b/flutter-hms-push/example/lib/main.dart index 627cc7d5..ae120de0 100644 --- a/flutter-hms-push/example/lib/main.dart +++ b/flutter-hms-push/example/lib/main.dart @@ -20,11 +20,11 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; -import 'package:huawei_push/model/remote_message.dart'; -import 'package:huawei_push/local_notification/local_notification.dart'; -import 'package:huawei_push/push.dart'; +import 'package:huawei_push/huawei_push_library.dart'; +import 'package:huawei_push_example/multi_sender_page.dart'; + import 'custom_intent_page.dart'; -import 'local_notification.dart'; +import 'local_notification_page.dart'; void main() { runApp(MaterialApp(home: MyApp())); @@ -36,8 +36,8 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - TextEditingController logTextController; - TextEditingController topicTextController; + late TextEditingController logTextController; + late TextEditingController topicTextController; final padding = EdgeInsets.symmetric(vertical: 1.0, horizontal: 16); @@ -49,21 +49,25 @@ class _MyAppState extends State { } void _onTokenError(Object error) { - PlatformException e = error; - showResult("TokenErrorEvent", e.message); + PlatformException e = error as PlatformException; + showResult("TokenErrorEvent", e.message!); } static void backgroundMessageCallback(RemoteMessage remoteMessage) async { - String data = remoteMessage.data; - - Push.localNotification({ - HMSLocalNotificationAttr.TITLE: '[Headless] DataMessage Received', - HMSLocalNotificationAttr.MESSAGE: data - }); + String? data = remoteMessage.data; + if (data != null) { + print("Background message is received, sending local notification."); + Push.localNotification({ + HMSLocalNotificationAttr.TITLE: '[Headless] DataMessage Received', + HMSLocalNotificationAttr.MESSAGE: data + }); + } else { + print("Background message is received. There is no data in the message."); + } } void _onMessageReceived(RemoteMessage remoteMessage) { - String data = remoteMessage.data; + String? data = remoteMessage.data; if (data != null) { Push.localNotification({ HMSLocalNotificationAttr.TITLE: 'DataMessage Received', @@ -84,11 +88,11 @@ class _MyAppState extends State { } void _onRemoteMessageSendError(Object error) { - PlatformException e = error; + PlatformException e = error as PlatformException; showResult("RemoteMessageSendError", "Error: " + e.toString()); } - void _onNewIntent(String intentString) { + void _onNewIntent(String? intentString) { // For navigating to the custom intent page (deep link) the custom // intent that sent from the push kit console is: // app://app2 @@ -97,7 +101,7 @@ class _MyAppState extends State { showResult('CustomIntentEvent: ', intentString); List parsedString = intentString.split("://"); if (parsedString[1] == "app2") { - SchedulerBinding.instance.addPostFrameCallback((timeStamp) { + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { Navigator.of(context).push( MaterialPageRoute(builder: (context) => CustomIntentPage())); }); @@ -106,20 +110,24 @@ class _MyAppState extends State { } void _onIntentError(Object err) { - PlatformException e = err; + PlatformException e = err as PlatformException; print("Error on intent stream: " + e.toString()); } void _onNotificationOpenedApp(dynamic initialNotification) { - showResult("onNotificationOpenedApp", initialNotification.toString()); - print("[onNotificationOpenedApp]" + initialNotification.toString()); + if (initialNotification != null) { + showResult("onNotificationOpenedApp", initialNotification.toString()); + print("[onNotificationOpenedApp]" + initialNotification.toString()); + } } @override void initState() { super.initState(); + Push.enableLogger(); logTextController = new TextEditingController(); topicTextController = new TextEditingController(); + Push.disableLogger(); initPlatformState(); } @@ -130,7 +138,7 @@ class _MyAppState extends State { Push.onNotificationOpenedApp.listen(_onNotificationOpenedApp); var initialNotification = await Push.getInitialNotification(); _onNotificationOpenedApp(initialNotification); - String intent = await Push.getInitialIntent(); + String? intent = await Push.getInitialIntent(); _onNewIntent(intent); Push.onMessageReceivedStream .listen(_onMessageReceived, onError: _onMessageReceiveError); @@ -147,8 +155,8 @@ class _MyAppState extends State { @override void dispose() { - logTextController?.dispose(); - topicTextController?.dispose(); + logTextController.dispose(); + topicTextController.dispose(); super.dispose(); } @@ -163,12 +171,12 @@ class _MyAppState extends State { } void getId() async { - String result = await Push.getId(); + String? result = await Push.getId(); showResult("getId", result); } void getAAID() async { - String result = await Push.getAAID(); + String? result = await Push.getAAID(); showResult("getAAID", result); } @@ -178,7 +186,7 @@ class _MyAppState extends State { } void getOdid() async { - String result = await Push.getOdid(); + String? result = await Push.getOdid(); showResult("getOdid", result); } @@ -187,6 +195,11 @@ class _MyAppState extends State { showResult("getCreationTime", result); } + void deleteToken() async { + String result = await Push.deleteToken(""); + showResult("deleteToken", result); + } + void deleteAAID() async { String result = await Push.deleteAAID(); showResult("deleteAAID", result); @@ -230,7 +243,7 @@ class _MyAppState extends State { void isAutoInitEnabled() async { bool result = await Push.isAutoInitEnabled(); - showResult("isAutoInitEnabled", result ? "Enabled" : "Disabled"); + showResult("isAutoInitEnabled", result.toString()); } void getInitialNotification() async { @@ -239,8 +252,8 @@ class _MyAppState extends State { } void getInitialIntent() async { - final String initialIntent = await Push.getInitialIntent(); - showResult("getInitialIntent", initialIntent ?? ''); + final String? initialIntent = await Push.getInitialIntent(); + showResult("getInitialIntent", initialIntent); } void getAgConnectValues() async { @@ -254,9 +267,13 @@ class _MyAppState extends State { }); } - void showResult(String name, [String msg = "Button pressed."]) { + void showResult(String name, [String? msg = "Button pressed."]) { + if (msg == null) { + msg = ""; + } appendLog("[" + name + "]" + ": " + msg); - if (msg.isNotEmpty) Push.showToast("[" + name + "]: " + msg); + print("[" + name + "]" + ": " + msg); + Push.showToast("[" + name + "]: " + msg); } void appendLog([String msg = "Button pressed."]) { @@ -270,18 +287,22 @@ class _MyAppState extends State { Function func, String txt, { double fontSize = 16.0, - Color color, + Color? color, }) { return Expanded( flex: flex, child: Padding( padding: padding, - child: RaisedButton( - onPressed: func, - color: color, + child: ElevatedButton( + onPressed: () { + func(); + }, + style: ElevatedButton.styleFrom( + primary: color ?? Colors.grey.shade300, + ), child: Text( txt, - style: TextStyle(fontSize: fontSize), + style: TextStyle(fontSize: fontSize, color: Colors.black87), ), ), ), @@ -317,6 +338,14 @@ class _MyAppState extends State { 'Local Notification', color: Colors.blue), ]), + Row(children: [ + expandedButton( + 5, + () => Navigator.of(context).push(MaterialPageRoute( + builder: (context) => MultiSenderPage())), + 'Multi Sender Page', + color: Colors.yellow), + ]), Row(children: [ expandedButton(5, () => turnOnPush(), 'TurnOnPush', fontSize: 20), expandedButton(5, () => turnOffPush(), 'TurnOffPush', @@ -334,7 +363,7 @@ class _MyAppState extends State { fontSize: 20) ]), Row(children: [ - expandedButton(5, () => Push.deleteToken(""), 'DeleteToken', + expandedButton(5, () => deleteToken(), 'DeleteToken', fontSize: 20), expandedButton(5, () => deleteAAID(), 'DeleteAAID', fontSize: 20) ]), diff --git a/flutter-hms-push/example/lib/multi_sender_page.dart b/flutter-hms-push/example/lib/multi_sender_page.dart new file mode 100644 index 00000000..dd997549 --- /dev/null +++ b/flutter-hms-push/example/lib/multi_sender_page.dart @@ -0,0 +1,259 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import 'package:flutter/material.dart'; +import 'package:huawei_push/huawei_push_library.dart'; + +class MultiSenderPage extends StatefulWidget { + MultiSenderPage({Key? key}) : super(key: key); + + @override + _MultiSenderPageState createState() => _MultiSenderPageState(); +} + +class _MultiSenderPageState extends State { + @override + void initState() { + super.initState(); + Push.getMultiSenderTokenStream + .listen(_onMultiSenderTokenReceived, onError: _onMultiSenderTokenError); + } + + void _onMultiSenderTokenReceived(Map multiSenderTokenEvent) { + showResult('onMultiSenderTokenReceived', multiSenderTokenEvent.toString()); + } + + void _onMultiSenderTokenError(dynamic error) { + showResult('onMultiSenderTokenError', error.toString()); + } + + TextEditingController logTextController = TextEditingController(); + final padding = EdgeInsets.symmetric(vertical: 1.0, horizontal: 10); + final TextStyle _textStyle = TextStyle(fontSize: 16); + Widget customTextField(TextEditingController controller, String hintText, + {EdgeInsets? customPadding}) { + return Padding( + padding: customPadding ?? padding, + child: Container( + child: TextField( + controller: controller, + style: TextStyle(fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.blueAccent, width: 1.0), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.blueGrey, width: 1.0), + ), + contentPadding: EdgeInsets.zero, + hintText: hintText, + hintStyle: TextStyle(fontWeight: FontWeight.normal), + ), + ), + ), + ); + } + + Widget labelText(String text) { + return Expanded( + flex: 3, + child: Padding( + padding: padding, + child: Text( + text, + style: _textStyle.copyWith(fontWeight: FontWeight.bold), + ), + ), + ); + } + + void _clearLog() { + setState(() { + logTextController.text = ""; + }); + } + + Widget customButton(String label, Function() callback, {Color? color}) { + return Expanded( + flex: 5, + child: Padding( + padding: padding.copyWith(top: 0.0, bottom: 0.0), + child: ElevatedButton( + onPressed: callback, + style: ElevatedButton.styleFrom( + primary: color ?? Colors.grey.shade300, + ), + child: Text( + label, + style: TextStyle(fontSize: 12, color: Colors.black87), + ), + ), + ), + ); + } + + void showResult(String name, [String? msg = "Button pressed."]) { + if (msg == null) { + msg = ""; + } + appendLog("[" + name + "]" + ": " + msg); + print("[" + name + "]" + ": " + msg); + Push.showToast("[" + name + "]: " + msg); + } + + void appendLog([String msg = "Button pressed."]) { + setState(() { + logTextController.text = msg + "\n" + logTextController.text; + }); + } + + void isSupportProfile() async { + showResult( + 'isSupportProfile', (await HmsProfile.isSupportProfile()).toString()); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text( + 'Push Kit Demo - Multi-Sender', + style: TextStyle(fontSize: 16), + ), + ), + body: ListView( + shrinkWrap: true, + children: [ + Row( + children: [ + customButton( + 'isSupportProfile', + () => isSupportProfile(), + ), + ], + ), + Row( + children: [ + customButton( + 'addProfile', + () => HmsProfile.addProfile( + HmsProfile.HUAWEI_PROFILE, "profile001") + .then( + (_) => showResult("addProfile", "Success"), + onError: (e) => showResult("addProfile Error:", e.toString()), + ), + ), + ], + ), + Row( + children: [ + customButton( + 'addMultiSenderProfile', + () => HmsProfile.addMultiSenderProfile("", + HmsProfile.HUAWEI_PROFILE, "multiSenderProfile001") + .then( + (_) => showResult("addMultiSenderProfile", "Success"), + onError: (e) => + showResult("addMultiSenderProfile Error:", e.toString()), + ), + ), + ], + ), + Row( + children: [ + customButton( + 'deleteProfile', + () => HmsProfile.deleteProfile("profile001").then( + (_) => showResult("deleteProfile", "Success"), + onError: (e) => + showResult("deleteProfile Error:", e.toString()), + ), + ), + ], + ), + Row( + children: [ + customButton( + 'deleteMultiSenderProfile', + () => HmsProfile.deleteMultiSenderProfile( + "", "multiSenderProfile001") + .then( + (_) => showResult("deleteMultiSenderProfile", "Success"), + onError: (e) => showResult( + "deleteMultiSenderProfile Error:", e.toString()), + ), + ), + ], + ), + // Enter the sender app's project id to the subjectId parameter to get the Multi-Sender push token. + Row( + children: [ + customButton( + 'getMultiSenderToken', + () => Push.getMultiSenderToken("").then( + (_) => showResult("getMultiSenderToken", "Success"), + onError: (e) => + showResult("getMultiSenderToken Error:", e.toString()), + ), + ), + ], + ), + // Enter the sender app's project id to the subjectId parameter to delete the obtained Multi-Sender push token. + Row( + children: [ + customButton( + 'deleteMultiSenderToken', + () => Push.deleteMultiSenderToken("").then( + (_) => showResult("deleteMultiSenderToken", "Success"), + onError: (e) => + showResult("deleteMultiSenderToken Error:", e.toString()), + ), + ), + ], + ), + Row( + children: [customButton('clearLog', () => _clearLog())], + ), + Padding( + padding: padding.copyWith(top: 10.0, bottom: 10.0), + child: Divider( + height: 1.0, + thickness: 2.0, + ), + ), + Padding( + padding: padding, + child: TextField( + controller: logTextController, + keyboardType: TextInputType.multiline, + maxLines: 15, + readOnly: true, + decoration: new InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.blueAccent, width: 3.0), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: Colors.blueGrey, width: 3.0), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/flutter-hms-push/example/pubspec.yaml b/flutter-hms-push/example/pubspec.yaml index e70399f0..c1ffa21c 100644 --- a/flutter-hms-push/example/pubspec.yaml +++ b/flutter-hms-push/example/pubspec.yaml @@ -1,9 +1,9 @@ name: huawei_push_example description: Demonstrates how to use the Huawei Push plugin. -version: 5.0.2+304 +version: 5.1.1+301 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: diff --git a/flutter-hms-push/ios/huawei_push.podspec b/flutter-hms-push/ios/huawei_push.podspec index af558dbe..ec031364 100644 --- a/flutter-hms-push/ios/huawei_push.podspec +++ b/flutter-hms-push/ios/huawei_push.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'huawei_push' - s.version = '5.0.2+304' + s.version = '5.1.1.301' s.summary = 'HUAWEI Push Kit plugin for Flutter.' s.description = <<-DESC HUAWEI Push Kit plugin for Flutter that exposes all the functionality provided by the HUAWEI Push Kit SDK. diff --git a/flutter-hms-push/lib/constants/channel.dart b/flutter-hms-push/lib/constants/channel.dart deleted file mode 100644 index 0270edae..00000000 --- a/flutter-hms-push/lib/constants/channel.dart +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License") - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/// API Constant Event and Method Channel Name Definitions /// -const String TOKEN_CHANNEL = "com.huawei.flutter.push/token"; -const String REMOTE_MESSAGE_RECEIVE_CHANNEL = - "com.huawei.flutter.push/remote_message_receive"; -const String REMOTE_MESSAGE_SEND_STATUS_CHANNEL = - "com.huawei.flutter.push/remote_message_send_status"; -const String REMOTE_MESSAGE_NOTIFICATION_INTENT_CHANNEL = - "com.huawei.flutter.push/remote_message_notification_intent"; -const String NOTIFICATION_OPEN_CHANNEL = - "com.huawei.flutter.push/notification_open"; -const String LOCAL_NOTIFICATION_CLICK_CHANNEL = - "com.huawei.flutter.push/local_notification_click"; -const String METHOD_CHANNEL = "com.huawei.flutter.push/method"; -const String BACKGROUND_MESSAGE_CHANNEL = "com.huawei.flutter.push/background"; diff --git a/flutter-hms-push/lib/huawei_push_library.dart b/flutter-hms-push/lib/huawei_push_library.dart new file mode 100644 index 00000000..d80dcac8 --- /dev/null +++ b/flutter-hms-push/lib/huawei_push_library.dart @@ -0,0 +1,20 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export 'src/cli/cli_export.dart'; +export 'src/constants/constants_export.dart' show ResultCodes; +export 'src/local_notification/local_notification.dart'; +export 'src/model/remote_message.dart'; diff --git a/flutter-hms-push/lib/src/cli/cli_export.dart b/flutter-hms-push/lib/src/cli/cli_export.dart new file mode 100644 index 00000000..4deec047 --- /dev/null +++ b/flutter-hms-push/lib/src/cli/cli_export.dart @@ -0,0 +1,20 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export 'fcm_push_proxy.dart'; +export 'hms_profile.dart'; +export 'proxy_settings.dart'; +export 'push.dart'; diff --git a/flutter-hms-push/lib/src/cli/fcm_push_proxy.dart b/flutter-hms-push/lib/src/cli/fcm_push_proxy.dart new file mode 100644 index 00000000..f13f6f4e --- /dev/null +++ b/flutter-hms-push/lib/src/cli/fcm_push_proxy.dart @@ -0,0 +1,25 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import 'package:huawei_push/src/constants/channel.dart'; + +/// Provides the package for you to aggregate the push capability of FCM. +class FcmPushProxy { + /// Initializes the push capability of FCM. + static Future init() async { + return await methodChannel.invokeMethod("initFcmPushProxy"); + } +} diff --git a/flutter-hms-push/lib/src/cli/hms_profile.dart b/flutter-hms-push/lib/src/cli/hms_profile.dart new file mode 100644 index 00000000..cecd3476 --- /dev/null +++ b/flutter-hms-push/lib/src/cli/hms_profile.dart @@ -0,0 +1,69 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import 'package:huawei_push/src/constants/channel.dart'; + +/// A class for checking whether to display messages for the user based on the account. +/// +/// Supported devices: phones and tablets +/// Supported operating systems: EMUI 9.1.0 or later and Android 9.0 or later +class HmsProfile { + /// Account Type Constant. + /// + /// HUAWEI ID that you transfer by [addProfile] or [addMultiSenderProfile] in HmsProfile to verify the account. + static const int HUAWEI_PROFILE = 1; + + /// Account Type Constant. + /// + /// Account different than the HUAWEI ID, which you transfer by [addProfile] or [addMultiSenderProfile] in HmsProfile to verify the account. + static const int CUSTOM_PROFILE = 2; + + /// Account Type Constant. + /// + /// Undefined account type. + static const UNDEFINED_PROFILE = -1; + + /// Checks whether the device supports account verification. + static Future isSupportProfile() async { + return await methodChannel.invokeMethod('isSupportProfile'); + } + + /// Adds the relationship between the user and app on the device. + static Future addProfile(int type, String profileId) async { + return await methodChannel + .invokeMethod('addProfile', {'type': type, 'profileId': profileId}); + } + + /// Adds the relationships between the user and apps on the device in the multi-sender scenario. + static Future addMultiSenderProfile( + String subjectId, int type, String profileId) async { + return await methodChannel.invokeMethod('addMultiSenderProfile', + {'subjectId': subjectId, 'type': type, 'profileId': profileId}); + } + + /// Deletes the relationship between the user and app on the device. + static Future deleteProfile(String profileId) async { + return await methodChannel + .invokeMethod('deleteProfile', {'profileId': profileId}); + } + + /// Deletes the relationships between the user and apps on the device in the multi-sender scenario. + static Future deleteMultiSenderProfile( + String subjectId, String profileId) async { + return await methodChannel.invokeMethod( + 'deleteProfile', {'subjectId': subjectId, 'profileId': profileId}); + } +} diff --git a/flutter-hms-push/lib/src/cli/proxy_settings.dart b/flutter-hms-push/lib/src/cli/proxy_settings.dart new file mode 100644 index 00000000..ed5d9a7a --- /dev/null +++ b/flutter-hms-push/lib/src/cli/proxy_settings.dart @@ -0,0 +1,25 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import 'package:huawei_push/src/constants/channel.dart'; + +/// A class provided by the aggregation capability package for setting basic attributes. +class ProxySettings { + /// Sets a country/region code. This method is available only for Huawei-developed apps. + static Future setCountryCode(String countryCode) async { + methodChannel.invokeMethod("setCountryCode", {"countryCode": countryCode}); + } +} diff --git a/flutter-hms-push/lib/push.dart b/flutter-hms-push/lib/src/cli/push.dart similarity index 82% rename from flutter-hms-push/lib/push.dart rename to flutter-hms-push/lib/src/cli/push.dart index 574b4d60..b6265ba6 100644 --- a/flutter-hms-push/lib/push.dart +++ b/flutter-hms-push/lib/src/cli/push.dart @@ -20,43 +20,29 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:huawei_push/model/remote_message.dart'; +import 'package:huawei_push/src/constants/constants_export.dart'; +import 'package:huawei_push/src/model/remote_message.dart'; -import './constants/Channel.dart' as Channel; -import './constants/Method.dart' as Method; -import 'constants/Code.dart'; +import 'package:huawei_push/src/constants/channel.dart'; +import 'package:huawei_push/src/constants/method.dart' as Method; class Push { - /// Constant Method and Event Channel definitions for communicating with native platform - static const MethodChannel methodChannel = - const MethodChannel(Channel.METHOD_CHANNEL); - static const EventChannel tokenEventChannel = - EventChannel(Channel.TOKEN_CHANNEL); - static const EventChannel remoteMessageReceiveEventChannel = - EventChannel(Channel.REMOTE_MESSAGE_RECEIVE_CHANNEL); - static const EventChannel remoteMessageSendStatusEventChannel = - EventChannel(Channel.REMOTE_MESSAGE_SEND_STATUS_CHANNEL); - static const EventChannel remoteMessageNotificationIntentEventChannel = - EventChannel(Channel.REMOTE_MESSAGE_NOTIFICATION_INTENT_CHANNEL); - static const EventChannel notificationOpenEventChannel = - EventChannel(Channel.NOTIFICATION_OPEN_CHANNEL); - static const EventChannel localNotificationClickEventChannel = - EventChannel(Channel.LOCAL_NOTIFICATION_CLICK_CHANNEL); - /// Enables the function of receiving notification messages. /// /// Returns the corresponding Push SDK Result Code's Description static Future turnOnPush() async { - final String result = await methodChannel.invokeMethod(Method.turnOnPush); - return Code[result]; + final String result = + await methodChannel.invokeMethod(Method.turnOnPush) ?? '-1'; + return ResultCodes[result]; } /// Disables the function of receiving notification messages. /// /// Returns the corresponding Push SDK Result Code's Description static Future turnOffPush() async { - final String result = await methodChannel.invokeMethod(Method.turnOffPush); - return Code[result]; + final String result = + await methodChannel.invokeMethod(Method.turnOffPush) ?? '-1'; + return ResultCodes[result]; } /// Before applying for a token, an app calls this method to obtain its unique AAID. @@ -65,14 +51,14 @@ class Push { /// If the AAID of the app changes, a new token will be generated next time when /// the app applies for a token. If an app needs to report statistics events, /// it must carry the AAID as its unique ID. - static Future getId() async { - final String result = await methodChannel.invokeMethod(Method.getId); + static Future getId() async { + final String? result = await methodChannel.invokeMethod(Method.getId); return result; } /// Obtains an AAID of Push SDK - static Future getAAID() async { - final String result = await methodChannel.invokeMethod(Method.getAAID); + static Future getAAID() async { + final String? result = await methodChannel.invokeMethod(Method.getAAID); return result; } @@ -83,8 +69,8 @@ class Push { } /// Obtains an open device ID (ODID) in asynchronous mode. - static Future getOdid() async { - final String result = await methodChannel.invokeMethod(Method.getOdid); + static Future getOdid() async { + final String? result = await methodChannel.invokeMethod(Method.getOdid); return result; } @@ -113,18 +99,23 @@ class Push { /// Deletes a local AAID and its generation timestamp. static Future deleteAAID() async { final String result = await methodChannel.invokeMethod(Method.deleteAAID); - return Code[result]; + return ResultCodes[result]; } /// Deletes the push token. - /// - /// Result of this method will be returned to the **onError** callback of the - /// Token Stream. - static Future deleteToken(String scope) async { + static Future deleteToken(String scope) async { Map args = {}; args.putIfAbsent("scope", () => scope); + String result = await methodChannel.invokeMethod(Method.deleteToken, args); + return ResultCodes[result]; + } - methodChannel.invokeMethod(Method.deleteToken, args); + /// Deletes a token that a target app developer applies for a sender to integrate + /// Push Kit in the multi-sender scenario. + static Future deleteMultiSenderToken(String subjectId) async { + String result = await methodChannel + .invokeMethod(Method.deleteToken, {'subjectId': subjectId}); + return ResultCodes[result]; } /// Obtains the stream of [tokenEventChannel]. @@ -134,6 +125,15 @@ class Push { static Stream get getTokenStream => tokenEventChannel.receiveBroadcastStream().cast(); + /// Obtains the stream of [multiSenderTokenEventChannel]. + /// + /// The stream emits the requested push token and errors thrown with the Push + /// SDK [Code] values in the multi-sender scenario. + static Stream> get getMultiSenderTokenStream => + multiSenderTokenEventChannel + .receiveBroadcastStream() + .map((event) => jsonDecode(event)); + /// Obtains the stream of [remoteMessageReceiveEventChannel]. /// /// The stream emits the remote message object of received data messages from @@ -166,7 +166,7 @@ class Push { RemoteMessageBuilder remoteMsg) async { final String result = await methodChannel.invokeMethod(Method.send, remoteMsg.toMap()); - return Code[result]; + return ResultCodes[result]; } /// Subscribes to topics. @@ -185,7 +185,7 @@ class Push { final String result = await methodChannel.invokeMethod(Method.subscribe, args); - return Code[result]; + return ResultCodes[result]; } /// Unsubscribes from topics that are subscribed to. @@ -198,7 +198,7 @@ class Push { final String result = await methodChannel.invokeMethod(Method.unsubscribe, args); - return Code[result]; + return ResultCodes[result]; } /// Determines whether to enable automatic initialization. @@ -221,7 +221,7 @@ class Push { final String result = await methodChannel.invokeMethod(Method.setAutoInitEnabled, args); - return Code[result]; + return ResultCodes[result]; } /// Checks whether automatic initialization is enabled. @@ -234,24 +234,23 @@ class Push { /// Obtains values from the **agconnect-services.json** file. static Future getAgConnectValues() async { final String result = - await methodChannel.invokeMethod(Method.getAgConnectValues); + await methodChannel.invokeMethod(Method.getAgConnectValues); return result; } /// Utility for showing an Android Toast Message - static Future showToast(String msg) async { + static Future showToast(String msg) async { Map args = {}; args.putIfAbsent("msg", () => msg); await methodChannel.invokeMethod(Method.showToast, args); - return null; } /// Obtains the custom intent URI of the notification message which launches the app. /// /// If another notification message with a custom intent is selected, the return /// value will be updated. - static Future getInitialIntent() async { - final String result = + static Future getInitialIntent() async { + final String? result = await methodChannel.invokeMethod(Method.getInitialIntent); return result; } @@ -317,10 +316,10 @@ class Push { /// Obtains the list of all active notification messages. static Future>> getNotifications() async { - final List notifications = + final List? notifications = await methodChannel.invokeMethod(Method.getNotifications); List> result = []; - notifications.forEach((element) { + notifications?.forEach((element) { result.add(json.decode(element)); }); return result; @@ -328,10 +327,10 @@ class Push { /// Obtains the list of all pending scheduled notification messages. static Future>> getScheduledNotifications() async { - final List scheduledNotifications = + final List? scheduledNotifications = await methodChannel.invokeMethod(Method.getScheduledNotifications); List> result = []; - scheduledNotifications.forEach((element) { + scheduledNotifications?.forEach((element) { result.add(json.decode(element)); }); return result; @@ -339,7 +338,8 @@ class Push { /// Obtains the list of all notification channels. static Future> getChannels() async { - final List result = await methodChannel.invokeMethod(Method.getChannels); + final List result = + await methodChannel.invokeMethod(Method.getChannels) ?? []; List strList = result.cast(); return strList; } @@ -347,8 +347,9 @@ class Push { /// Deletes a notification channel with the given ID. static Future deleteChannel(String channelId) async { final String result = - await methodChannel.invokeMethod(Method.deleteChannel, channelId); - return Code[result]; + await methodChannel.invokeMethod(Method.deleteChannel, channelId) ?? + '-1'; + return ResultCodes[result]; } /// Checks whether a notification channel with the given ID exists. @@ -400,6 +401,16 @@ class Push { methodChannel.invokeMethod(Method.cancelNotificationsWithIdTag, idTags); } + /// Obtains a token that a target app developer applies for a sender to integrate + /// Push Kit in the multi-sender scenario. + /// + /// The requested token will be emitted to the multi sender token stream. Listen for the stream + /// from [getMultiSenderTokenStream] to obtain the token. + static Future getMultiSenderToken(String subjectId) async { + methodChannel + .invokeMethod(Method.getMultiSenderToken, {"subjectId": subjectId}); + } + /// Enables HMS Plugin Method Analytics static Future enableLogger() async { methodChannel.invokeMethod(Method.enableLogger); @@ -414,9 +425,10 @@ class Push { static Future registerBackgroundMessageHandler( void Function(RemoteMessage remoteMessage) callback) { int rawHandle = - PluginUtilities.getCallbackHandle(callbackDispatcher).toRawHandle(); + PluginUtilities.getCallbackHandle(callbackDispatcher)!.toRawHandle(); print("rawHandle $rawHandle"); - int rawCallback = PluginUtilities.getCallbackHandle(callback).toRawHandle(); + int rawCallback = + PluginUtilities.getCallbackHandle(callback)!.toRawHandle(); print("rawCallback $rawCallback"); return methodChannel.invokeMethod('registerBackgroundMessageHandler', { "rawHandle": rawHandle, @@ -434,8 +446,6 @@ class Push { /// Callback function for handling received [RemoteMessage] objects in the background. void callbackDispatcher() { - const MethodChannel backgroundMessageChannel = - MethodChannel(Channel.BACKGROUND_MESSAGE_CHANNEL); WidgetsFlutterBinding.ensureInitialized(); backgroundMessageChannel.setMethodCallHandler((MethodCall call) async { @@ -443,7 +453,7 @@ void callbackDispatcher() { Map.from(call.arguments[1]); RemoteMessage remoteMessage = RemoteMessage.fromMap(args); final Function rawHandler = PluginUtilities.getCallbackFromHandle( - CallbackHandle.fromRawHandle(call.arguments[0])); + CallbackHandle.fromRawHandle(call.arguments[0]))!; rawHandler(remoteMessage); }); diff --git a/flutter-hms-push/lib/src/constants/channel.dart b/flutter-hms-push/lib/src/constants/channel.dart new file mode 100644 index 00000000..120c5058 --- /dev/null +++ b/flutter-hms-push/lib/src/constants/channel.dart @@ -0,0 +1,37 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import 'package:flutter/services.dart'; + +/// Includes Constant Method and Event Channel definitions for communicating with the native platform. +const MethodChannel methodChannel = + MethodChannel('com.huawei.flutter.push/method'); +const EventChannel tokenEventChannel = + EventChannel('com.huawei.flutter.push/token'); +const EventChannel multiSenderTokenEventChannel = + EventChannel('com.huawei.flutter.push/multi_sender_token'); +const EventChannel remoteMessageReceiveEventChannel = + EventChannel('com.huawei.flutter.push/remote_message_receive'); +const EventChannel remoteMessageSendStatusEventChannel = + EventChannel('com.huawei.flutter.push/remote_message_send_status'); +const EventChannel remoteMessageNotificationIntentEventChannel = + EventChannel('com.huawei.flutter.push/remote_message_notification_intent'); +const EventChannel notificationOpenEventChannel = + EventChannel('com.huawei.flutter.push/notification_open'); +const EventChannel localNotificationClickEventChannel = + EventChannel('com.huawei.flutter.push/local_notification_click'); +const MethodChannel backgroundMessageChannel = + MethodChannel('com.huawei.flutter.push/background'); diff --git a/flutter-hms-push/lib/src/constants/constants_export.dart b/flutter-hms-push/lib/src/constants/constants_export.dart new file mode 100644 index 00000000..5a64dd89 --- /dev/null +++ b/flutter-hms-push/lib/src/constants/constants_export.dart @@ -0,0 +1,19 @@ +/* + Copyright 2020-2021. Huawei Technologies Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export 'channel.dart'; +export 'method.dart'; +export 'result_codes.dart'; diff --git a/flutter-hms-push/lib/constants/method.dart b/flutter-hms-push/lib/src/constants/method.dart similarity index 95% rename from flutter-hms-push/lib/constants/method.dart rename to flutter-hms-push/lib/src/constants/method.dart index 8a7e8b66..a1b4ad36 100644 --- a/flutter-hms-push/lib/constants/method.dart +++ b/flutter-hms-push/lib/src/constants/method.dart @@ -23,10 +23,12 @@ const String getAAID = "getAAID"; const String getAppId = "getAppId"; const String getOdid = "getOdid"; const String getToken = "getToken"; +const String getMultiSenderToken = "getMultiSenderToken"; const String getCreationTime = "getCreationTime"; const String deleteAAID = "deleteAAID"; const String deleteToken = "deleteToken"; +const String deleteMultiSenderToken = "deleteMultiSenderToken"; const String subscribe = "subscribe"; const String unsubscribe = "unsubscribe"; diff --git a/flutter-hms-push/lib/constants/code.dart b/flutter-hms-push/lib/src/constants/result_codes.dart similarity index 99% rename from flutter-hms-push/lib/constants/code.dart rename to flutter-hms-push/lib/src/constants/result_codes.dart index 3d456163..9e6c4b57 100644 --- a/flutter-hms-push/lib/constants/code.dart +++ b/flutter-hms-push/lib/src/constants/result_codes.dart @@ -15,7 +15,7 @@ */ /// Push SDK Result Codes /// -const Map Code = { +const Map ResultCodes = { /// Success '0': 'RESULT_SUCCESS', diff --git a/flutter-hms-push/lib/local_notification/attributes.dart b/flutter-hms-push/lib/src/local_notification/attributes.dart similarity index 100% rename from flutter-hms-push/lib/local_notification/attributes.dart rename to flutter-hms-push/lib/src/local_notification/attributes.dart diff --git a/flutter-hms-push/lib/local_notification/importance.dart b/flutter-hms-push/lib/src/local_notification/importance.dart similarity index 100% rename from flutter-hms-push/lib/local_notification/importance.dart rename to flutter-hms-push/lib/src/local_notification/importance.dart diff --git a/flutter-hms-push/lib/local_notification/local_notification.dart b/flutter-hms-push/lib/src/local_notification/local_notification.dart similarity index 100% rename from flutter-hms-push/lib/local_notification/local_notification.dart rename to flutter-hms-push/lib/src/local_notification/local_notification.dart diff --git a/flutter-hms-push/lib/local_notification/priority.dart b/flutter-hms-push/lib/src/local_notification/priority.dart similarity index 100% rename from flutter-hms-push/lib/local_notification/priority.dart rename to flutter-hms-push/lib/src/local_notification/priority.dart diff --git a/flutter-hms-push/lib/local_notification/repeat_type.dart b/flutter-hms-push/lib/src/local_notification/repeat_type.dart similarity index 96% rename from flutter-hms-push/lib/local_notification/repeat_type.dart rename to flutter-hms-push/lib/src/local_notification/repeat_type.dart index b1a42cae..6778e1ad 100644 --- a/flutter-hms-push/lib/local_notification/repeat_type.dart +++ b/flutter-hms-push/lib/src/local_notification/repeat_type.dart @@ -14,7 +14,7 @@ limitations under the License. */ -class RepeatType { +abstract class RepeatType { static const String HOUR = "hour"; static const String MINUTE = "minute"; static const String DAY = "day"; diff --git a/flutter-hms-push/lib/local_notification/visibility.dart b/flutter-hms-push/lib/src/local_notification/visibility.dart similarity index 100% rename from flutter-hms-push/lib/local_notification/visibility.dart rename to flutter-hms-push/lib/src/local_notification/visibility.dart diff --git a/flutter-hms-push/lib/model/remote_message.dart b/flutter-hms-push/lib/src/model/remote_message.dart similarity index 81% rename from flutter-hms-push/lib/model/remote_message.dart rename to flutter-hms-push/lib/src/model/remote_message.dart index ddc7962d..35f3a27e 100644 --- a/flutter-hms-push/lib/model/remote_message.dart +++ b/flutter-hms-push/lib/src/model/remote_message.dart @@ -40,23 +40,23 @@ class RemoteMessage { static const String SEND_MODE = 'sendMode'; static const String RECEIPT_MODE = 'receiptMode'; - final String messageId; - final String to; - final String from; - final String type; - final String token; - final int ttl; - final String collapseKey; - final int urgency; - final int originalUrgency; - final int sentTime; - final String data; - final Map dataOfMap; - final _RemoteMessageNotification notification; - final int sendMode; - final int receiptMode; - - RemoteMessage._internal({ + final String? messageId; + final String? to; + final String? from; + final String? type; + final String? token; + final int? ttl; + final String? collapseKey; + final int? urgency; + final int? originalUrgency; + final int? sentTime; + final String? data; + final Map? dataOfMap; + final _RemoteMessageNotification? notification; + final int? sendMode; + final int? receiptMode; + + RemoteMessage._({ this.collapseKey, this.data, this.dataOfMap, @@ -75,47 +75,47 @@ class RemoteMessage { }); /// Obtains the classification identifier (collapse key) of a message. - String get getCollapseKey => collapseKey; + String? get getCollapseKey => collapseKey; /// Obtains the payload of a message. - String get getData => data; + String? get getData => data; /// Obtains the payload of a Map message. - Map get getDataOfMap => dataOfMap; + Map? get getDataOfMap => dataOfMap; /// Obtains the ID of a message. - String get getMessageId => messageId; + String? get getMessageId => messageId; /// Obtains the type of a message. - String get getMessageType => type; + String? get getMessageType => type; /// Obtains the notification data instance from a message. - _RemoteMessageNotification get getNotification => notification; + _RemoteMessageNotification? get getNotification => notification; /// Obtains the message priority set by an app. - int get getOriginalUrgency => originalUrgency; + int? get getOriginalUrgency => originalUrgency; /// Obtains the message priority set on the HUAWEI Push Kit server. - int get getUrgency => urgency; + int? get getUrgency => urgency; /// Obtains the maximum cache duration of a message. - int get getTtl => ttl; + int? get getTtl => ttl; /// Obtains the time when a message is sent from the server. - int get getSentTime => sentTime; + int? get getSentTime => sentTime; /// Obtains the recipient of a message. - String get getTo => to; + String? get getTo => to; /// Obtains the source of a message. - String get getFrom => from; + String? get getFrom => from; /// Obtains the token in a message. - String get getToken => token; + String? get getToken => token; - factory RemoteMessage.fromMap(Map map) { - if (map == null) return null; - return RemoteMessage._internal( + factory RemoteMessage.fromMap(Map? map) { + if (map == null) return RemoteMessage._(); + return RemoteMessage._( to: map[RemoteMessage.TO] == null ? null : map[RemoteMessage.TO], from: map[RemoteMessage.FROM] == null ? null : map[RemoteMessage.FROM], messageId: map[RemoteMessage.MESSAGE_ID] == null @@ -168,7 +168,7 @@ class RemoteMessage { COLLAPSE_KEY: this.collapseKey ?? '', DATA: this.data ?? '', DATA_OF_MAP: this.dataOfMap ?? {}, - NOTIFICATION: this.notification != null ? this.notification.toMap() : '', + NOTIFICATION: this.notification != null ? this.notification!.toMap() : '', SEND_MODE: this.sendMode != null ? this.sendMode : '', RECEIPT_MODE: this.receiptMode != null ? this.receiptMode : '', }; @@ -176,14 +176,14 @@ class RemoteMessage { } class RemoteMessageBuilder { - String collapseKey; - Map data; - String messageId; - String messageType; - int ttl; - String to; - int sendMode = 1; - int receiptMode = 1; + String? collapseKey; + Map? data; + String? messageId; + String? messageType; + int? ttl; + String? to; + int sendMode; + int receiptMode; RemoteMessageBuilder( {this.to, @@ -192,12 +192,12 @@ class RemoteMessageBuilder { this.messageId, this.messageType, this.ttl, - this.sendMode, - this.receiptMode}); + this.sendMode = 1, + this.receiptMode = 1}); /// Adds key-value pair data to a message. RemoteMessageBuilder addData(String key, String value) { - this.data[key] = value; + this.data![key] = value; return this; } @@ -209,7 +209,7 @@ class RemoteMessageBuilder { /// Deletes message data. RemoteMessageBuilder clearData() { - this.data.clear(); + this.data!.clear(); return this; } @@ -316,39 +316,39 @@ class _RemoteMessageNotification { static const IS_DEFAULT_SOUND = 'isDefaultSound'; static const IS_DEFAULT_VIBRATE = 'isDefaultVibrate'; - final String title; - final String titleLocalizationKey; - final String body; - final String bodyLocalizationKey; - final String icon; - final String sound; - final String tag; - final String color; - final String clickAction; - final String channelId; - final String ticker; - final String intentUri; - - final bool isDefaultLight; - final bool isDefaultSound; - final bool isDefaultVibrate; - final bool isAutoCancel; - final bool isLocalOnly; - - final int notifyId; - final int badgeNumber; - final int importance; - final int visibility; - - final Uri imageUrl; - final Uri link; - - final double when; - - final List lightSettings; - final List vibrateConfig; - final List titleLocalizationArgs; - final List bodyLocalizationArgs; + final String? title; + final String? titleLocalizationKey; + final String? body; + final String? bodyLocalizationKey; + final String? icon; + final String? sound; + final String? tag; + final String? color; + final String? clickAction; + final String? channelId; + final String? ticker; + final String? intentUri; + + final bool? isDefaultLight; + final bool? isDefaultSound; + final bool? isDefaultVibrate; + final bool? isAutoCancel; + final bool? isLocalOnly; + + final int? notifyId; + final int? badgeNumber; + final int? importance; + final int? visibility; + + final Uri? imageUrl; + final Uri? link; + + final double? when; + + final List? lightSettings; + final List? vibrateConfig; + final List? titleLocalizationArgs; + final List? bodyLocalizationArgs; _RemoteMessageNotification( {this.title, @@ -381,76 +381,76 @@ class _RemoteMessageNotification { this.vibrateConfig}); /// Obtains the title of a message. - String get getTitle => title; + String? get getTitle => title; /// Obtains the key of the displayed title of a message. - String get getTitleLocalizationKey => titleLocalizationKey; + String? get getTitleLocalizationKey => titleLocalizationKey; /// Obtains variables of the displayed title of a message. - List get getTitleLocalizationArgs => titleLocalizationArgs; + List? get getTitleLocalizationArgs => titleLocalizationArgs; /// Obtains the key of the displayed content of a message. - String get getBodyLocalizationKey => bodyLocalizationKey; + String? get getBodyLocalizationKey => bodyLocalizationKey; /// Obtains variables of the displayed content of a message. - List get getBodyLocalizationArgs => bodyLocalizationArgs; + List? get getBodyLocalizationArgs => bodyLocalizationArgs; /// Obtains the displayed content of a message. - String get getBody => body; + String? get getBody => body; /// Obtains the image resource name of the notification icon. - String get getIcon => icon; + String? get getIcon => icon; /// Obtains the name of an audio resource to be played when a notification message is displayed. - String get getSound => sound; + String? get getSound => sound; /// Obtains the tag from a message for message overwriting. - String get getTag => tag; + String? get getTag => tag; /// Obtains the colors of icons and buttons in a message. - String get getColor => color; + String? get getColor => color; /// Obtains actions triggered by message tapping. - String get getClickAction => clickAction; + String? get getClickAction => clickAction; /// Obtains IDs of channels that support the display of messages. - String get getChannelId => channelId; + String? get getChannelId => channelId; /// Obtains the image URL from a message. - Uri get getImageUrl => imageUrl; + Uri? get getImageUrl => imageUrl; /// Obtains the deep link from a message. - Uri get getLink => link; + Uri? get getLink => link; /// Obtains the unique ID of a message. - int get getNotifyId => notifyId; + int? get getNotifyId => notifyId; /// Obtains the display time of a notification message. - double get getWhen => when; + double? get getWhen => when; /// Obtains the blinking frequency and color of a breathing light. - List get getLightSettings => lightSettings; + List? get getLightSettings => lightSettings; /// Obtains a badge number. - int get getBadgeNumber => badgeNumber; + int? get getBadgeNumber => badgeNumber; /// Obtains the priority of a notification message. - int get getImportance => importance; + int? get getImportance => importance; /// Obtains the text to be displayed on the status bar for a notification message. - String get getTicker => ticker; + String? get getTicker => ticker; /// Obtains an array of vibration patterns. - List get getVibrateConfig => vibrateConfig; + List? get getVibrateConfig => vibrateConfig; /// Obtains the visibility of a notification message. - int get getVisibility => visibility; + int? get getVisibility => visibility; /// Obtains the intent in a notification message. - String get getIntentUri => intentUri; + String? get getIntentUri => intentUri; - factory _RemoteMessageNotification.fromMap(Map map) { - if (map == null) return null; + factory _RemoteMessageNotification.fromMap(Map? map) { + if (map == null) return _RemoteMessageNotification(); return _RemoteMessageNotification( title: map[TITLE] == null ? null : map[TITLE], titleLocalizationKey: map[TITLE_LOCALIZATION_KEY] == null @@ -494,9 +494,6 @@ class _RemoteMessageNotification { ); } - factory _RemoteMessageNotification.fromJson(String source) => - _RemoteMessageNotification.fromMap(json.decode(source)); - Map toMap() { return { TITLE: this.title, diff --git a/flutter-hms-push/pubspec.yaml b/flutter-hms-push/pubspec.yaml index 702d3692..ccb0741f 100644 --- a/flutter-hms-push/pubspec.yaml +++ b/flutter-hms-push/pubspec.yaml @@ -1,12 +1,12 @@ name: huawei_push description: HUAWEI Push Kit plugin for Flutter that exposes all the functionality provided by the HUAWEI Push Kit SDK. -version: 5.0.2+304 +version: 5.1.1+301 homepage: https://www.huawei.com repository: https://github.com/HMS-Core/hms-flutter-plugin/tree/master/flutter-hms-push environment: - sdk: ">=2.1.0 <3.0.0" - flutter: ">=1.12.13+hotfix.6 <2.0.0" + sdk: ">=2.12.0 <3.0.0" + flutter: ">=1.12.13+hotfix.6" dependencies: flutter: