Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,29 @@ compile 'com.iterable:iterableapi:3.0.5'
compile 'com.google.firebase:firebase-messaging:X.X.X' // Min version 9.0.0
```

See [Bintray](https://bintray.com/davidtruong/maven/Iterable-SDK) for the latest version of the Iterable Android SDK.
See [Bintray](https://bintray.com/davidtruong/maven/Iterable-SDK) for the latest version of the Iterable Android SDK.

#### Handling Firebase push messages and tokens

The SDK adds a FirebaseMessagingService and FirebaseInstanceIdService to the app manifest automatically, so you don't have to do any extra setup to handle incoming push messages.
If your application implements its own FirebaseMessagingService, make sure you forward `onMessageReceived` and `onNewToken` calls to `IterableFirebaseMessagingService.handleMessageReceived` and `IterableFirebaseInstanceIDService.handleTokenRefresh`, respectively:

```java
public class MyFirebaseMessagingService extends FirebaseMessagingService {

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
IterableFirebaseMessagingService.handleMessageReceived(this, remoteMessage);
}

@Override
public void onNewToken(String s) {
IterableFirebaseInstanceIDService.handleTokenRefresh();
}
}
```

Note that `FirebaseInstanceIdService` is deprecated and replaced with `onNewToken` in recent versions of Firebase.

# Using the SDK

Expand Down
4 changes: 2 additions & 2 deletions iterableapi/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
<service
android:name="com.iterable.iterableapi.IterableFirebaseMessagingService"
android:exported="false">
<intent-filter>
<intent-filter android:priority="-1">
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>

<service
android:name="com.iterable.iterableapi.IterableFirebaseInstanceIDService"
android:exported="false">
<intent-filter>
<intent-filter android:priority="-1">
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,10 @@ public void updateUser(JSONObject dataFields) {
* user email or user ID is set before calling this method.
*/
public void registerForPush() {
if (!checkSDKInitialization()) {
return;
}

if (config.pushIntegrationName == null) {
IterableLogger.e(TAG, "registerForPush: pushIntegrationName is not set");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ public class IterableFirebaseInstanceIDService extends FirebaseInstanceIdService

@Override
public void onTokenRefresh() {
handleTokenRefresh();
}

/**
* Handles token refresh
* Call this from a custom {@link FirebaseInstanceIdService} to register the new token with Iterable
*/
public static void handleTokenRefresh() {
String registrationToken = FirebaseInstanceId.getInstance().getToken();
IterableLogger.d(TAG, "New Firebase Token generated: " + registrationToken);
IterableApi.getInstance().registerForPush();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.iterable.iterableapi;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;

Expand All @@ -18,40 +15,54 @@ public class IterableFirebaseMessagingService extends FirebaseMessagingService {

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData().size() > 0) {
Map<String,String> messageData = remoteMessage.getData();
handlePushReceived(messageData);
IterableLogger.d(TAG, "Message data payload: " + remoteMessage.getData());
handleMessageReceived(this, remoteMessage);
}

/**
* Handles receiving an incoming push notification from the intent.
*
* Call this from a custom {@link FirebaseMessagingService} to pass Iterable push messages to
* Iterable SDK for tracking and rendering
* @param remoteMessage Remote message received from Firebase in
* {@link FirebaseMessagingService#onMessageReceived(RemoteMessage)}
* @return Boolean indicating whether it was an Iterable message or not
*/
public static boolean handleMessageReceived(Context context, RemoteMessage remoteMessage) {
Map<String,String> messageData = remoteMessage.getData();

if (messageData == null || messageData.size() == 0) {
return false;
}

IterableLogger.d(TAG, "Message data payload: " + remoteMessage.getData());
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
IterableLogger.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}

/**
* Handles receiving an incoming push notification from the intent.
* @param messageData
*/
private void handlePushReceived(Map<String,String> messageData) {
Bundle extras = new Bundle();
for (Map.Entry<String, String> entry : messageData.entrySet()) {
extras.putString(entry.getKey(), entry.getValue());
}

if (!IterableNotificationBuilder.isIterablePush(extras)) {
IterableLogger.d(TAG, "Not an Iterable push message");
return false;
}

if (!IterableNotificationBuilder.isGhostPush(extras)) {
if (!IterableNotificationBuilder.isEmptyBody(extras)) {
IterableLogger.d(TAG, "Iterable push received " + messageData);
IterableNotificationBuilder notificationBuilder = IterableNotificationBuilder.createNotification(
getApplicationContext(), extras);
context.getApplicationContext(), extras);
new IterableNotificationManager().execute(notificationBuilder);
} else {
IterableLogger.d(TAG, "Iterable OS notification push received");
}
} else {
IterableLogger.d(TAG, "Iterable ghost silent push received");
}
return true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ private static int getIconId(Context context) {
return iconId;
}

static boolean isIterablePush(Bundle extras) {
return extras != null && extras.containsKey(IterableConstants.ITERABLE_DATA_KEY);
}

/**
* Returns if the given notification is a ghost/silent push notification
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,24 @@
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.MockRepository;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ServiceController;

import java.util.HashMap;
import java.util.Map;

import okhttp3.mockwebserver.MockWebServer;

import static com.iterable.iterableapi.unit.IterableTestUtils.bundleToMap;
import static com.iterable.iterableapi.unit.IterableTestUtils.getMapFromJsonResource;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
Expand Down Expand Up @@ -72,15 +78,18 @@ public void tearDown() throws Exception {
@Test
public void testOnMessageReceived() throws Exception {
PowerMockito.mockStatic(IterableNotificationBuilder.class);
Mockito.when(IterableNotificationBuilder.isIterablePush(any(Bundle.class))).thenCallRealMethod();

RemoteMessage.Builder builder = new RemoteMessage.Builder("1234@gcm.googleapis.com");
builder.setData(getMapFromJsonResource("push_payload_custom_action.json"));
builder.addData(IterableConstants.ITERABLE_DATA_KEY, IterableTestUtils.getResourceString("push_payload_custom_action.json"));
controller.get().onMessageReceived(builder.build());

PowerMockito.verifyStatic(IterableNotificationBuilder.class);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
IterableNotificationBuilder.createNotification(eq(RuntimeEnvironment.application), bundleCaptor.capture());
assertTrue(bundleToMap(bundleCaptor.getValue()).equals(getMapFromJsonResource("push_payload_custom_action.json")));
Map<String, String> expectedPayload = new HashMap<>();
expectedPayload.put(IterableConstants.ITERABLE_DATA_KEY, IterableTestUtils.getResourceString("push_payload_custom_action.json"));
assertEquals(expectedPayload, bundleToMap(bundleCaptor.getValue()));
}

}