Skip to content

Commit

Permalink
feat/Update dependencies and add HMS support
Browse files Browse the repository at this point in the history
  • Loading branch information
FrantisekGazo committed Mar 24, 2022
1 parent b591022 commit d9d888e
Show file tree
Hide file tree
Showing 78 changed files with 932 additions and 575 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
## Release Notes
## Release Notes for 1.0.0
#### March 23, 2022
* Features
* Flutter SDK upgraded to 2.10
* Native Android SDK updated to 3.0.3 - [Android SDK Release notes](https://github.com/exponea/exponea-android-sdk/blob/3.0.3/Documentation/RELEASE_NOTES.md)
* Native iOS SDK updated to 2.11.3 - [iOS SDK Release notes](https://github.com/exponea/exponea-ios-sdk/blob/2.11.3/Documentation/RELEASE_NOTES.md)

## Release Notes for 0.2.1
#### August 12, 2021
* Fixes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Flutter Exponea SDK - Beta version
# Flutter Exponea SDK
Flutter Exponea SDK allows your application to interact with the [Exponea](https://exponea.com/) Customer Data & Experience Platform. Exponea empowers B2C marketers to raise conversion rates, improve acquisition ROI, and maximize customer lifetime value.

Flutter SDK is implemented as a wrapper around [native Android SDK](https://github.com/exponea/exponea-android-sdk) and [native iOS SDK](https://github.com/exponea/exponea-ios-sdk).
Expand Down
14 changes: 14 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
include: package:flutter_lints/flutter.yaml

linter:
rules:
avoid_void_async: true
parameter_assignments: true
prefer_final_in_for_each: true
# override defaults from flutter_lints :
avoid_renaming_method_parameters: false
unnecessary_this: false

analyzer:
errors:
parameter_assignments: error
12 changes: 5 additions & 7 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ version '1.0.0-SNAPSHOT'
buildscript {
ext {
androidGradlePluginVersion = '4.1.0'
kotlinVersion = '1.3.50'
kotlinVersion = '1.5.30'

exponeaSdkVersion = '2.9.5'
exponeaSdkVersion = '3.0.3'
gsonVersion = '2.8.6'
}

repositories {
google()
jcenter()
mavenCentral()
}

dependencies {
Expand All @@ -24,15 +24,15 @@ buildscript {
rootProject.allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 30
compileSdkVersion 31

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand All @@ -47,6 +47,4 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation "com.exponea.sdk:sdk:$exponeaSdkVersion"
implementation "com.google.code.gson:gson:$gsonVersion"

testImplementation 'junit:junit:4.12'
}
3 changes: 1 addition & 2 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@

<uses-permission android:name="android.permission.INTERNET"/>

<meta-data android:name="ExponeaFlutterSDK" android:value="true" />

<application>
<meta-data android:name="ExponeaFlutterSDK" android:value="true" />
<receiver
android:name=".ExponeaPushReceiver"
android:enabled="true"
Expand Down
36 changes: 34 additions & 2 deletions android/src/main/kotlin/com/exponea/ExponeaPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.exponea

import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.os.Handler
Expand Down Expand Up @@ -45,8 +46,39 @@ class ExponeaPlugin : FlutterPlugin, ActivityAware {
private const val STREAM_NAME_OPENED_PUSH = "$CHANNEL_NAME/opened_push"
private const val STREAM_NAME_RECEIVED_PUSH = "$CHANNEL_NAME/received_push"

fun handleCampaignIntent(intent: Intent?, context: Context) {
Exponea.handleCampaignIntent(intent, context)
fun handleCampaignIntent(intent: Intent?, applicationContext: Context) {
Log.d(TAG, "handleCampaignIntent()")
Exponea.handleCampaignIntent(intent, applicationContext)
}

fun handleRemoteMessage(
applicationContext: Context,
messageData: Map<String, String>?,
manager: NotificationManager,
showNotification: Boolean = true
) {
Log.d(TAG, "handleRemoteMessage()")
Exponea.handleRemoteMessage(applicationContext, messageData, manager, showNotification)
}

fun trackGmsPushToken(token: String) {
Log.d(TAG, "trackGmsPushToken($token)")
Exponea.trackPushToken(token)
}

fun trackHmsPushToken(token: String) {
Log.d(TAG, "trackHmsPushToken($token)")
Exponea.trackHmsPushToken(token)
}

fun handleNewGmsToken(context: Context, token: String) {
Log.d(TAG, "handleNewGmsToken($token)")
Exponea.handleNewToken(context, token)
}

fun handleNewHmsToken(context: Context, token: String) {
Log.d(TAG, "handleNewHmsToken($token)")
Exponea.handleNewHmsToken(context, token)
}
}

Expand Down
20 changes: 8 additions & 12 deletions android/src/main/kotlin/com/exponea/ExponeaPushReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import android.content.Context
import android.content.Intent
import com.exponea.data.OpenedPush
import com.exponea.data.PushAction
import com.exponea.sdk.ExponeaExtras
import com.exponea.sdk.models.NotificationAction
import com.exponea.sdk.services.ExponeaPushReceiver
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.lang.RuntimeException

class ExponeaPushReceiver : BroadcastReceiver() {
/**
Expand All @@ -20,20 +19,17 @@ class ExponeaPushReceiver : BroadcastReceiver() {
*/
override fun onReceive(context: Context, intent: Intent) {
val action = when (intent.action) {
ExponeaPushReceiver.ACTION_CLICKED -> PushAction.APP
ExponeaPushReceiver.ACTION_DEEPLINK_CLICKED -> PushAction.DEEPLINK
ExponeaPushReceiver.ACTION_URL_CLICKED -> PushAction.WEB
ExponeaExtras.ACTION_CLICKED -> PushAction.APP
ExponeaExtras.ACTION_DEEPLINK_CLICKED -> PushAction.DEEPLINK
ExponeaExtras.ACTION_URL_CLICKED -> PushAction.WEB
else -> throw RuntimeException("Unknown push notification action ${intent.action}")
}
val url = (intent.getSerializableExtra(ExponeaPushReceiver.EXTRA_ACTION_INFO) as? NotificationAction)?.url
val pushData = intent.getSerializableExtra(ExponeaPushReceiver.EXTRA_CUSTOM_DATA) as Map<String, String>

val actionInfo = intent.getSerializableExtra(ExponeaExtras.EXTRA_ACTION_INFO) as? NotificationAction
val url = actionInfo?.url
val pushData = intent.getSerializableExtra(ExponeaExtras.EXTRA_CUSTOM_DATA) as Map<String, String>
val additionalDataType = object : TypeToken<Map<String, Any?>?>() {}.getType()
val additionalData = Gson().fromJson(pushData["attributes"], additionalDataType) as Map<String, Any?>?
OpenedPushStreamHandler.handle(OpenedPush(action, url, additionalData))

if (intent.action == ExponeaPushReceiver.ACTION_CLICKED) {
val actionIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
context.startActivity(actionIntent)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.exponea.sdk.models.ExponeaProject
import java.lang.Exception

@Suppress("UNCHECKED_CAST")
internal class ExponeaConfigurationParser {
class ExponeaConfigurationParser {
fun parseConfig(map: Map<String, Any?>): ExponeaConfiguration {
return ExponeaConfiguration().apply {
projectToken = map.getRequired("projectToken")
Expand Down
131 changes: 119 additions & 12 deletions documentation/PUSH_ANDROID.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,133 @@ We rely on our native SDK to do push tracking. For more complex scenarios(multip

> Exponea Android SDK contains self-check functionality to help you successfully setup push notifications. Self-check will try to track push token, request Exponea backend to send silent push to the device and check the app is ready to open push notifications. To enable self-check call `ExponeaPlugin().checkPushSetup()` **before** configuring the SDK.
## Integrating Firebase to your project
To send/receive push notifications you have to setup Firebase project. [Official Firebase documentation](https://firebase.google.com/docs/android/setup#console) describes this process. You'll need to create a project in Firebase console, add generated `google-services.json` to your app and update gradle scripts.
## Push Integrations
Exponea Android SDK supports these integrations:

> When following the Firebase documentation, the root of your Android project is `/android`
- [Standard (Firebase) integration](#firebase-integration)
- [Huawei integration](#huawei-integration)

## Firebase integration

### Integrating Firebase into your project
To send/receive push notifications, you have to set up the Firebase project. [Official Firebase documentation](https://firebase.google.com/docs/android/setup#console) describes this process. You'll need to create a project in the Firebase console, add generated `google-services.json` to your app and update Gradle scripts.

> When following the Firebase documentation, the root of your Android project is `/android`.
#### Checklist:
- `google-services.json` file downloaded from Firebase console is in the **android/app** folder of your Android project e.g. *android/app/google-services.json*
- `google-services.json` file downloaded from the Firebase console is in the **android/app** folder of your Android project e.g., *android/app/google-services.json*
- your **android/app** folder gradle build file(*android/app/build.gradle*) contains `apply plugin: 'com.google.gms.google-services'`
- your **android** folder gradle build file(*android/build.gradle*) has `classpath 'com.google.gms:google-services:X.X.X'` listed in build script dependencies.

### Passing token and messages to Exponea SDK
To handle incomming push messages, you will have to create your `FirebaseMessagingService` implementation and register it in your `AndroidManifest.xml`. Then, call `handleRemoteMessage` in `onMessageReceived` method and `handleNewGmsToken` in `onNewToken` method, like in example code below:

```kotlin
import android.app.NotificationManager
import android.content.Context
import com.exponea.ExponeaPlugin
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class MessageService : FirebaseMessagingService() {
private val notificationManager by lazy {
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
ExponeaPlugin.handleRemoteMessage(applicationContext, message.data, notificationManager)
}

override fun onNewToken(token: String) {
super.onNewToken(token)
ExponeaPlugin.handleNewGmsToken(applicationContext, token)
}
}
```

Registering in AndroidManifest.xml
```xml
...
<application>
<service android:name=".MessageService" android:exported="false" >
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
...
```

## Setting the Firebase server key in the Exponea web app
You'll need to set the Firebase server key so Exponea can use it to send push notification to your application. Our native Android has a [guide describing how to do so](https://github.com/exponea/exponea-android-sdk/blob/develop/Guides/FIREBASE.md).
### Setting the Firebase server key in the Exponea web app
You'll need to set the Firebase server key so Exponea can use it to send push notifications to your application. Our native Android has a [guide describing how to do so](https://github.com/exponea/exponea-android-sdk/blob/develop/Guides/FIREBASE.md).

### That's it
After these steps, you should be able to receive push notifications from Exponea. To learn how to send one, check a [Sending Push notifications guide](./PUSH_SEND.md).

## That's it
After these steps you should be able to receive push notifications from Exponea. To learn how to send one, check a [Sending Push notifications guide](./PUSH_SEND.md).
## Huawei integration
Newer phones manufactured by [Huawei](https://huaweimobileservices.com/) come with Huawei Mobile Services (HMS). It's a service used to deliver push _instead of_ Google's Firebase Cloud Messaging (FCM).

### Integrating HMS into your project
To send/receive push notifications, you have to:
1. register and set up a [Huawei Developer account](https://developer.huawei.com/consumer/en/console)
2. create a project and App in AppGallery Connect
3. generate and configure a Signing Certificate
4. enable push kit in AppGallery Connect APIs
5. update Gradle scripts and add generated `agconnect-services.json` to your app
6. configure the Signing Information in your app

Steps 2-6 are described in detail in the official [Huawei documentation](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0)

### Passing token and messages to Exponea SDK
To handle incomming push messages, you will have to create your `HmsMessageService` implementation and register it in your `AndroidManifest.xml`. Then, call `handleRemoteMessage` in `onMessageReceived` method and `handleNewHmsToken` in `onNewToken` method, like in example code below:

```kotlin
import android.app.NotificationManager
import android.content.Context
import com.exponea.ExponeaPlugin
import com.huawei.hms.push.HmsMessageService
import com.huawei.hms.push.RemoteMessage

class MessageService : HmsMessageService() {

private val notificationManager by lazy {
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
ExponeaPlugin.handleRemoteMessage(applicationContext, message.dataOfMap, notificationManager)
}

override fun onNewToken(token: String) {
super.onNewToken(token)
ExponeaPlugin.handleNewHmsToken(applicationContext, token)
}
}
```
Registering in AndroidManifest.xml
```xml
...
<application>
<service android:name=".MessageService" android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT"/>
</intent-filter>
</service>
<meta-data android:name="push_kit_auto_init_enabled" android:value="true"/>
</application>
...
```

### That's it
After these steps, you should be able to receive push notifications from Exponea. To learn how to send one, check a [Sending Push notifications guide](./PUSH_SEND.md).

## Deeplinking
You can use `ExponeaPlugin().openedPushStream` to define a listener that will respond to push notifications. In case you'd like to use deeplinking, you'll need to update your `AndroidManifest` in `android/src/main` a bit.
You can use `ExponeaPlugin().openedPushStream` to define a listener that will respond to push notifications. If you'd like to use deep-linking, you'll need to update your `AndroidManifest` in `android/src/main` a bit.

### Set activity to to single task launch mode
By default Android will launch a new activity for your application when deeplink is opened, you want to override this by setting `android:launchMode="singleTask"` for your main activity.
### Set activity to single task launch mode
By default, Android will launch a new activity for your application when a deep-link is opened. You want to override this by setting `android:launchMode="singleTask"` for your main activity.
``` xml
<activity
android:name=".MainActivity"
Expand All @@ -33,7 +139,8 @@ By default Android will launch a new activity for your application when deeplink
```

### Define an intent filter
You'll have to define an intent filter that can respond to url you define when creating push notification. You can either use a custom scheme, or an URL. You can find more information in official [Android documentation](https://developer.android.com/training/app-links/deep-linking#adding-filters).
You'll have to define an intent filter that can respond to URL you define when creating a push notification. You can either use a custom scheme or an URL. You can find more information in the official [Android documentation](https://developer.android.com/training/app-links/deep-linking#adding-filters).

```xml
<activity ...>
...
Expand Down
49 changes: 49 additions & 0 deletions documentation/VERSION_UPDATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Version update
This guide will help you upgrade your Exponea SDK to the new version.

## Updating from version 0.x.x to 1.x.x
Changes you will need to do when updating Exponea SDK to version 1 and higher are related to firebase push notifications.

### Changes regarding FirebaseMessagingService
We decided not to include the implementation of FirebaseMessagingService in our SDK since we want to keep it as small as possible and avoid including the libraries that are not essential for its functionality. SDK no longer has a dependency on the firebase library. Changes you will need to do are as follows:

1. You will need to implement `FirebaseMessagingService` on your android application side.
2. Call `ExponeaPlugin.handleRemoteMessage` when a message is received
3. Call `ExponeaPlugin.handleNewGmsToken` when a token is obtained
4. Register this service in your `AndroidManifest.xml`

```kotlin
import android.app.NotificationManager
import android.content.Context
import com.exponea.ExponeaPlugin
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class MessageService : FirebaseMessagingService() {
private val notificationManager by lazy {
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
ExponeaPlugin.handleRemoteMessage(applicationContext, message.data, notificationManager)
}

override fun onNewToken(token: String) {
super.onNewToken(token)
ExponeaPlugin.handleNewGmsToken(applicationContext, token)
}
}
```

```xml
...
<application>
<service android:name=".MessageService" android:exported="false" >
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
...
```
Loading

0 comments on commit d9d888e

Please sign in to comment.