{"metadata":{"image":[],"title":"","description":""},"api":{"url":"","auth":"required","params":[],"results":{"codes":[]},"settings":"","apiSetting":null},"next":{"description":"","pages":[]},"title":"Android: Rich Notifications","type":"basic","slug":"rich-notifications","excerpt":"","body":"Sailthru Mobile supports Android Rich Notifications out of the box for image payloads.\n\n\n### Send Rich Notifications\n\nWhen creating an in-app message with push notification, the image added to the in-app message will automatically be delivered to the Android device and displayed as a rich push notification.\n\nAlternatively, [rich notifications can be sent using the API as per the Rich Push example](https://docs.mobile.sailthru.com/docs/notifications).\n[block:image]\n{\n \"images\": [\n {\n \"image\": [\n \"https://files.readme.io/131d415-Screen_Shot_2018-05-08_at_1.45.22_PM.png\",\n \"Screen Shot 2018-05-08 at 1.45.22 PM.png\",\n 1105,\n 523,\n \"#e2e8ed\"\n ],\n \"caption\": \"Creating a message with an image inside the Sailthru Mobile platform.\",\n \"border\": true\n }\n ]\n}\n[/block]\n\n[block:image]\n{\n \"images\": [\n {\n \"image\": [\n \"https://files.readme.io/e9cb256-Screenshot_20170324-063420.png\",\n \"Screenshot_20170324-063420.png\",\n 709,\n 508,\n \"#e9dfdd\"\n ],\n \"caption\": \"An Android Rich Notification on device created from the message.\",\n \"sizing\": \"smart\",\n \"border\": true\n }\n ]\n}\n[/block]\n### Extend or change default behavior \n\nYou can extend or change this default behavior by adding a `NotificationCompat.Extender` and implementing your own notification style. This is useful if you want to add media controls, or you'd like to render the notification body with an expanded view.\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"\\nimport android.support.v4.app.NotificationCompat;\\npublic class RichPushNotificationExtender implements NotificationCompat.Extender {\\n protected static String TAG = \\\"RichPushNotificationExtender\\\";\\n protected static String KEY_PAYLOAD_ALERT = \\\"alert\\\";\\n protected static String KEY_PAYLOAD_TITLE = \\\"title\\\";\\n protected static String KEY_PAYLOAD_IMAGE_URL = \\\"image_url\\\";\\n protected static String KEY_PAYLOAD_ST = \\\"_st\\\";\\n \\n :::at:::Override\\n public NotificationCompat.Builder extend(NotificationCompat.Builder builder) {\\n Bundle bundle = builder.getExtras();\\n Context context = builder.mContext;\\n \\n // For Image or Video in-app messages, we will send the media URL in the\\n // _st payload\\n String imageUrl = null;\\n String stString = bundle.getString(KEY_PAYLOAD_ST);\\n if(stString != null && !stString.isEmpty()) {\\n try {\\n JSONObject stPayload = new JSONObject(stString);\\n if (!stPayload.isNull(KEY_PAYLOAD_IMAGE_URL)) {\\n imageUrl = stPayload.getString(KEY_PAYLOAD_IMAGE_URL);\\n }\\n } catch (JSONException e) {\\n Log.e(TAG, \\\"Unable to get \\\" + KEY_PAYLOAD_IMAGE_URL + \\\" from '_st' payload: \\\" + stString + \\\".\\\\n\\\" + e.getLocalizedMessage());\\n }\\n }\\n \\n builder.setContentTitle(context.getResources().getString(R.string.app_name))\\n .setSmallIcon(R.drawable.st_bg_notification)\\n .setContentText(bundle.getString(KEY_PAYLOAD_ALERT));\\n\\n if(imageUrl != null && !imageUrl.isEmpty()) {\\n Bitmap image = fetchImageForMessage(imageUrl);\\n\\n NotificationCompat.BigPictureStyle largeFormatStyle = new NotificationCompat.BigPictureStyle()\\n .bigPicture(image)\\n .setBigContentTitle(context.getResources().getString(R.string.app_name))\\n .setSummaryText(bundle.getString(KEY_PAYLOAD_TITLE))\\n .bigLargeIcon(image);\\n builder.setLargeIcon(image);\\n builder.setStyle(largeFormatStyle);\\n }\\n\\n return builder;\\n }\\n \\n // code used to load image from url\\n private @Nullable Bitmap fetchImageForMessage(@NonNull String imageUrl) {\\n URL url;\\n try {\\n url = new URL(imageUrl);\\n } catch (MalformedURLException e) {\\n Log.e(TAG, \\\"Malformed image URL in Push Payload: \\\" + e.getLocalizedMessage());\\n return null;\\n }\\n\\n AsyncTask<URL, Void, Bitmap> task = new AsyncTask<URL, Void, Bitmap>() {\\n\\n @Override\\n protected Bitmap doInBackground(URL... params) {\\n try {\\n URL url = params[0];\\n HttpURLConnection connection = (HttpURLConnection) url.openConnection();\\n connection.setDoInput(true);\\n connection.connect();\\n InputStream input = connection.getInputStream();\\n return BitmapFactory.decodeStream(input);\\n } catch (IOException e) {\\n Log.e(TAG, \\\"IO Error loading Message image:\\\" + e.getLocalizedMessage());\\n return Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);\\n }\\n }\\n\\n }.execute(url);\\n try {\\n return task.get(5, TimeUnit.SECONDS);\\n } catch (Exception e) {\\n Log.e(TAG, \\\"Failed to wait for Message Image in RichPushNotificationExtender: \\\" + e.getMessage());\\n return null;\\n }\\n }\\n \\n}\",\n \"language\": \"java\",\n \"name\": \"Android (Java)\"\n },\n {\n \"code\": \"import androidx.core.app.NotificationCompat\\n\\nclass RichPushNotificationExtender : NotificationCompat.Extender {\\n override fun extend(builder: NotificationCompat.Builder): NotificationCompat.Builder {\\n val bundle: Bundle = builder.getExtras()\\n val context: Context = builder.mContext\\n\\n // For Image or Video in-app messages, we will send the media URL in the\\n // _st payload\\n var imageUrl: String? = null\\n val stString = bundle.getString(KEY_PAYLOAD_ST)\\n if (stString != null && !stString.isEmpty()) {\\n try {\\n val stPayload = JSONObject(stString)\\n if (!stPayload.isNull(KEY_PAYLOAD_IMAGE_URL)) {\\n imageUrl = stPayload.getString(KEY_PAYLOAD_IMAGE_URL)\\n }\\n } catch (e: JSONException) {\\n Log.e(TAG, \\\"\\\"\\\"Unable to get $KEY_PAYLOAD_IMAGE_URL from '_st' payload: $stString.\\n${e.getLocalizedMessage()}\\\"\\\"\\\")\\n }\\n }\\n builder.setContentTitle(context.resources.getString(R.string.app_name))\\n .setSmallIcon(R.drawable.st_bg_notification)\\n .setContentText(bundle.getString(KEY_PAYLOAD_ALERT))\\n if (imageUrl != null && !imageUrl.isEmpty()) {\\n val image = fetchImageForMessage(imageUrl)\\n val largeFormatStyle: NotificationCompat.BigPictureStyle = NotificationCompat.BigPictureStyle()\\n .bigPicture(image)\\n .setBigContentTitle(context.resources.getString(R.string.app_name))\\n .setSummaryText(bundle.getString(KEY_PAYLOAD_TITLE))\\n .bigLargeIcon(image)\\n builder.setLargeIcon(image)\\n builder.setStyle(largeFormatStyle)\\n }\\n return builder\\n }\\n\\n // code used to load image from url\\n private fun fetchImageForMessage(imageUrl: String): Bitmap? {\\n val url: URL\\n try {\\n url = URL(imageUrl)\\n } catch (e: MalformedURLException) {\\n Log.e(TAG, \\\"Malformed image URL in Push Payload: \\\" + e.getLocalizedMessage())\\n return null\\n }\\n val task: AsyncTask<URL?, Void?, Bitmap?> = object : AsyncTask<URL?, Void?, Bitmap>() {\\n override fun doInBackground(vararg params: URL): Bitmap {\\n return try {\\n val url: URL = params[0]\\n val connection: HttpURLConnection = url.openConnection() as HttpURLConnection\\n connection.setDoInput(true)\\n connection.connect()\\n val input: InputStream = connection.getInputStream()\\n BitmapFactory.decodeStream(input)\\n } catch (e: IOException) {\\n Log.e(TAG, \\\"IO Error loading Message image:\\\" + e.getLocalizedMessage())\\n Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8)\\n }\\n }\\n }.execute(url)\\n return try {\\n task[5, TimeUnit.SECONDS]\\n } catch (e: Exception) {\\n Log.e(TAG, \\\"Failed to wait for Message Image in RichPushNotificationExtender: \\\" + e.message)\\n null\\n }\\n }\\n\\n companion object {\\n protected var TAG = \\\"RichPushNotificationExtender\\\"\\n protected var KEY_PAYLOAD_ALERT = \\\"alert\\\"\\n protected var KEY_PAYLOAD_TITLE = \\\"title\\\"\\n protected var KEY_PAYLOAD_IMAGE_URL = \\\"image_url\\\"\\n protected var KEY_PAYLOAD_ST = \\\"_st\\\"\\n }\\n}\",\n \"language\": \"kotlin\"\n }\n ]\n}\n[/block]\nThen add your extender to `NotificationConfig`\n[block:code]\n{\n \"codes\": [\n {\n \"code\": \"public class MyApplication extends Application {\\n @Override\\n public void onCreate() {\\n super.onCreate();\\n\\n SailthruMobile sailthruMobile = new SailthruMobile();\\n sailthruMobile.startEngine(getApplicationContext(), \\\"your sdk key\\\");\\n\\n NotificationConfig notificationConfig = new NotificationConfig();\\n notificationConfig.addNotificationExtender(new RichPushNotificationExtender());\\n sailthruMobile.setNotificationConfig(notificationConfig);\\n }\\n}\",\n \"language\": \"java\"\n },\n {\n \"code\": \"class MyApplication : Application() {\\n fun onCreate() {\\n super.onCreate()\\n val sailthruMobile = SailthruMobile()\\n sailthruMobile.startEngine(applicationContext, \\\"your sdk key\\\")\\n val notificationConfig = NotificationConfig()\\n notificationConfig.addNotificationExtender(RichPushNotificationExtender())\\n sailthruMobile.setNotificationConfig(notificationConfig)\\n }\\n}\",\n \"language\": \"kotlin\"\n }\n ]\n}\n[/block]","updates":[],"order":1,"isReference":false,"hidden":false,"sync_unique":"","link_url":"","link_external":false,"_id":"5e6156bf5e4a51006dcd815e","parentDoc":null,"githubsync":"","createdAt":"2016-05-19T02:48:53.845Z","project":"55e67aaa9cc7c62b00c4a1ea","__v":9,"category":{"sync":{"isSync":false,"url":""},"pages":[],"title":"Android Techniques","slug":"android-techniques","order":9999,"from_sync":false,"reference":false,"_id":"5e69868cbd5dcb006b35867b","createdAt":"2020-03-12T00:47:08.696Z","version":"5e6156bf5e4a51006dcd818c","project":"55e67aaa9cc7c62b00c4a1ea","__v":0},"user":"56035f358d58900d0051e976","version":{"version":"1.5","version_clean":"1.5.0","codename":"ST Rebrand","is_stable":true,"is_beta":false,"is_hidden":false,"is_deprecated":false,"categories":["5e6156bf5e4a51006dcd8120","5e6156bf5e4a51006dcd8121","5e6156bf5e4a51006dcd8122","5e6156bf5e4a51006dcd8123","5e6156bf5e4a51006dcd8124","561c61b4ad272c0d00a892df","586c014c0abf1d0f000d04d4","58991d2ad207df0f0002186b","5e6156bf5e4a51006dcd8125","5e6156bf5e4a51006dcd8126","5af0fe494ca2730003cbc98a","5af0fe55ec80af0003804ca2","5e69868cbd5dcb006b35867b","5e6986ca2c6652006791b6e8"],"_id":"5e6156bf5e4a51006dcd818c","project":"55e67aaa9cc7c62b00c4a1ea","__v":2,"forked_from":"5b720760c44b7600034b7a08","createdAt":"2015-09-02T04:27:23.612Z","releaseDate":"2015-09-02T04:27:23.612Z"}}