Skip to content

Commit b8420c7

Browse files
authored
Merge pull request #12 from Iterable/feature/ITBL-1090-FCM-upgrade
Feature/itbl 1090 fcm upgrade
2 parents afbb3bb + d2cc75d commit b8420c7

9 files changed

+398
-171
lines changed

iterableapi/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ dependencies {
2323
testCompile 'junit:junit:4.12'
2424
compile 'com.android.support:appcompat-v7:23.2.1'
2525
compile 'com.google.android.gms:play-services-gcm:9.0.2'
26+
compile 'com.google.firebase:firebase-messaging:9.0.2'
2627
compile 'com.android.support:support-annotations:23.2.1'
2728
compile 'com.squareup.picasso:picasso:2.5.2'
2829
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.iterable.iterableapi;
2+
3+
import android.app.Application;
4+
import android.content.Context;
5+
import android.content.SharedPreferences;
6+
import android.test.ApplicationTestCase;
7+
8+
/**
9+
* Tests
10+
* Created by David Truong [email protected].
11+
*/
12+
public class IterablePushRegistrationTest extends ApplicationTestCase<Application> {
13+
public IterablePushRegistrationTest() {
14+
super(Application.class);
15+
}
16+
17+
Context appContext;
18+
IterableApi iterableApi;
19+
String senderID = "111111111111";
20+
21+
public void setUp() throws Exception {
22+
super.setUp();
23+
24+
appContext = getContext().getApplicationContext();
25+
iterableApi = IterableApi.sharedInstanceWithApiKey(appContext, "fake_key", "test_email");
26+
27+
SharedPreferences sharedPref = appContext.getSharedPreferences(IterableConstants.PUSH_APP_ID, Context.MODE_PRIVATE);
28+
SharedPreferences.Editor editor = sharedPref.edit();
29+
editor.remove(IterableConstants.PUSH_APP_ID);
30+
editor.commit();
31+
}
32+
33+
/**
34+
* Tests getting a token for GCM
35+
* @throws Exception
36+
*/
37+
public void testGetGCMToken() throws Exception {
38+
IterablePushRegistration registration = new IterablePushRegistration();
39+
IterablePushRegistration.PushRegistrationObject registrationObject = registration.getDeviceToken(senderID, IterableConstants.MESSAGING_PLATFORM_GOOGLE, "test_application_GCM", false);
40+
assertNotNull(registrationObject.token);
41+
assertEquals(IterableConstants.MESSAGING_PLATFORM_GOOGLE, registrationObject.messagingPlatform);
42+
43+
SharedPreferences sharedPref = appContext.getSharedPreferences(IterableConstants.PUSH_APP_ID, Context.MODE_PRIVATE);
44+
String pushIdPref = sharedPref.getString(IterableConstants.PUSH_APP_ID, null);
45+
assertNull(pushIdPref);
46+
}
47+
48+
/**
49+
* Tests getting a token for FCM. Defaults to GCM if the project hasn't upgraded to Firebase and included the google-services.json
50+
* Checks the sharedPref flag that is set after upgrading to firebase.
51+
* @throws Exception
52+
*/
53+
public void testGetFCMToken() throws Exception {
54+
IterablePushRegistration registration = new IterablePushRegistration();
55+
SharedPreferences sharedPref;
56+
String pushIdPref;
57+
IterablePushRegistration.PushRegistrationObject registrationObject = registration.getDeviceToken(senderID, IterableConstants.MESSAGING_PLATFORM_FIREBASE, "test_application_FCM", false);
58+
assertNotNull(registrationObject.token);
59+
if (IterablePushRegistration.getFirebaseResouceId(appContext) != 0) {
60+
//FCM registration
61+
sharedPref = appContext.getSharedPreferences(IterableConstants.PUSH_APP_ID, Context.MODE_PRIVATE);
62+
pushIdPref = sharedPref.getString(IterableConstants.PUSH_APP_ID, null);
63+
assertNotNull(pushIdPref);
64+
assertEquals(IterableConstants.MESSAGING_PLATFORM_FIREBASE, registrationObject.messagingPlatform);
65+
66+
} else {
67+
//GCM registration
68+
sharedPref = appContext.getSharedPreferences(IterableConstants.PUSH_APP_ID, Context.MODE_PRIVATE);
69+
pushIdPref = sharedPref.getString(IterableConstants.PUSH_APP_ID, null);
70+
assertNull(pushIdPref);
71+
assertEquals(IterableConstants.MESSAGING_PLATFORM_GOOGLE, registrationObject.messagingPlatform);
72+
}
73+
}
74+
}

iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java

Lines changed: 85 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import android.content.Context;
55
import android.content.Intent;
66
import android.content.SharedPreferences;
7-
import android.net.Uri;
87
import android.os.Build;
98
import android.os.Bundle;
109

@@ -313,15 +312,30 @@ public boolean isIterableIntent(Intent intent) {
313312
}
314313

315314
/**
316-
* Registers an existing GCM device token with Iterable.
317-
* Recommended to use registerForPush if you do not already have a deviceToken
315+
* Registers a device token with Iterable.
318316
* @param applicationName
319317
* @param token
320318
*/
321319
public void registerDeviceToken(String applicationName, String token) {
322320
registerDeviceToken(applicationName, token, null);
323321
}
324322

323+
/**
324+
* Registers a device token with Iterable.
325+
* @param applicationName
326+
* @param token
327+
* @param pushServicePlatform
328+
*/
329+
public void registerDeviceToken(final String applicationName, final String token, final String pushServicePlatform) {
330+
if (token != null) {
331+
new Thread(new Runnable() {
332+
public void run() {
333+
registerDeviceToken(applicationName, token, pushServicePlatform, null);
334+
}
335+
}).start();
336+
}
337+
}
338+
325339
/**
326340
* Track an event.
327341
* @param eventName
@@ -470,20 +484,40 @@ public void updateUser(JSONObject dataFields) {
470484
* @param gcmProjectNumber
471485
*/
472486
public void registerForPush(String iterableAppId, String gcmProjectNumber) {
473-
registerForPush(iterableAppId, gcmProjectNumber, false);
487+
registerForPush(iterableAppId, gcmProjectNumber, IterableConstants.MESSAGING_PLATFORM_GOOGLE);
488+
}
489+
490+
/**
491+
* Registers for push notifications.
492+
* @param iterableAppId
493+
* @param projectNumber
494+
* @param pushServicePlatform
495+
*/
496+
public void registerForPush(String iterableAppId, String projectNumber, String pushServicePlatform) {
497+
IterablePushRegistrationData data = new IterablePushRegistrationData(iterableAppId, projectNumber, pushServicePlatform, IterablePushRegistrationData.PushRegistrationAction.ENABLE);
498+
new IterablePushRegistration().execute(data);
474499
}
475500

476501
/**
477502
* Disables the device from push notifications
478503
*
479-
* The disablePush call first calls registerForPush to obtain the device's registration token.
480-
* Then it calls the disablePush api endpoint.
481-
*
482504
* @param iterableAppId
483505
* @param gcmProjectNumber
484506
*/
485507
public void disablePush(String iterableAppId, String gcmProjectNumber) {
486-
registerForPush(iterableAppId, gcmProjectNumber, true);
508+
disablePush(iterableAppId, gcmProjectNumber, IterableConstants.MESSAGING_PLATFORM_GOOGLE);
509+
}
510+
511+
/**
512+
* Disables the device from push notifications
513+
*
514+
* @param iterableAppId
515+
* @param projectNumber
516+
* @param pushServicePlatform
517+
*/
518+
public void disablePush(String iterableAppId, String projectNumber, String pushServicePlatform) {
519+
IterablePushRegistrationData data = new IterablePushRegistrationData(iterableAppId, projectNumber, pushServicePlatform, IterablePushRegistrationData.PushRegistrationAction.DISABLE);
520+
new IterablePushRegistration().execute(data);
487521
}
488522

489523
/**
@@ -606,21 +640,6 @@ static String getNotificationIcon(Context context) {
606640
return iconName;
607641
}
608642

609-
/**
610-
* Registers the device for push notifications.
611-
* @param iterableAppId
612-
* @param gcmProjectNumber
613-
* @param disableAfterRegistration
614-
*/
615-
protected void registerForPush(String iterableAppId, String gcmProjectNumber, boolean disableAfterRegistration) {
616-
Intent pushRegistrationIntent = new Intent(_applicationContext, IterablePushReceiver.class);
617-
pushRegistrationIntent.setAction(IterableConstants.ACTION_PUSH_REGISTRATION);
618-
pushRegistrationIntent.putExtra(IterableConstants.PUSH_APP_ID, iterableAppId);
619-
pushRegistrationIntent.putExtra(IterableConstants.PUSH_GCM_PROJECT_NUMBER, gcmProjectNumber);
620-
pushRegistrationIntent.putExtra(IterableConstants.PUSH_DISABLE_AFTER_REGISTRATION, disableAfterRegistration);
621-
_applicationContext.sendBroadcast(pushRegistrationIntent);
622-
}
623-
624643
/**
625644
* Tracks when a push notification is opened on device.
626645
* @param campaignId
@@ -643,7 +662,7 @@ protected void trackPushOpen(int campaignId, int templateId, String messageId) {
643662
}
644663

645664
/**
646-
* Internal api call made from IterablePushRegistrationGCM after a registrationToken is obtained.
665+
* Internal api call made from IterablePushRegistration after a registrationToken is obtained.
647666
* @param token
648667
*/
649668
protected void disablePush(String token) {
@@ -658,6 +677,48 @@ protected void disablePush(String token) {
658677
sendPostRequest(IterableConstants.ENDPOINT_DISABLE_DEVICE, requestJSON);
659678
}
660679

680+
/**
681+
* Registers the GCM registration ID with Iterable.
682+
* @param applicationName
683+
* @param token
684+
* @param pushServicePlatform
685+
* @param dataFields
686+
*/
687+
protected void registerDeviceToken(String applicationName, String token, String pushServicePlatform, JSONObject dataFields) {
688+
String platform = IterableConstants.MESSAGING_PLATFORM_GOOGLE;
689+
690+
JSONObject requestJSON = new JSONObject();
691+
try {
692+
addEmailOrUserIdToJson(requestJSON);
693+
694+
if (dataFields == null) {
695+
dataFields = new JSONObject();
696+
}
697+
if (pushServicePlatform != null) {
698+
dataFields.put(IterableConstants.FIREBASE_COMPATIBLE, pushServicePlatform.equalsIgnoreCase(IterableConstants.MESSAGING_PLATFORM_FIREBASE));
699+
}
700+
dataFields.put(IterableConstants.DEVICE_BRAND, Build.BRAND); //brand: google
701+
dataFields.put(IterableConstants.DEVICE_MANUFACTURER, Build.MANUFACTURER); //manufacturer: samsung
702+
dataFields.putOpt(IterableConstants.DEVICE_ADID, getAdvertisingId()); //ADID: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
703+
dataFields.put(IterableConstants.DEVICE_SYSTEM_NAME, Build.DEVICE); //device name: toro
704+
dataFields.put(IterableConstants.DEVICE_SYSTEM_VERSION, Build.VERSION.RELEASE); //version: 4.0.4
705+
dataFields.put(IterableConstants.DEVICE_MODEL, Build.MODEL); //device model: Galaxy Nexus
706+
dataFields.put(IterableConstants.DEVICE_SDK_VERSION, Build.VERSION.SDK_INT); //sdk version/api level: 15
707+
708+
JSONObject device = new JSONObject();
709+
device.put(IterableConstants.KEY_TOKEN, token);
710+
device.put(IterableConstants.KEY_PLATFORM, platform);
711+
device.put(IterableConstants.KEY_APPLICATION_NAME, applicationName);
712+
device.putOpt(IterableConstants.KEY_DATA_FIELDS, dataFields);
713+
requestJSON.put(IterableConstants.KEY_DEVICE, device);
714+
715+
} catch (JSONException e) {
716+
e.printStackTrace();
717+
}
718+
719+
sendPostRequest(IterableConstants.ENDPOINT_REGISTER_DEVICE_TOKEN, requestJSON);
720+
}
721+
661722
//---------------------------------------------------------------------------------------
662723
//endregion
663724

@@ -694,44 +755,6 @@ private void tryTrackNotifOpen(Intent calledIntent) {
694755
}
695756
}
696757

697-
/**
698-
* Registers the GCM registration ID with Iterable.
699-
* @param applicationName
700-
* @param token
701-
* @param dataFields
702-
*/
703-
private void registerDeviceToken(String applicationName, String token, JSONObject dataFields) {
704-
String platform = IterableConstants.MESSAGING_PLATFORM_GOOGLE;
705-
706-
JSONObject requestJSON = new JSONObject();
707-
try {
708-
addEmailOrUserIdToJson(requestJSON);
709-
710-
if (dataFields == null) {
711-
dataFields = new JSONObject();
712-
dataFields.put("brand", Build.BRAND); //brand: google
713-
dataFields.put("manufacturer", Build.MANUFACTURER); //manufacturer: samsung
714-
dataFields.putOpt("advertisingId", getAdvertisingId()); //ADID: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
715-
dataFields.put("systemName", Build.DEVICE); //device name: toro
716-
dataFields.put("systemVersion", Build.VERSION.RELEASE); //version: 4.0.4
717-
dataFields.put("model", Build.MODEL); //device model: Galaxy Nexus
718-
dataFields.put("sdkVersion", Build.VERSION.SDK_INT); //sdk version/api level: 15
719-
}
720-
721-
JSONObject device = new JSONObject();
722-
device.put(IterableConstants.KEY_TOKEN, token);
723-
device.put(IterableConstants.KEY_PLATFORM, platform);
724-
device.put(IterableConstants.KEY_APPLICATION_NAME, applicationName);
725-
device.putOpt(IterableConstants.KEY_DATA_FIELDS, dataFields);
726-
requestJSON.put(IterableConstants.KEY_DEVICE, device);
727-
728-
} catch (JSONException e) {
729-
e.printStackTrace();
730-
}
731-
732-
sendPostRequest(IterableConstants.ENDPOINT_REGISTER_DEVICE_TOKEN, requestJSON);
733-
}
734-
735758
/**
736759
* Sends the POST request to Iterable.
737760
* Performs network operations on an async thread instead of the main thread.

iterableapi/src/main/java/com/iterable/iterableapi/IterableConstants.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,41 @@ public final class IterableConstants {
4747
public static final String PUSH_GCM_PROJECT_NUMBER = "GCMProjectNumber";
4848
public static final String PUSH_DISABLE_AFTER_REGISTRATION = "DisableAfterRegistration";
4949

50-
public static final String MESSAGING_PLATFORM_GOOGLE = "GCM";
51-
public static final String MESSAGING_PLATFORM_AMAZON = "ADM";
50+
public static final String MESSAGING_PUSH_SERVICE_PLATFORM = "PushServicePlatform";
51+
public static final String MESSAGING_PLATFORM_GOOGLE = "GCM";
52+
public static final String MESSAGING_PLATFORM_FIREBASE = "FCM";
53+
public static final String MESSAGING_PLATFORM_AMAZON = "ADM";
5254

5355
public static final String IS_GHOST_PUSH = "isGhostPush";
5456
public static final String ITERABLE_DATA_KEY = "itbl";
5557
public static final String ITERABLE_DATA_BODY = "body";
5658
public static final String ITERABLE_DATA_TITLE = "title";
5759
public static final String ITERABLE_DATA_SOUND = "sound";
5860

61+
//Device
62+
public static final String DEVICE_BRAND = "brand";
63+
public static final String DEVICE_MANUFACTURER = "manufacturer";
64+
public static final String DEVICE_ADID = "advertisingId";
65+
public static final String DEVICE_SYSTEM_NAME = "systemName";
66+
public static final String DEVICE_SYSTEM_VERSION = "systemVersion";
67+
public static final String DEVICE_MODEL = "model";
68+
public static final String DEVICE_SDK_VERSION = "sdkVersion";
69+
5970
public static final String INSTANCE_ID_CLASS = "com.google.android.gms.iid.InstanceID";
6071
public static final String ICON_FOLDER_IDENTIFIER = "drawable";
6172
public static final String NOTIFICATION_ICON_NAME = "iterable_notification_icon";
6273
public static final String NOTIFICATION_COLOR = "iterable_notification_color";
6374
public static final String DEFAULT_SOUND = "default";
6475
public static final String SOUND_FOLDER_IDENTIFIER = "raw";
6576
public static final String ANDROID_RESOURCE_PATH = "android.resource://";
77+
public static final String ANDROID_STRING = "string";
78+
79+
//Firebase
80+
public static final String FIREBASE_RESOURCE_ID = "firebase_database_url";
81+
public static final String FIREBASE_MESSAGING_CLASS = "com.google.firebase.messaging.FirebaseMessaging";
82+
public static final String FIREBASE_COMPATIBLE = "firebaseCompatible";
83+
public static final String FIREBASE_TOKEN_TYPE = "tokenRegistrationType";
84+
public static final String FIREBASE_INITIAL_UPGRADE = "initialFirebaseUpgrade";
6685

6786
public static final String ITBL_DEEPLINK_IDENTIFIER = "/a/[A-Za-z0-9]+";
6887
public static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.iterable.iterableapi;
2+
3+
import android.content.Context;
4+
import android.content.SharedPreferences;
5+
6+
import com.google.firebase.iid.FirebaseInstanceId;
7+
import com.google.firebase.iid.FirebaseInstanceIdService;
8+
9+
import org.json.JSONException;
10+
import org.json.JSONObject;
11+
12+
/**
13+
* Created by David Truong [email protected].
14+
*/
15+
public class IterableFirebaseInstanceIDService extends FirebaseInstanceIdService {
16+
17+
static final String TAG = "itblFCMInstanceService";
18+
19+
/**
20+
* Register the new token if this the first upgrade to Firebase
21+
*/
22+
@Override
23+
public void onTokenRefresh() {
24+
String registrationToken = FirebaseInstanceId.getInstance().getToken();
25+
26+
Context mainContext = IterableApi.sharedInstance.getMainActivityContext();
27+
if (mainContext != null) {
28+
SharedPreferences sharedPref = mainContext.getSharedPreferences(IterableConstants.PUSH_APP_ID, Context.MODE_PRIVATE);
29+
String pushIdPref = sharedPref.getString(IterableConstants.PUSH_APP_ID, null);
30+
if (registrationToken != null && pushIdPref != null && !pushIdPref.equalsIgnoreCase(IterableConstants.PUSH_APP_ID)) {
31+
IterableLogger.w(TAG, "Refreshed fcm token: " + registrationToken);
32+
JSONObject data = new JSONObject();
33+
try {
34+
data.put(IterableConstants.FIREBASE_TOKEN_TYPE, IterableConstants.MESSAGING_PLATFORM_FIREBASE);
35+
data.put(IterableConstants.FIREBASE_INITIAL_UPGRADE, true);
36+
} catch (JSONException e) {
37+
IterableLogger.e(TAG, e.toString());
38+
}
39+
IterableApi.sharedInstance.registerDeviceToken(pushIdPref, registrationToken, IterableConstants.MESSAGING_PLATFORM_FIREBASE, data);
40+
SharedPreferences.Editor editor = sharedPref.edit();
41+
editor.putString(IterableConstants.PUSH_APP_ID, IterableConstants.PUSH_APP_ID);
42+
editor.commit();
43+
}
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)