{"_id":"573d2995daba6a1900e0cc4a","parentDoc":null,"project":"55e67aaa9cc7c62b00c4a1ea","__v":9,"category":{"_id":"589b8e1fdbb7cd190026732c","project":"55e67aaa9cc7c62b00c4a1ea","__v":0,"version":"55e67aab9cc7c62b00c4a1ed","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2017-02-08T21:31:11.878Z","from_sync":false,"order":6,"slug":"advanced-techniques","title":"Advanced Techniques"},"user":"56035f358d58900d0051e976","version":{"_id":"55e67aab9cc7c62b00c4a1ed","project":"55e67aaa9cc7c62b00c4a1ea","__v":10,"createdAt":"2015-09-02T04:27:23.612Z","releaseDate":"2015-09-02T04:27:23.612Z","categories":["55e67aac9cc7c62b00c4a1ee","55e67b5556007d23005fee7d","55e67b5dde6fef23009480ca","55e680efde6fef23009480db","55e6829485a9741900314e99","561c61b4ad272c0d00a892df","586c014c0abf1d0f000d04d4","58991d2ad207df0f0002186b","589b8e1fdbb7cd190026732c","58b8ca5e3265d70f001788d4"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-05-19T02:48:53.845Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":6,"body":"Carnival supports Android Rich Notifications out of the box for image payloads.\n\nWhen creating image messages, Android will automatically add the image's thumbnail to the notification with an expanded layout showing a larger image.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/d2cff56-Screen_Shot_2017-03-23_at_1.25.38_PM.png\",\n        \"Screen Shot 2017-03-23 at 1.25.38 PM.png\",\n        1272,\n        1596,\n        \"#e2ddde\"\n      ],\n      \"caption\": \"Creating a message with an image inside the Carnival 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]\nYou can extend or change this default behavior by extending a `CarnivalMessageListener` 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\": \"public class RichPushNotificationExtender extends CarnivalMessageListener {\\n    protected static String TAG = \\\"Showcase\\\";\\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\\n    private :::at:::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 GcmIntentService: \\\" + e.getMessage());\\n            return null;\\n        }\\n    }\\n\\n    private @Nullable Intent getDefaultIntent(@NonNull Context context) {\\n        Intent intent = null;\\n        try {\\n            PackageManager manager = context.getPackageManager();\\n            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);\\n            intent = manager.getLaunchIntentForPackage(info.packageName);\\n            if (intent != null) {\\n                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);\\n            }\\n        } catch (PackageManager.NameNotFoundException e) {\\n            Log.e(TAG, \\\"Unable to get launch intent from Package Info\\\");\\n        }\\n\\n        Log.d(TAG, \\\"Loading default intent: \\\" + intent);\\n        return intent;\\n    }\\n\\n    protected PendingIntent createPendingIntent(Context context, Bundle bundle) {\\n        PendingIntent pendingIntent = null;\\n        Intent intent = null;\\n        String deepLinkUrl = bundle.getString(\\\"deeplink\\\");\\n        if (TextUtils.isEmpty(deepLinkUrl)) {\\n            intent = new Intent(context, AppDemoActivity.class);\\n        } else {\\n            intent = new Intent();\\n            intent.putExtras(bundle);\\n            intent.setAction(Intent.ACTION_VIEW);\\n            intent.setData(android.net.Uri.parse(deepLinkUrl));\\n            intent.addFlags(Intent.FLAG_FROM_BACKGROUND);\\n        }\\n\\n        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);\\n        stackBuilder.addParentStack(AppDemoActivity.class);\\n        stackBuilder.addNextIntent(intent);\\n        pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);\\n        return pendingIntent;\\n\\n    }\\n\\n    @Override\\n    public boolean onMessageReceived(@NonNull Context context, @NonNull Bundle bundle, @Nullable Message message) {\\n        NotificationCompat.Builder mBuilder =\\n                new NotificationCompat.Builder(context)\\n                        .setContentTitle(context.getResources().getString(R.string.app_name))\\n                        .setSmallIcon(R.drawable.carnival_bg_notification)\\n                        .setContentText(bundle.getString(KEY_PAYLOAD_ALERT));\\n\\n\\n        String imageUrl = bundle.getString(KEY_PAYLOAD_IMAGE_URL);\\n        if (TextUtils.isEmpty(imageUrl)) {\\n            return false;\\n        }\\n\\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        mBuilder.setLargeIcon(image);\\n        mBuilder.setStyle(largeFormatStyle);\\n\\n\\n        mBuilder.setContentIntent(createPendingIntent(context, bundle));\\n        NotificationManager mNotificationManager =\\n                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);\\n        mNotificationManager.notify((int)System.currentTimeMillis(), mBuilder.build());\\n        return true;\\n    }\\n}\\n\\n// Add this before Carnival.startEngine\\nCarnival.setMessageReceivedListener(RichPushNotificationExtender.class);\",\n      \"language\": \"java\",\n      \"name\": \"Android (Java)\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Message Listeners and Deep Linking\",\n  \"body\": \"Keep in mind that Deep Linking via `_u` will not call the message listener. You can still implement your deep linking logic as described in our [Deep Linking guide](https://docs.carnival.io/docs/deep-linking#section-android).\"\n}\n[/block]","excerpt":"","slug":"rich-notifications","type":"basic","title":"Android Rich Notifications"}

Android Rich Notifications


Carnival supports Android Rich Notifications out of the box for image payloads. When creating image messages, Android will automatically add the image's thumbnail to the notification with an expanded layout showing a larger image. [block:image] { "images": [ { "image": [ "https://files.readme.io/d2cff56-Screen_Shot_2017-03-23_at_1.25.38_PM.png", "Screen Shot 2017-03-23 at 1.25.38 PM.png", 1272, 1596, "#e2ddde" ], "caption": "Creating a message with an image inside the Carnival platform.", "border": true } ] } [/block] [block:image] { "images": [ { "image": [ "https://files.readme.io/e9cb256-Screenshot_20170324-063420.png", "Screenshot_20170324-063420.png", 709, 508, "#e9dfdd" ], "caption": "An Android Rich Notification on device created from the message.", "sizing": "smart", "border": true } ] } [/block] You can extend or change this default behavior by extending a `CarnivalMessageListener` 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. [block:code] { "codes": [ { "code": "public class RichPushNotificationExtender extends CarnivalMessageListener {\n protected static String TAG = \"Showcase\";\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\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 GcmIntentService: \" + e.getMessage());\n return null;\n }\n }\n\n private @Nullable Intent getDefaultIntent(@NonNull Context context) {\n Intent intent = null;\n try {\n PackageManager manager = context.getPackageManager();\n PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);\n intent = manager.getLaunchIntentForPackage(info.packageName);\n if (intent != null) {\n intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);\n }\n } catch (PackageManager.NameNotFoundException e) {\n Log.e(TAG, \"Unable to get launch intent from Package Info\");\n }\n\n Log.d(TAG, \"Loading default intent: \" + intent);\n return intent;\n }\n\n protected PendingIntent createPendingIntent(Context context, Bundle bundle) {\n PendingIntent pendingIntent = null;\n Intent intent = null;\n String deepLinkUrl = bundle.getString(\"deeplink\");\n if (TextUtils.isEmpty(deepLinkUrl)) {\n intent = new Intent(context, AppDemoActivity.class);\n } else {\n intent = new Intent();\n intent.putExtras(bundle);\n intent.setAction(Intent.ACTION_VIEW);\n intent.setData(android.net.Uri.parse(deepLinkUrl));\n intent.addFlags(Intent.FLAG_FROM_BACKGROUND);\n }\n\n TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);\n stackBuilder.addParentStack(AppDemoActivity.class);\n stackBuilder.addNextIntent(intent);\n pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);\n return pendingIntent;\n\n }\n\n @Override\n public boolean onMessageReceived(@NonNull Context context, @NonNull Bundle bundle, @Nullable Message message) {\n NotificationCompat.Builder mBuilder =\n new NotificationCompat.Builder(context)\n .setContentTitle(context.getResources().getString(R.string.app_name))\n .setSmallIcon(R.drawable.carnival_bg_notification)\n .setContentText(bundle.getString(KEY_PAYLOAD_ALERT));\n\n\n String imageUrl = bundle.getString(KEY_PAYLOAD_IMAGE_URL);\n if (TextUtils.isEmpty(imageUrl)) {\n return false;\n }\n\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 mBuilder.setLargeIcon(image);\n mBuilder.setStyle(largeFormatStyle);\n\n\n mBuilder.setContentIntent(createPendingIntent(context, bundle));\n NotificationManager mNotificationManager =\n (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);\n mNotificationManager.notify((int)System.currentTimeMillis(), mBuilder.build());\n return true;\n }\n}\n\n// Add this before Carnival.startEngine\nCarnival.setMessageReceivedListener(RichPushNotificationExtender.class);", "language": "java", "name": "Android (Java)" } ] } [/block] [block:callout] { "type": "warning", "title": "Message Listeners and Deep Linking", "body": "Keep in mind that Deep Linking via `_u` will not call the message listener. You can still implement your deep linking logic as described in our [Deep Linking guide](https://docs.carnival.io/docs/deep-linking#section-android)." } [/block]