diff --git a/.pubignore b/.pubignore new file mode 100644 index 0000000..39c3af3 --- /dev/null +++ b/.pubignore @@ -0,0 +1,44 @@ +# Sub-plugins — published as separate packages, not part of this package +PointSDK-Flutter-Push/ + +# Internal docs not intended for pub.dev +push.md + +# Build outputs & caches +build/ +.dart_tool/ +.pub/ +.pub-cache/ + +# Flutter-generated files +.flutter-plugins +.flutter-plugins-dependencies +.packages + +# IDE +.idea/ +*.iml +.vscode/ + +# Android build artefacts +**/android/.gradle +**/android/local.properties +**/android/captures/ + +# iOS / Xcode artefacts +**/ios/**/Pods/ +**/ios/**/DerivedData/ +**/ios/**/xcuserdata/ +**/ios/**/.symlinks/ +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/flutter_export_environment.sh +**/ios/Runner/GeneratedPluginRegistrant.* + +# macOS +.DS_Store +._* + +# Misc +*.log +*.class + diff --git a/PointSDK-Flutter-Push/.pubignore b/PointSDK-Flutter-Push/.pubignore new file mode 100644 index 0000000..eea4723 --- /dev/null +++ b/PointSDK-Flutter-Push/.pubignore @@ -0,0 +1,39 @@ +# Build outputs & caches +build/ +.dart_tool/ +.pub/ +.pub-cache/ + +# Flutter-generated files +.flutter-plugins +.flutter-plugins-dependencies +.packages + +# IDE +.idea/ +*.iml +.vscode/ + +# Android build artefacts +**/android/.gradle +**/android/local.properties +**/android/captures/ + +# iOS / Xcode artefacts +**/ios/**/Pods/ +**/ios/**/DerivedData/ +**/ios/**/xcuserdata/ +**/ios/**/.symlinks/ +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/flutter_export_environment.sh +**/ios/Runner/GeneratedPluginRegistrant.* + +# macOS +.DS_Store +._* + +# Misc +*.log +*.class + + diff --git a/PointSDK-Flutter-Push/INTEGRATION.md b/PointSDK-Flutter-Push/INTEGRATION.md new file mode 100644 index 0000000..4dc797c --- /dev/null +++ b/PointSDK-Flutter-Push/INTEGRATION.md @@ -0,0 +1,129 @@ +# `bluedot_point_sdk_push` — Android Integration Guide + +## Overview + +The `bluedot_point_sdk_push` Flutter plugin bridges the Bluedot push notifications module +to Flutter. Because a Flutter app may already use Firebase Cloud Messaging (FCM) for its own +purposes, **the plugin does not register a `FirebaseMessagingService`**. Instead, you wire up +FCM in your own app and forward the relevant events to the plugin with two method calls. + +--- + +## Step 1 — Add the plugin + +In your app's `pubspec.yaml`: + +```yaml +dependencies: + bluedot_point_sdk: ^2.0.0 + bluedot_point_sdk_push: ^1.0.0 +``` + +--- + +## Step 2 — Set up Firebase + +If your app doesn't use Firebase yet, follow the +[official Android FCM setup guide](https://firebase.google.com/docs/cloud-messaging/android/get-started) +to add Firebase to your project (`google-services.json`, `google-services` Gradle plugin, etc.). + +> **Android 13 (API 33) and above:** You must declare `POST_NOTIFICATIONS` in your manifest +> and request it at runtime before notifications can be displayed. +> See the [Android documentation](https://developer.android.com/training/permissions/requesting). + +--- + +## Step 3 — Implement `FirebaseMessagingService` + +Create a `FirebaseMessagingService` subclass in your app's Android source and forward the two +FCM events to the plugin using `BluedotPushPlugin`: + +```kotlin +// android/app/src/main/kotlin/com/yourcompany/yourapp/MyFirebaseMessagingService.kt + +package com.yourcompany.yourapp + +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage +import io.bluedot.bluedot_point_sdk_push.BluedotPushPlugin + +class MyFirebaseMessagingService : FirebaseMessagingService() { + + override fun onNewToken(token: String) { + // Forward the new token to Bluedot. + BluedotPushPlugin.onNewFcmToken(token, this) + + // Add any other token-refresh handling here. + } + + override fun onMessageReceived(remoteMessage: RemoteMessage) { + // Let Bluedot handle its own messages first. + // Returns true if the message was a Bluedot push notification. + if (BluedotPushPlugin.onMessageReceived(remoteMessage, this)) return + + // Handle your own non-Bluedot FCM messages here. + } +} +``` + +--- + +## Step 4 — Register the service in `AndroidManifest.xml` + +Add the service declaration inside the `` tag of your +`android/app/src/main/AndroidManifest.xml`: + +```xml + + + + + +``` + +> The `AppPushNotificationsReceiver` (required for event callbacks to Flutter) is registered +> automatically by the plugin's own manifest — no additional entry is needed for it. + +--- + +## Step 5 — Listen for push notification events in Flutter + +Set up the event listener early in your app, before any notifications can arrive +(e.g. in `main.dart` or your root widget's `initState`): + +```dart +import 'package:flutter/services.dart'; +import 'package:bluedot_point_sdk_push/bluedot_point_sdk_push.dart'; + +void _initPushListener() { + const channel = MethodChannel(BluedotPointSdkPush.pushNotifications); + channel.setMethodCallHandler((call) async { + final data = Map.from(call.arguments as Map); + switch (call.method) { + case PushNotificationEvents.onNotificationReceived: + // Notification delivered to the device. + print('Received: ${data['title']} — ${data['body']}'); + print('Campaign: ${data['campaignId']}, Zone: ${data['zoneId']}'); + break; + case PushNotificationEvents.onNotificationClicked: + // User tapped the notification. + print('Clicked: ${data['notificationId']}'); + break; + } + }); +} +``` + +### Event payload fields + +| Field | Type | Description | +|------------------|----------------------|-----------------------------------------| +| `title` | `String` | Notification title | +| `body` | `String` | Notification body text | +| `pushVersion` | `String` | Push schema version | +| `campaignId` | `String` | Campaign UUID | +| `zoneId` | `String` | Zone UUID | +| `notificationId` | `String` | Notification UUID | +| `data` | `Map`| Custom key-value pairs from the payload | diff --git a/PointSDK-Flutter-Push/android/build.gradle b/PointSDK-Flutter-Push/android/build.gradle new file mode 100644 index 0000000..aafcaec --- /dev/null +++ b/PointSDK-Flutter-Push/android/build.gradle @@ -0,0 +1,75 @@ +group 'io.bluedot.bluedot_point_sdk_push' +version '1.0.0' + +buildscript { + ext.kotlin_version = '2.3.0' + ext.sdk_version = '18.0.0' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:9.0.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + mavenLocal() + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + namespace 'io.bluedot.bluedot_point_sdk_push' + java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + minSdk 29 + compileSdk 36 + } +} + +// --------------------------------------------------------------------------- +// Firebase BOM version +// +// The consumer app is responsible for applying the google-services plugin and +// placing google-services.json in their own app module. This library only +// needs the firebase-messaging artifact on the compile classpath; it does NOT +// need (or want) the google-services Gradle plugin. +// +// Override the BOM version from your app's build.gradle / gradle.properties: +// ext.firebaseBomVersion = '34.0.0' +// --------------------------------------------------------------------------- +def firebaseBomVersion = rootProject.hasProperty('firebaseBomVersion') ? + rootProject.property('firebaseBomVersion') : (project.hasProperty('firebaseBomVersion') ? + project.property('firebaseBomVersion') : '34.12.0') + +dependencies { + // Core Point SDK — must match the version used by the base plugin. + implementation "com.gitlab.bluedotio.android:point_sdk_android:$sdk_version" + + + // Push notifications module and its Firebase dependency. + // These are the ONLY place in the plugin ecosystem where these artifacts are declared, + // so they are only resolved for apps that add bluedot_point_sdk_push. + implementation "com.gitlab.bluedotio.android:point_sdk_push:$sdk_version" + implementation platform("com.google.firebase:firebase-bom:${firebaseBomVersion}") + implementation "com.google.firebase:firebase-messaging" +} + diff --git a/PointSDK-Flutter-Push/android/src/main/AndroidManifest.xml b/PointSDK-Flutter-Push/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8846970 --- /dev/null +++ b/PointSDK-Flutter-Push/android/src/main/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/AppPushNotificationsEventReceiver.kt b/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/AppPushNotificationsEventReceiver.kt new file mode 100644 index 0000000..9138b1a --- /dev/null +++ b/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/AppPushNotificationsEventReceiver.kt @@ -0,0 +1,40 @@ +package io.bluedot.pushnotifications + +import android.content.Context +import au.com.bluedot.point.api.push.model.RezolvePushData +import com.rezolve.pushnotifications.PushNotificationsEventReceiver + +/** + * Receives Bluedot push notification callbacks and forwards them to Flutter via + * [BluedotPushPlugin.pushNotificationsChannel]. + * + * Registered automatically in this plugin's AndroidManifest.xml — no manual + * manifest entry required in the consuming app. + */ +class AppPushNotificationsEventReceiver : PushNotificationsEventReceiver() { + + override fun onNotificationReceived(rezolvePushData: RezolvePushData, context: Context) { + BluedotPushPlugin.pushNotificationsChannel?.invokeMethod( + "onNotificationReceived", + rezolvePushData.toMap() + ) + } + + override fun onNotificationClicked(rezolvePushData: RezolvePushData, context: Context) { + BluedotPushPlugin.pushNotificationsChannel?.invokeMethod( + "onNotificationClicked", + rezolvePushData.toMap() + ) + } + + private fun RezolvePushData.toMap(): Map = mapOf( + "title" to title, + "body" to body, + "pushVersion" to pushVersion, + "campaignId" to campaignId, + "zoneId" to zoneId, + "notificationId" to notificationId, + "data" to data + ) +} + diff --git a/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/BluedotPushPlugin.kt b/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/BluedotPushPlugin.kt new file mode 100644 index 0000000..9b8ad5c --- /dev/null +++ b/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/BluedotPushPlugin.kt @@ -0,0 +1,101 @@ +package io.bluedot.pushnotifications + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import androidx.core.app.NotificationCompat +import au.com.bluedot.point.api.push.model.RezolvePushData +import au.com.bluedot.point.net.engine.ServiceManager +import com.google.firebase.messaging.RemoteMessage +import com.rezolve.pushnotifications.isRezolvePushNotification +import com.rezolve.pushnotifications.toRezolvePushData +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.MethodChannel.Result + +/** BluedotPushPlugin — the Flutter plugin class for the push notifications sub-module. */ +class BluedotPushPlugin : FlutterPlugin, MethodCallHandler { + + companion object { + /** Exposed so AppPushNotificationsReceiver can invoke push event callbacks. */ + @JvmStatic var pushNotificationsChannel: MethodChannel? = null + + /** + * Forward a new FCM token to the Bluedot push module. + * Call this from your FirebaseMessagingService.onNewToken(). + */ + @JvmStatic + fun onNewFcmToken(token: String, context: Context) { + ServiceManager.getInstance(context).pushNotificationsManager.onNewFcmToken(token) + } + + /** + * Forward an incoming FCM message to the Bluedot push module. + * Call this from your FirebaseMessagingService.onMessageReceived(). + * + * Returns true if the message was a Bluedot push notification and was handled, + * false if you should handle it yourself. + */ + @JvmStatic + fun onMessageReceived(remoteMessage: RemoteMessage, context: Context): Boolean { + if (remoteMessage.isRezolvePushNotification()) { + ServiceManager.getInstance(context).pushNotificationsManager.onMessageReceived(remoteMessage.toRezolvePushData()) + return true + } + return false + } + } + + private val PUSH_COMMAND_CHANNEL = "bluedot_point_flutter/push_sdk" + private val PUSH_EVENTS_CHANNEL = "bluedot_point_flutter/push_notification_events" + + private var commandChannel: MethodChannel? = null + private lateinit var context: Context + + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + if (commandChannel == null) { + commandChannel = MethodChannel(binding.binaryMessenger, PUSH_COMMAND_CHANNEL) + commandChannel!!.setMethodCallHandler(this) + } + if (pushNotificationsChannel == null) { + pushNotificationsChannel = MethodChannel(binding.binaryMessenger, PUSH_EVENTS_CHANNEL) + } + context = binding.applicationContext + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + commandChannel?.setMethodCallHandler(null) + commandChannel = null + } + + override fun onMethodCall(call: MethodCall, result: Result) { + when (call.method) { + "onNewFcmToken" -> { + val token = call.argument("token") ?: return result.error("INVALID_ARG", "token is required", null) + ServiceManager.getInstance(context).pushNotificationsManager.onNewFcmToken(token) + result.success(null) + } + "onMessageReceived" -> { + @Suppress("UNCHECKED_CAST") + val data = call.arguments>() ?: emptyMap() + val pushData = RezolvePushData( + title = data[RezolvePushData.NOTIFICATION_TITLE_KEY].orEmpty(), + body = data[RezolvePushData.NOTIFICATION_BODY_KEY].orEmpty(), + pushVersion = data[RezolvePushData.KEY_REZOLVE_PUSH_VERSION].orEmpty(), + campaignId = data[RezolvePushData.KEY_CAMPAIGN_ID].orEmpty(), + zoneId = data[RezolvePushData.KEY_ZONE_ID].orEmpty(), + notificationId = data[RezolvePushData.KEY_NOTIFICATION_ID].orEmpty(), + data = data.filterKeys { it !in RezolvePushData.KNOWN_KEYS } + ) + ServiceManager.getInstance(context).pushNotificationsManager.onMessageReceived(pushData) + result.success(null) + } + else -> result.notImplemented() + } + } +} diff --git a/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/DefaultMessagingService.kt b/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/DefaultMessagingService.kt new file mode 100644 index 0000000..4504503 --- /dev/null +++ b/PointSDK-Flutter-Push/android/src/main/kotlin/io/bluedot/pushnotifications/DefaultMessagingService.kt @@ -0,0 +1,59 @@ +package io.bluedot.pushnotifications + +import au.com.bluedot.point.net.engine.ServiceManager +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage +import com.rezolve.pushnotifications.isRezolvePushNotification +import com.rezolve.pushnotifications.toRezolvePushData + +/** + * Default FCM handler that forwards Bluedot push messages to the Bluedot Push SDK. + * + * Registered in the library manifest at [android:priority="-1"][intent-filter], so any + * [FirebaseMessagingService] the consumer app registers at the default priority (0) takes + * precedence and this service is never reached. + * + * ## Integration patterns + * + * ### Pattern A — automatic (recommended when not using @react-native-firebase/messaging) + * No extra work needed. This service handles FCM automatically. + * + * ### Pattern B — @react-native-firebase/messaging + * That library registers its own [FirebaseMessagingService] at priority 0, which pre-empts + * this service. Forward messages to Bluedot from your JS handlers instead: + * ``` + * messaging().onMessage(msg => PushNotifications.onMessageReceived(msg)); + * messaging().onTokenRefresh(token => PushNotifications.onNewFcmToken(token)); + * ``` + * + * ### Pattern C — multiple push sources (e.g. Airship + Bluedot) + * Create your own [FirebaseMessagingService] (default intent-filter priority 0). + * Android routes all FCM messages to your service; this service never fires. + * Forward Bluedot messages from your service: + * ```kotlin + * if (remoteMessage.isRezolvePushNotification()) { + * ServiceManager.getInstance(this) + * .pushNotificationsManager + * .onMessageReceived(remoteMessage.toRezolvePushData()) + * } + * ServiceManager.getInstance(this) + * .pushNotificationsManager + * .onNewFcmToken(token) // in onNewToken() + * ``` + */ +class DefaultMessagingService : FirebaseMessagingService() { + + override fun onMessageReceived(remoteMessage: RemoteMessage) { + if (remoteMessage.isRezolvePushNotification()) { + ServiceManager.getInstance(this).pushNotificationsManager.onMessageReceived(remoteMessage.toRezolvePushData()) + } + } + + override fun onNewToken(token: String) { + ServiceManager.getInstance(this).pushNotificationsManager.onNewFcmToken(token) + } + + companion object { + const val TAG = "DefaultMessagingService" + } +} diff --git a/PointSDK-Flutter-Push/ios/Classes/BluedotPointSdkPushPlugin.h b/PointSDK-Flutter-Push/ios/Classes/BluedotPointSdkPushPlugin.h new file mode 100644 index 0000000..64869ff --- /dev/null +++ b/PointSDK-Flutter-Push/ios/Classes/BluedotPointSdkPushPlugin.h @@ -0,0 +1,5 @@ +#import + +@interface BluedotPointSdkPushPlugin : NSObject +@end + diff --git a/PointSDK-Flutter-Push/ios/Classes/BluedotPointSdkPushPlugin.m b/PointSDK-Flutter-Push/ios/Classes/BluedotPointSdkPushPlugin.m new file mode 100644 index 0000000..63a7587 --- /dev/null +++ b/PointSDK-Flutter-Push/ios/Classes/BluedotPointSdkPushPlugin.m @@ -0,0 +1,17 @@ +#import "BluedotPointSdkPushPlugin.h" + +// Push notifications are Android-only. This iOS implementation is a no-op stub +// so the package can be included in cross-platform Flutter projects without errors. + +@implementation BluedotPointSdkPushPlugin + ++ (void)registerWithRegistrar:(NSObject *)registrar { + // No-op on iOS. +} + +- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { + result(FlutterMethodNotImplemented); +} + +@end + diff --git a/PointSDK-Flutter-Push/ios/bluedot_point_sdk_push.podspec b/PointSDK-Flutter-Push/ios/bluedot_point_sdk_push.podspec new file mode 100644 index 0000000..49df43f --- /dev/null +++ b/PointSDK-Flutter-Push/ios/bluedot_point_sdk_push.podspec @@ -0,0 +1,19 @@ +Pod::Spec.new do |s| + s.name = 'bluedot_point_sdk_push' + s.version = '2.1.2' + s.summary = 'Optional push notifications module for the Bluedot Point SDK Flutter plugin (Android only).' + s.description = <<-DESC + Optional push notifications module for the Bluedot Point SDK Flutter plugin. + Push notification support is Android-only; this podspec provides the required + no-op iOS stub so the package can be included in cross-platform Flutter projects. + DESC + s.homepage = 'https://bluedot.io' + s.license = { :file => '../LICENSE' } + s.author = { 'Bluedot Innovation' => 'help@bluedot.io' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '14.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } +end + diff --git a/PointSDK-Flutter-Push/lib/bluedot_point_sdk_push.dart b/PointSDK-Flutter-Push/lib/bluedot_point_sdk_push.dart new file mode 100644 index 0000000..e401c8a --- /dev/null +++ b/PointSDK-Flutter-Push/lib/bluedot_point_sdk_push.dart @@ -0,0 +1,104 @@ +import 'package:flutter/services.dart'; + +/// Called when a Bluedot push notification is received in the foreground. +typedef NotificationReceivedHandler = void Function(Map data); + +/// Called when the user taps a Bluedot push notification. +typedef NotificationClickedHandler = void Function(Map data); + +/// ### Receiving events +/// ```dart +/// BluedotPointSdkPush.instance.setNotificationListener( +/// onReceived: (data) => print('Received: $data'), +/// onClicked: (data) => print('Clicked: $data'), +/// ); +/// ``` +class BluedotPointSdkPush { + BluedotPointSdkPush._(); + static final instance = BluedotPointSdkPush._(); + + /// Event channel name for push notification callbacks. + /// + /// See [PushNotificationEvents] for the available event method names. + static const pushNotifications = 'bluedot_point_flutter/push_notification_events'; + + static const _eventsChannel = MethodChannel(pushNotifications); + static const _commandChannel = MethodChannel('bluedot_point_flutter/push_sdk'); + + /// Register callbacks for push notification events. + /// + /// Both parameters are optional — pass only the ones you need. + void setNotificationListener({ + NotificationReceivedHandler? onReceived, + NotificationClickedHandler? onClicked, + }) { + _eventsChannel.setMethodCallHandler((call) async { + final data = Map.from(call.arguments as Map); + switch (call.method) { + case PushNotificationEvents.onNotificationReceived: + onReceived?.call(data); + break; + case PushNotificationEvents.onNotificationClicked: + onClicked?.call(data); + break; + } + }); + } + + /// Remove all push notification listeners. + void removeNotificationListener() { + _eventsChannel.setMethodCallHandler(null); + } + + /// Forward a new FCM token to the Bluedot push module. + /// + /// Call this from your `FirebaseMessaging.instance.onTokenRefresh` listener + /// when your app manages FCM directly (e.g. via the `firebase_messaging` package). + /// + /// Android only — no-op on iOS. + Future onNewFcmToken(String token) async { + await _commandChannel.invokeMethod('onNewFcmToken', {'token': token}); + } + + /// Forward an incoming FCM message to the Bluedot push module. + /// + /// Call this from your `FirebaseMessaging.onMessage` / `onBackgroundMessage` handler + /// when your app manages FCM directly (e.g. via the `firebase_messaging` package). + /// Bluedot will silently ignore messages that are not Bluedot push notifications. + /// + /// Pass `remoteMessage.data` (the data payload map from the FCM message). + /// Bluedot push notifications carry all fields inside the data payload, so + /// the notification title/body and Bluedot-specific fields are all present there. + /// + /// Example: + /// ```dart + /// FirebaseMessaging.onMessage.listen((remoteMessage) { + /// BluedotPointSdkPush.instance.onMessageReceived(remoteMessage.data); + /// }); + /// ``` + /// + /// Android only — no-op on iOS. + Future onMessageReceived(Map message) async { + await _commandChannel.invokeMethod('onMessageReceived', message); + } +} + +/// Event method names fired on the [BluedotPointSdkPush.pushNotifications] +/// channel. +/// +/// `call.arguments` is a `Map` with the following fields: +/// +/// | Field | Type | Description | +/// |------------------|---------------------|------------------------------------| +/// | `title` | `String` | Notification title | +/// | `body` | `String` | Notification body text | +/// | `pushVersion` | `String` | Push schema version | +/// | `campaignId` | `String` | Campaign UUID | +/// | `zoneId` | `String` | Zone UUID | +/// | `notificationId` | `String` | Notification UUID | +/// | `data` | `Map`| Custom key-value pairs from payload| +class PushNotificationEvents { + static const onNotificationReceived = 'onNotificationReceived'; + static const onNotificationClicked = 'onNotificationClicked'; +} + diff --git a/PointSDK-Flutter-Push/pubspec.lock b/PointSDK-Flutter-Push/pubspec.lock new file mode 100644 index 0000000..7b69331 --- /dev/null +++ b/PointSDK-Flutter-Push/pubspec.lock @@ -0,0 +1,71 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + bluedot_point_sdk: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + url: "https://pub.dev" + source: hosted + version: "1.4.1" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + url: "https://pub.dev" + source: hosted + version: "0.13.0" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" +sdks: + dart: ">=3.9.0-0 <4.0.0" + flutter: ">=3.0.0" diff --git a/PointSDK-Flutter-Push/pubspec.yaml b/PointSDK-Flutter-Push/pubspec.yaml new file mode 100644 index 0000000..9461ad0 --- /dev/null +++ b/PointSDK-Flutter-Push/pubspec.yaml @@ -0,0 +1,26 @@ +name: bluedot_point_sdk_push +description: > + Optional push notifications module for the Bluedot Point SDK Flutter plugin. + Adds Firebase Cloud Messaging support via the Bluedot pushnotifications module. + Android only. +version: 2.1.1 +homepage: "https://bluedot.io" + +environment: + sdk: '>=3.0.0 <4.0.0' + flutter: '>=3.0.0' + +dependencies: + flutter: + sdk: flutter + bluedot_point_sdk: ^2.1.1 + +flutter: + plugin: + platforms: + android: + package: io.bluedot.pushnotifications + pluginClass: BluedotPushPlugin + ios: + pluginClass: BluedotPointSdkPushPlugin + diff --git a/android/build.gradle b/android/build.gradle index c96e472..f627d58 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -3,7 +3,7 @@ version '2.1.2' buildscript { ext.kotlin_version = '2.3.0' - ext.sdk_version = '17.4.1' + ext.sdk_version = '18.0.0' repositories { google() mavenCentral() @@ -15,6 +15,7 @@ buildscript { } } + rootProject.allprojects { repositories { mavenLocal() @@ -48,7 +49,4 @@ android { dependencies { implementation "com.gitlab.bluedotio.android:point_sdk_android:$sdk_version" - - //NOTE: This is used when building with MavenLocal. - //implementation "com.github.Bluedot-Innovation:pointsdk:1262" } diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 217920b..3412ad7 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,6 +1,17 @@ + + ?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? = null + override fun getType(uri: Uri): String? = null + override fun insert(uri: Uri, values: ContentValues?): Uri? = null + override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int = 0 + override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?): Int = 0 +} + diff --git a/android/src/main/kotlin/io/bluedot/bluedot_point_sdk/BluedotPointSdkPlugin.kt b/android/src/main/kotlin/io/bluedot/bluedot_point_sdk/BluedotPointSdkPlugin.kt index 4f9f2d2..72c55f7 100644 --- a/android/src/main/kotlin/io/bluedot/bluedot_point_sdk/BluedotPointSdkPlugin.kt +++ b/android/src/main/kotlin/io/bluedot/bluedot_point_sdk/BluedotPointSdkPlugin.kt @@ -9,7 +9,7 @@ import android.content.Intent import android.graphics.Color import android.os.Build import androidx.core.app.NotificationCompat -import au.com.bluedot.point.CustomEventMetaDataSetError +import au.com.bluedot.point.error.CustomEventMetaDataSetError import au.com.bluedot.point.net.engine.* import au.com.bluedot.point.net.engine.ZoneInfo import io.flutter.embedding.engine.plugins.FlutterPlugin @@ -87,7 +87,7 @@ class BluedotPointSdkPlugin: FlutterPlugin, MethodCallHandler { "getInstallRef" -> result.success(serviceManager.installRef) "getSDKVersion" -> result.success(serviceManager.sdkVersion) "getZonesAndFences" -> getZonesAndFences(serviceManager.zonesAndFences, result) - "getCustomEventMetaData" -> result.success(serviceManager.getCustomEventMetaData()) + "getCustomEventMetaData" -> result.success(serviceManager.customEventMetaData) else -> { result.notImplemented() } @@ -200,7 +200,7 @@ class BluedotPointSdkPlugin: FlutterPlugin, MethodCallHandler { private fun setCustomEventMetaData(call: MethodCall, result: Result) { val metadata = call.arguments as HashMap try { - serviceManager.setCustomEventMetaData(metadata) + serviceManager.customEventMetaData = metadata result.success(null) } catch (err: Error) { result.error(CustomEventMetaDataSetError().errorCode.toString(), err.message, err.toString()) diff --git a/example b/example index ed3fc26..a9b7122 160000 --- a/example +++ b/example @@ -1 +1 @@ -Subproject commit ed3fc26634bab41690455b4581a11fef66b4192d +Subproject commit a9b71225b9fa0c2b000ba02819cfd377bb4218a3