diff --git a/iterableapi/src/main/AndroidManifest.xml b/iterableapi/src/main/AndroidManifest.xml
index 3afe07bca..e8ec645a2 100644
--- a/iterableapi/src/main/AndroidManifest.xml
+++ b/iterableapi/src/main/AndroidManifest.xml
@@ -22,6 +22,11 @@
+
diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java
index 7b35883d4..435a187eb 100644
--- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java
+++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java
@@ -303,7 +303,7 @@ public static void initialize(@NonNull Context context, @NonNull String apiKey,
}
loadLastSavedConfiguration(context);
- IterablePushActionReceiver.processPendingAction(context);
+ IterablePushNotificationUtil.processPendingAction(context);
}
public static void setContext(Context context) {
diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java
index 5670b18be..de7843897 100644
--- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java
+++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationBuilder.java
@@ -111,24 +111,37 @@ public Notification build() {
* @param extras Notification payload
*/
public void createNotificationActionButton(Context context, IterableNotificationData.Button button, Bundle extras) {
+ PendingIntent pendingButtonIntent = getPendingIntent(context, button, extras);
+ NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action
+ .Builder(NotificationCompat.BADGE_ICON_NONE, button.title, pendingButtonIntent);
+ if (button.buttonType.equals(IterableNotificationData.Button.BUTTON_TYPE_TEXT_INPUT)) {
+ actionBuilder.addRemoteInput(new RemoteInput.Builder(IterableConstants.USER_INPUT).setLabel(button.inputPlaceholder).build());
+ }
+ addAction(actionBuilder.build());
+ }
+
+ private PendingIntent getPendingIntent(Context context, IterableNotificationData.Button button, Bundle extras) {
+ PendingIntent pendingButtonIntent;
+
Intent buttonIntent = new Intent(IterableConstants.ACTION_PUSH_ACTION);
- buttonIntent.setClass(context, IterablePushActionReceiver.class);
buttonIntent.putExtras(extras);
buttonIntent.putExtra(IterableConstants.REQUEST_CODE, requestCode);
buttonIntent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, button.identifier);
buttonIntent.putExtra(IterableConstants.ACTION_IDENTIFIER, button.identifier);
- PendingIntent pendingButtonIntent = PendingIntent.getBroadcast(context, buttonIntent.hashCode(),
- buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action
- .Builder(NotificationCompat.BADGE_ICON_NONE, button.title, pendingButtonIntent);
-
- if (button.buttonType.equals(IterableNotificationData.Button.BUTTON_TYPE_TEXT_INPUT)) {
- actionBuilder.addRemoteInput(new RemoteInput.Builder(IterableConstants.USER_INPUT).setLabel(button.inputPlaceholder).build());
+ if (button.openApp) {
+ IterableLogger.d(TAG, "Go through TrampolineActivity");
+ buttonIntent.setClass(context, IterableTrampolineActivity.class);
+ pendingButtonIntent = PendingIntent.getActivity(context, buttonIntent.hashCode(),
+ buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ } else {
+ IterableLogger.d(TAG, "Go through IterablePushActionReceiver");
+ buttonIntent.setClass(context, IterablePushActionReceiver.class);
+ pendingButtonIntent = PendingIntent.getBroadcast(context, buttonIntent.hashCode(),
+ buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
- addAction(actionBuilder.build());
+ return pendingButtonIntent;
}
/**
diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java
index 1a603ed5c..62ce24658 100644
--- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java
+++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableNotificationHelper.java
@@ -177,10 +177,12 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
IterableLogger.d(IterableNotificationBuilder.TAG, "Request code = " + notificationBuilder.requestCode);
}
- Intent pushContentIntent = new Intent(IterableConstants.ACTION_PUSH_ACTION);
- pushContentIntent.setClass(context, IterablePushActionReceiver.class);
- pushContentIntent.putExtras(extras);
- pushContentIntent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, IterableConstants.ITERABLE_ACTION_DEFAULT);
+ //Create an intent for TrampolineActivity instead of BroadcastReceiver
+ Intent trampolineActivityIntent = new Intent(IterableConstants.ACTION_PUSH_ACTION);
+ trampolineActivityIntent.setClass(context, IterableTrampolineActivity.class);
+ trampolineActivityIntent.putExtras(extras);
+ trampolineActivityIntent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, IterableConstants.ITERABLE_ACTION_DEFAULT);
+ trampolineActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Action buttons
if (notificationData.getActionButtons() != null) {
@@ -192,8 +194,8 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
}
}
- PendingIntent notificationClickedIntent = PendingIntent.getBroadcast(context, notificationBuilder.requestCode,
- pushContentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent notificationClickedIntent = PendingIntent.getActivity(context, notificationBuilder.requestCode,
+ trampolineActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
notificationBuilder.setContentIntent(notificationClickedIntent);
notificationBuilder.setIsGhostPush(isGhostPush(extras));
diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterablePushActionReceiver.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterablePushActionReceiver.java
index 0403d4846..03c964d78 100644
--- a/iterableapi/src/main/java/com/iterable/iterableapi/IterablePushActionReceiver.java
+++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterablePushActionReceiver.java
@@ -1,15 +1,8 @@
package com.iterable.iterableapi;
-import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.Bundle;
-
-import androidx.core.app.RemoteInput;
-
-import org.json.JSONException;
-import org.json.JSONObject;
/**
* Handles incoming push actions built by {@link IterableNotificationBuilder}
@@ -17,137 +10,14 @@
*/
public class IterablePushActionReceiver extends BroadcastReceiver {
private static final String TAG = "IterablePushActionReceiver";
- // Used to hold intents until the SDK is initialized
- private static PendingAction pendingAction = null;
@Override
public void onReceive(Context context, Intent intent) {
- // Dismiss the notification
- int requestCode = intent.getIntExtra(IterableConstants.REQUEST_CODE, 0);
- NotificationManager mNotificationManager = (NotificationManager)
- context.getSystemService(Context.NOTIFICATION_SERVICE);
- mNotificationManager.cancel(requestCode);
-
- // Dismiss the notifications panel
- try {
- context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
- } catch (SecurityException e) {
- IterableLogger.w(TAG, e.getLocalizedMessage());
- }
-
+ IterablePushNotificationUtil.dismissNotification(context, intent);
+ IterablePushNotificationUtil.dismissNotificationPanel(context);
String actionName = intent.getAction();
if (IterableConstants.ACTION_PUSH_ACTION.equalsIgnoreCase(actionName)) {
- handlePushAction(context, intent);
- }
- }
-
- static boolean processPendingAction(Context context) {
- boolean handled = false;
- if (pendingAction != null) {
- handled = executeAction(context, pendingAction);
- pendingAction = null;
+ IterablePushNotificationUtil.handlePushAction(context, intent);
}
- return handled;
}
-
- private static void handlePushAction(Context context, Intent intent) {
- if (intent.getExtras() == null) {
- IterableLogger.e(TAG, "handlePushAction: extras == null, can't handle push action");
- return;
- }
- IterableNotificationData notificationData = new IterableNotificationData(intent.getExtras());
- String actionIdentifier = intent.getStringExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER);
- IterableAction action = null;
- JSONObject dataFields = new JSONObject();
-
- boolean openApp = true;
-
- if (actionIdentifier != null) {
- try {
- if (actionIdentifier.equals(IterableConstants.ITERABLE_ACTION_DEFAULT)) {
- // Default action (click on a push)
- dataFields.put(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, IterableConstants.ITERABLE_ACTION_DEFAULT);
- action = notificationData.getDefaultAction();
- if (action == null) {
- action = getLegacyDefaultActionFromPayload(intent.getExtras());
- }
- } else {
- dataFields.put(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, actionIdentifier);
- IterableNotificationData.Button button = notificationData.getActionButton(actionIdentifier);
- action = button.action;
- openApp = button.openApp;
-
- if (button.buttonType.equals(IterableNotificationData.Button.BUTTON_TYPE_TEXT_INPUT)) {
- Bundle results = RemoteInput.getResultsFromIntent(intent);
- if (results != null) {
- String userInput = results.getString(IterableConstants.USER_INPUT);
- if (userInput != null) {
- dataFields.putOpt(IterableConstants.KEY_USER_TEXT, userInput);
- action.userInput = userInput;
- }
- }
- }
- }
- } catch (JSONException e) {
- IterableLogger.e(TAG, "Encountered an exception while trying to handle the push action", e);
- }
- }
-
- pendingAction = new PendingAction(intent, notificationData, action, openApp, dataFields);
-
- boolean handled = false;
- if (IterableApi.getInstance().getMainActivityContext() != null) {
- handled = processPendingAction(context);
- }
-
- // Open the launcher activity if the action was not handled by anything, and openApp is true
- if (openApp && !handled) {
- Intent launcherIntent = IterableNotificationHelper.getMainActivityIntent(context);
- launcherIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
- if (launcherIntent.resolveActivity(context.getPackageManager()) != null) {
- context.startActivity(launcherIntent);
- }
- }
- }
-
- private static boolean executeAction(Context context, PendingAction action) {
- // Automatic tracking
- IterableApi.sharedInstance.setPayloadData(action.intent);
- IterableApi.sharedInstance.setNotificationData(action.notificationData);
- IterableApi.sharedInstance.trackPushOpen(action.notificationData.getCampaignId(), action.notificationData.getTemplateId(),
- action.notificationData.getMessageId(), action.dataFields);
-
- return IterableActionRunner.executeAction(context, action.iterableAction, IterableActionSource.PUSH);
- }
-
- private static IterableAction getLegacyDefaultActionFromPayload(Bundle extras) {
- try {
- if (extras.containsKey(IterableConstants.ITERABLE_DATA_DEEP_LINK_URL)) {
- JSONObject actionJson = new JSONObject();
- actionJson.put("type", IterableAction.ACTION_TYPE_OPEN_URL);
- actionJson.put("data", extras.getString(IterableConstants.ITERABLE_DATA_DEEP_LINK_URL));
- return IterableAction.from(actionJson);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- private static class PendingAction {
- Intent intent;
- IterableNotificationData notificationData;
- IterableAction iterableAction;
- boolean openApp;
- JSONObject dataFields;
-
- PendingAction(Intent intent, IterableNotificationData notificationData, IterableAction iterableAction, boolean openApp, JSONObject dataFields) {
- this.intent = intent;
- this.notificationData = notificationData;
- this.iterableAction = iterableAction;
- this.openApp = openApp;
- this.dataFields = dataFields;
- }
- }
-
}
diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterablePushNotificationUtil.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterablePushNotificationUtil.java
new file mode 100644
index 000000000..9499db682
--- /dev/null
+++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterablePushNotificationUtil.java
@@ -0,0 +1,142 @@
+package com.iterable.iterableapi;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.core.app.RemoteInput;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+class IterablePushNotificationUtil {
+ private static PendingAction pendingAction = null;
+ private static final String TAG = "IterablePushNotificationUtil";
+
+ static boolean processPendingAction(Context context) {
+ boolean handled = false;
+ if (pendingAction != null) {
+ handled = executeAction(context, pendingAction);
+ pendingAction = null;
+ }
+ return handled;
+ }
+
+ static boolean executeAction(Context context, PendingAction action) {
+ // Automatic tracking
+ IterableApi.sharedInstance.setPayloadData(action.intent);
+ IterableApi.sharedInstance.setNotificationData(action.notificationData);
+ IterableApi.sharedInstance.trackPushOpen(action.notificationData.getCampaignId(), action.notificationData.getTemplateId(),
+ action.notificationData.getMessageId(), action.dataFields);
+
+ return IterableActionRunner.executeAction(context, action.iterableAction, IterableActionSource.PUSH);
+ }
+
+
+ static void handlePushAction(Context context, Intent intent) {
+ if (intent.getExtras() == null) {
+ IterableLogger.e(TAG, "handlePushAction: extras == null, can't handle push action");
+ return;
+ }
+ IterableNotificationData notificationData = new IterableNotificationData(intent.getExtras());
+ String actionIdentifier = intent.getStringExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER);
+ IterableAction action = null;
+ JSONObject dataFields = new JSONObject();
+
+ boolean openApp = true;
+
+ if (actionIdentifier != null) {
+ try {
+ if (actionIdentifier.equals(IterableConstants.ITERABLE_ACTION_DEFAULT)) {
+ // Default action (click on a push)
+ dataFields.put(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, IterableConstants.ITERABLE_ACTION_DEFAULT);
+ action = notificationData.getDefaultAction();
+ if (action == null) {
+ action = getLegacyDefaultActionFromPayload(intent.getExtras());
+ }
+ } else {
+ dataFields.put(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, actionIdentifier);
+ IterableNotificationData.Button button = notificationData.getActionButton(actionIdentifier);
+ action = button.action;
+ openApp = button.openApp;
+
+ if (button.buttonType.equals(IterableNotificationData.Button.BUTTON_TYPE_TEXT_INPUT)) {
+ Bundle results = RemoteInput.getResultsFromIntent(intent);
+ if (results != null) {
+ String userInput = results.getString(IterableConstants.USER_INPUT);
+ if (userInput != null) {
+ dataFields.putOpt(IterableConstants.KEY_USER_TEXT, userInput);
+ action.userInput = userInput;
+ }
+ }
+ }
+ }
+ } catch (JSONException e) {
+ IterableLogger.e(TAG, "Encountered an exception while trying to handle the push action", e);
+ }
+ }
+ pendingAction = new PendingAction(intent, notificationData, action, openApp, dataFields);
+
+ boolean handled = false;
+ if (IterableApi.getInstance().getMainActivityContext() != null) {
+ handled = processPendingAction(context);
+ }
+
+ // Open the launcher activity if the action was not handled by anything, and openApp is true
+ if (openApp && !handled) {
+ Intent launcherIntent = IterableNotificationHelper.getMainActivityIntent(context);
+ launcherIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ if (launcherIntent.resolveActivity(context.getPackageManager()) != null) {
+ context.startActivity(launcherIntent);
+ }
+ }
+ }
+
+ private static IterableAction getLegacyDefaultActionFromPayload(Bundle extras) {
+ try {
+ if (extras.containsKey(IterableConstants.ITERABLE_DATA_DEEP_LINK_URL)) {
+ JSONObject actionJson = new JSONObject();
+ actionJson.put("type", IterableAction.ACTION_TYPE_OPEN_URL);
+ actionJson.put("data", extras.getString(IterableConstants.ITERABLE_DATA_DEEP_LINK_URL));
+ return IterableAction.from(actionJson);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private static class PendingAction {
+ Intent intent;
+ IterableNotificationData notificationData;
+ IterableAction iterableAction;
+ boolean openApp;
+ JSONObject dataFields;
+
+ PendingAction(Intent intent, IterableNotificationData notificationData, IterableAction iterableAction, boolean openApp, JSONObject dataFields) {
+ this.intent = intent;
+ this.notificationData = notificationData;
+ this.iterableAction = iterableAction;
+ this.openApp = openApp;
+ this.dataFields = dataFields;
+ }
+ }
+
+ static void dismissNotificationPanel(Context context) {
+ // Dismiss the notifications panel
+ try {
+ context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ } catch (SecurityException e) {
+ IterableLogger.w(TAG, e.getLocalizedMessage());
+ }
+ }
+
+ static void dismissNotification(Context context, Intent notificationIntent) {
+ // Dismiss the notification
+ int requestCode = notificationIntent.getIntExtra(IterableConstants.REQUEST_CODE, 0);
+ NotificationManager mNotificationManager = (NotificationManager)
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
+ mNotificationManager.cancel(requestCode);
+ }
+}
diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableTrampolineActivity.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableTrampolineActivity.java
new file mode 100644
index 000000000..9e0e43781
--- /dev/null
+++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableTrampolineActivity.java
@@ -0,0 +1,57 @@
+package com.iterable.iterableapi;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+public class IterableTrampolineActivity extends AppCompatActivity {
+
+ private static final String TAG = "TrampolineActivity";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ IterableLogger.v(TAG, "Notification Trampoline Activity created");
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ IterableLogger.v(TAG, "Notification Trampoline Activity resumed");
+
+ Intent notificationIntent = getIntent();
+ if (notificationIntent == null) {
+ IterableLogger.d(TAG, "Intent is null. Doing nothing.");
+ finish();
+ return;
+ }
+
+ String actionName = notificationIntent.getAction();
+ if (actionName == null) {
+ IterableLogger.d(TAG, "Intent action is null. Doing nothing.");
+ finish();
+ return;
+ }
+
+ IterablePushNotificationUtil.dismissNotification(this, notificationIntent);
+ IterablePushNotificationUtil.dismissNotificationPanel(this);
+ if (IterableConstants.ACTION_PUSH_ACTION.equalsIgnoreCase(actionName)) {
+ IterablePushNotificationUtil.handlePushAction(this, notificationIntent);
+ }
+ finish();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ IterableLogger.v(TAG, "Notification Trampoline Activity on pause");
+
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ IterableLogger.v(TAG, "Notification Trampoline Activity destroyed");
+ }
+}
\ No newline at end of file
diff --git a/iterableapi/src/main/res/values/styles.xml b/iterableapi/src/main/res/values/styles.xml
new file mode 100644
index 000000000..ebbd77a47
--- /dev/null
+++ b/iterableapi/src/main/res/values/styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file