package com.appboy.push;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import com.appboy.Appboy;
import com.appboy.AppboyGcmReceiver;
import com.appboy.Constants;
import com.appboy.configuration.AppboyConfigurationProvider;
import com.appboy.support.AppboyLogger;
import com.appboy.support.IntentUtils;
import com.appboy.support.StringUtils;
public class AppboyNotificationActionUtils {
private static final String TAG = String.format("%s.%s", Constants.APPBOY_LOG_TAG_PREFIX, AppboyNotificationActionUtils.class.getName());
/**
* Add notification actions to the provided notification builder.
*
* Notification action button schema:
*
* “ab_a*_id”: action button id, used for analytics - optional
* “ab_a*_t”: action button text - optional
* “ab_a*_a”: action type, one of “ab_uri”, ”ab_none”, “ab_open” (open the app) - required
* “ab_a*_uri”: uri, only used when the action is “uri” - required only when action is “uri”
* “ab_a*_use_webview”: whether to open the web link in a web view - optional
*
* The * is replaced with an integer string depending on the button being described
* (e.g. the uri for the second button is “ab_a1_uri”).
* The left-most button is defined as button zero.
*
* @param context
* @param notificationBuilder
* @param notificationExtras GCM/ADM extras
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void addNotificationActions(Context context, NotificationCompat.Builder notificationBuilder, Bundle notificationExtras) {
try {
if (notificationExtras == null) {
AppboyLogger.w(TAG, "Notification extras were null. Doing nothing.");
return;
}
// Notification actions were added in Jelly Bean
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
return;
}
int actionIndex = 0;
while (!StringUtils.isNullOrBlank(getActionFieldAtIndex(actionIndex, notificationExtras, Constants.APPBOY_PUSH_ACTION_TYPE_KEY_TEMPLATE))) {
addNotificationAction(context, notificationBuilder, notificationExtras, actionIndex);
actionIndex++;
}
} catch (Exception e) {
AppboyLogger.e(TAG, "Caught exception while adding notification action buttons.", e);
}
}
/**
* Handles clicks on notification action buttons in the notification center. Called by GCM/ADM
* receiver when an Appboy notification action button is clicked. The GCM/ADM receiver passes on
* the intent from the notification action button click intent.
*
* @param context
* @param intent the action button click intent
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void handleNotificationActionClicked(Context context, Intent intent) {
try {
String actionType = intent.getStringExtra(Constants.APPBOY_ACTION_TYPE_KEY);
if (StringUtils.isNullOrBlank(actionType)) {
AppboyLogger.w(TAG, "Notification action button type was blank or null. Doing nothing.");
return;
}
int notificationId = intent.getIntExtra(Constants.APPBOY_PUSH_NOTIFICATION_ID, Constants.APPBOY_DEFAULT_NOTIFICATION_ID);
// Logs that the notification action was clicked.
// Click analytics for all action types are logged.
logNotificationActionClicked(context, intent);
if (actionType.equals(Constants.APPBOY_PUSH_ACTION_TYPE_URI) || actionType.equals(Constants.APPBOY_PUSH_ACTION_TYPE_OPEN)) {
AppboyNotificationUtils.cancelNotification(context, notificationId);
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
if (actionType.equals(Constants.APPBOY_PUSH_ACTION_TYPE_URI) && intent.getExtras().containsKey(Constants.APPBOY_ACTION_URI_KEY)) {
// Set the deep link that to open to the correct action's deep link.
intent.putExtra(Constants.APPBOY_PUSH_DEEP_LINK_KEY, intent.getStringExtra(Constants.APPBOY_ACTION_URI_KEY));
if (intent.getExtras().containsKey(Constants.APPBOY_ACTION_USE_WEBVIEW_KEY)) {
intent.putExtra(Constants.APPBOY_PUSH_OPEN_URI_IN_WEBVIEW_KEY,
intent.getStringExtra(Constants.APPBOY_ACTION_USE_WEBVIEW_KEY));
}
} else {
// Otherwise, remove any existing deep links.
intent.removeExtra(Constants.APPBOY_PUSH_DEEP_LINK_KEY);
}
AppboyNotificationUtils.sendNotificationOpenedBroadcast(context, intent);
AppboyConfigurationProvider appConfigurationProvider = new AppboyConfigurationProvider(context);
if (appConfigurationProvider.getHandlePushDeepLinksAutomatically()) {
AppboyNotificationUtils.routeUserWithNotificationOpenedIntent(context, intent);
}
} else if (actionType.equals(Constants.APPBOY_PUSH_ACTION_TYPE_NONE)) {
AppboyNotificationUtils.cancelNotification(context, notificationId);
} else {
AppboyLogger.w(TAG, "Unknown notification action button clicked. Doing nothing.");
}
} catch (Exception e) {
AppboyLogger.e(TAG, "Caught exception while handling notification action button click.", e);
}
}
/**
* Add the notification action at the specified index to the notification builder.
*
* @param context
* @param notificationBuilder
* @param notificationExtras
* @param actionIndex
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static void addNotificationAction(Context context, NotificationCompat.Builder notificationBuilder, Bundle notificationExtras, int actionIndex) {
Bundle notificationActionExtras = new Bundle(notificationExtras);
String actionType = getActionFieldAtIndex(actionIndex, notificationExtras, Constants.APPBOY_PUSH_ACTION_TYPE_KEY_TEMPLATE);
notificationActionExtras.putInt(Constants.APPBOY_ACTION_INDEX_KEY, actionIndex);
notificationActionExtras.putString(Constants.APPBOY_ACTION_TYPE_KEY, actionType);
notificationActionExtras.putString(Constants.APPBOY_ACTION_ID_KEY, getActionFieldAtIndex(actionIndex, notificationExtras, Constants.APPBOY_PUSH_ACTION_ID_KEY_TEMPLATE));
notificationActionExtras.putString(Constants.APPBOY_ACTION_URI_KEY, getActionFieldAtIndex(actionIndex, notificationExtras, Constants.APPBOY_PUSH_ACTION_URI_KEY_TEMPLATE));
notificationActionExtras.putString(Constants.APPBOY_ACTION_USE_WEBVIEW_KEY,
getActionFieldAtIndex(actionIndex, notificationExtras, Constants.APPBOY_PUSH_ACTION_USE_WEBVIEW_KEY_TEMPLATE));
Intent sendIntent = new Intent(Constants.APPBOY_ACTION_CLICKED_ACTION).setClass(context, AppboyNotificationUtils.getNotificationReceiverClass());
sendIntent.putExtras(notificationActionExtras);
String actionText = getActionFieldAtIndex(actionIndex, notificationExtras, Constants.APPBOY_PUSH_ACTION_TEXT_KEY_TEMPLATE);
PendingIntent pendingSendIntent = PendingIntent.getBroadcast(context, IntentUtils.getRequestCode(), sendIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder notificationActionBuilder = new NotificationCompat.Action.Builder(0, actionText, pendingSendIntent);
notificationActionBuilder.addExtras(new Bundle(notificationActionExtras));
notificationBuilder.addAction(notificationActionBuilder.build());
}
/**
* Log an action button clicked event. Logging requires a valid campaign Id and action button Id.
*
* @param context
* @param intent the action button click intent
*/
private static void logNotificationActionClicked(Context context, Intent intent) {
String campaignId = intent.getStringExtra(AppboyGcmReceiver.CAMPAIGN_ID_KEY);
String actionButtonId = intent.getStringExtra(Constants.APPBOY_ACTION_ID_KEY);
if (StringUtils.isNullOrBlank(campaignId)) {
AppboyLogger.i(TAG, "No campaign Id associated with this notification. Not logging push action click to Appboy.");
return;
}
if (StringUtils.isNullOrBlank(actionButtonId)) {
AppboyLogger.i(TAG, "No action button Id associated with this notification action. Not logging push action click to Appboy.");
return;
}
AppboyLogger.i(TAG, "Logging push action click to Appboy. Campaign Id: " + campaignId + " Action Button Id: " + actionButtonId);
Appboy.getInstance(context).logPushNotificationActionClicked(campaignId, actionButtonId);
}
/**
* Returns the value for the given action field key template at the specified index.
*
* @param actionIndex the index of the desired action
* @param notificationExtras GCM/ADM notification extras
* @param actionFieldKeyTemplate the template of the action field
* @return the desired notification action field value or the empty string if not present
*/
static String getActionFieldAtIndex(int actionIndex, Bundle notificationExtras, String actionFieldKeyTemplate) {
String actionFieldKey = actionFieldKeyTemplate.replace("*", String.valueOf(actionIndex));
String actionFieldValue = notificationExtras.getString(actionFieldKey);
if (actionFieldValue == null) {
return "";
} else {
return actionFieldValue;
}
}
}