{"_id":"57b0f17a4430cf0e00277921","project":"55e67aaa9cc7c62b00c4a1ea","user":"55d29988486de50d00327118","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"},"parentDoc":null,"__v":2,"category":{"_id":"55e67b5556007d23005fee7d","__v":35,"pages":["55e67b91de6fef23009480cb","55e67c28de6fef23009480ce","55e67c3cde6fef23009480d1","55e680e185a9741900314e96","55e682b7de6fef23009480dc","55ecd69bb2714d2100f227c0","55ecd6c554a67b1700edcf40","55ecd6edae66a30d00446ce7","55ecd777b2714d2100f227c2","55ecda5a7659d21700a7ef9b","55ecdaf6ae66a30d00446cf3","55ed006a0d968e2100de831e","55ed0258c9d5b3350072ae7a","55ee66a073d3941700f760e5","55f5ef61a1dea80d00a5dec5","55f5f38618b39b0d00c27eb0","55f9f86417b9d00d00969e29","55f9fdc8aba81f0d00a1156d","561b10b4c89cc30d0082154f","561b110a03bce90d00c4bd11","561c6195ad272c0d00a892dd","561c6ca0be5fb20d00077754","564f3e66c133343500286ca0","565b955b922c9a0d00d1f124","566784d2919aaa0d008e32db","566e1ee5972a290d00552084","569c58d77c3e44170014114f","56a2692f6928550d006c8327","56ca6c868014e417002bfe54","56cfa5386c5d7a13005eec0f","56e73d86555c030e00a52a73","56e7460c9000b120000ffe2e","56e8c19e99c6400e003820cf","56e8c53fc88bf80e00f8bed8","56f06ff4d386ce0e008e9b21"],"project":"55e67aaa9cc7c62b00c4a1ea","version":"55e67aab9cc7c62b00c4a1ed","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-09-02T04:30:13.305Z","from_sync":false,"order":1,"slug":"install-in-your-app","title":"Install in your app"},"updates":["590fb8e335cf270f008e961d"],"next":{"pages":[],"description":""},"createdAt":"2016-08-14T22:32:26.795Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"## Customizing the user interface\n\nSometimes, you might want to implement your own user interface for a full screen message that more closely matches the look and feel of your UI.\n\nOverride the following callback method, and return `false`, which ensures that Carnival's interface isn't displayed.  At this point you can construct your own full screen message interface using the `CarnivalMessage` object in iOS or 'Message' object in Android.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//On iOS, using Objective-C\\n\\n- (BOOL)shouldPresentMessageDetailForMessage:(CarnivalMessage *)message {\\t\\n  // Do something with the message\\n  return NO;\\t\\n}\\n\\n//Be sure to assign your delegate to CarnivalMessageStream\\n[CarnivalMessageStream setDelegate:self]\\n\\n\\n// This delegate is called anytime [CarnivalMessageStream presentMessageDetailForMessage:message] is called. Alternatively, just present your view controller manually.\",\n      \"language\": \"objectivec\",\n      \"name\": \"iOS (Objective-C)\"\n    },\n    {\n      \"code\": \"//On iOS, using Swift\\n\\nfunc shouldPresentMessageDetailForMessage(message: CarnivalMessage) -> Bool {\\n\\treturn false\\n}\\n\\n//Be sure to assign your delegate to CarnivalMessageStream\\nCarnivalMessageStream.setDelegate(self)\\n\\n// This delegate is called anytime [CarnivalMessageStream presentMessageDetailForMessage:message] is called. Alternatively, just present your view controller manually.\",\n      \"language\": \"swift\",\n      \"name\": \"iOS (Swift)\"\n    },\n    {\n      \"code\": \"//For setting the Intent fired when a notification is interacted with, use NotificationConfig#setDefaultContentIntent(Intent, int, int) so that push payload data can be added to the PendingIntent when the Notification is built.\\n\\nIntent intent = new Intent(getApplicationContext(), MyMessageDetail.class);\\nint requestCode = 123;\\n\\nNotificationConfig config = new NotificationConfig();\\nconfig.setDefaultContentIntent(intent, requestCode, PendingIntent.FLAG_UPDATE_CURRENT);\\n//If a push has a Message attached, the message will be added to the Intent's extras under Carnival.EXTRA_PARCELABLE_MESSAGE.\\n\\nprotected void onResume() {\\n    super.onResume();\\n\\n    String messageId = getIntent().getStringExtra(Carnival.EXTRA_MESSAGE_ID);\\n\\n    Carnival.getMessage(messageId, new Carnival.CarnivalHandler<Message>() {\\n        :::at:::Override\\n        public void onSuccess(Message value) {\\n            message = value;\\n            // Do stuff with the message\\n        }\\n\\n        @Override\\n        public void onFailure(Error error) {\\n            Log.e(TAG, \\\"Failed to load message: \\\" + error);\\n        }\\n    });\\n}\\n\\n\\n// For setting the Intent fired when a message in a message stream is tapped, intialise this as you normally would any other.\",\n      \"language\": \"java\",\n      \"name\": \"Android (Java)\"\n    },\n    {\n      \"code\": \"// Retrieve the message stream and store it in memory.\\n// If you are building a message stream, you can reuse the result from a previous\\n// call to Carnival.messages().\\nvar messages = {};\\nCarnival.messages(\\n  function callback(data) {\\n    // 'data' contains an array of messages\\n    for (var i in data) {\\n      var message = data[i];\\n      messages[message.id] = message;\\n    }\\n  },\\n  function errorHandler(err) {\\n    console.error('An error occurred: ' + err);\\n  }\\n);\\n\\n// In your message stream logic, add a listener to register \\n// an impression, then open your custom message view\\nmessageListItem.addEventListener('click', function() {\\n  // First, register an impression\\n  var messageId = this.getAttribute('data-message-id');\\n  var message = messages[messageId];\\n  Carnival.registerImpression(Carnival.MessageImpressionType.DetailView, message);\\n  \\n  // Add your logic to display the detail view for this message, \\n  // or to deeplink the user to the link URL for this message.\\n});\",\n      \"language\": \"javascript\",\n      \"name\": \"Cordova (JavaScript)\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Not available in Unity and React Native\",\n  \"body\": \"Due to limitations of current plugin architecture in Unity and React Native, it is not currently possible to override the stock experience for in-app notifications. Rest assured, you can still deliver these notifications, but you won't be able to customize their UX. We hope to bring customization to these platforms in the near future.\"\n}\n[/block]\n## Registering an impression event\n\nIn order to support impression analytics in your custom in-app notification, you will need to ensure you register an impression event when it is shown.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//On iOS, using Objective-C\\n \\n[CarnivalMessageStream registerImpressionWithType:CarnivalImpressionTypeDetailView forMessage:message];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"//On iOS, using Swift\\n   CarnivalMessageStream.registerImpressionWithType(CarnivalImpressionType.DetailView, forMessage: message)\\n\",\n      \"language\": \"swift\"\n    },\n    {\n      \"code\": \"//On Android, using Java\\n\\nCarnival.registerMessageImpression(message, CarnivalImpressionType.IMPRESSION_TYPE_DETAIL_VIEW);\\n\",\n      \"language\": \"java\"\n    },\n    {\n      \"code\": \"//On Cordova, using JavaScript\\n\\nCarnival.registerImpression(Carnival.MessageImpressionType.DetailView, message);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"//On Unity, using C#\\n\\nCarnival.RegisterImpression(message, CarnivalImpressionType.DetailView); \\n\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]","excerpt":"","slug":"customizing-full-screen-messages","type":"basic","title":"Customizing Full Screen Messages"}

Customizing Full Screen Messages


## Customizing the user interface Sometimes, you might want to implement your own user interface for a full screen message that more closely matches the look and feel of your UI. Override the following callback method, and return `false`, which ensures that Carnival's interface isn't displayed. At this point you can construct your own full screen message interface using the `CarnivalMessage` object in iOS or 'Message' object in Android. [block:code] { "codes": [ { "code": "//On iOS, using Objective-C\n\n- (BOOL)shouldPresentMessageDetailForMessage:(CarnivalMessage *)message {\t\n // Do something with the message\n return NO;\t\n}\n\n//Be sure to assign your delegate to CarnivalMessageStream\n[CarnivalMessageStream setDelegate:self]\n\n\n// This delegate is called anytime [CarnivalMessageStream presentMessageDetailForMessage:message] is called. Alternatively, just present your view controller manually.", "language": "objectivec", "name": "iOS (Objective-C)" }, { "code": "//On iOS, using Swift\n\nfunc shouldPresentMessageDetailForMessage(message: CarnivalMessage) -> Bool {\n\treturn false\n}\n\n//Be sure to assign your delegate to CarnivalMessageStream\nCarnivalMessageStream.setDelegate(self)\n\n// This delegate is called anytime [CarnivalMessageStream presentMessageDetailForMessage:message] is called. Alternatively, just present your view controller manually.", "language": "swift", "name": "iOS (Swift)" }, { "code": "//For setting the Intent fired when a notification is interacted with, use NotificationConfig#setDefaultContentIntent(Intent, int, int) so that push payload data can be added to the PendingIntent when the Notification is built.\n\nIntent intent = new Intent(getApplicationContext(), MyMessageDetail.class);\nint requestCode = 123;\n\nNotificationConfig config = new NotificationConfig();\nconfig.setDefaultContentIntent(intent, requestCode, PendingIntent.FLAG_UPDATE_CURRENT);\n//If a push has a Message attached, the message will be added to the Intent's extras under Carnival.EXTRA_PARCELABLE_MESSAGE.\n\nprotected void onResume() {\n super.onResume();\n\n String messageId = getIntent().getStringExtra(Carnival.EXTRA_MESSAGE_ID);\n\n Carnival.getMessage(messageId, new Carnival.CarnivalHandler<Message>() {\n @Override\n public void onSuccess(Message value) {\n message = value;\n // Do stuff with the message\n }\n\n @Override\n public void onFailure(Error error) {\n Log.e(TAG, \"Failed to load message: \" + error);\n }\n });\n}\n\n\n// For setting the Intent fired when a message in a message stream is tapped, intialise this as you normally would any other.", "language": "java", "name": "Android (Java)" }, { "code": "// Retrieve the message stream and store it in memory.\n// If you are building a message stream, you can reuse the result from a previous\n// call to Carnival.messages().\nvar messages = {};\nCarnival.messages(\n function callback(data) {\n // 'data' contains an array of messages\n for (var i in data) {\n var message = data[i];\n messages[message.id] = message;\n }\n },\n function errorHandler(err) {\n console.error('An error occurred: ' + err);\n }\n);\n\n// In your message stream logic, add a listener to register \n// an impression, then open your custom message view\nmessageListItem.addEventListener('click', function() {\n // First, register an impression\n var messageId = this.getAttribute('data-message-id');\n var message = messages[messageId];\n Carnival.registerImpression(Carnival.MessageImpressionType.DetailView, message);\n \n // Add your logic to display the detail view for this message, \n // or to deeplink the user to the link URL for this message.\n});", "language": "javascript", "name": "Cordova (JavaScript)" } ] } [/block] [block:callout] { "type": "warning", "title": "Not available in Unity and React Native", "body": "Due to limitations of current plugin architecture in Unity and React Native, it is not currently possible to override the stock experience for in-app notifications. Rest assured, you can still deliver these notifications, but you won't be able to customize their UX. We hope to bring customization to these platforms in the near future." } [/block] ## Registering an impression event In order to support impression analytics in your custom in-app notification, you will need to ensure you register an impression event when it is shown. [block:code] { "codes": [ { "code": "//On iOS, using Objective-C\n \n[CarnivalMessageStream registerImpressionWithType:CarnivalImpressionTypeDetailView forMessage:message];", "language": "objectivec" }, { "code": "//On iOS, using Swift\n CarnivalMessageStream.registerImpressionWithType(CarnivalImpressionType.DetailView, forMessage: message)\n", "language": "swift" }, { "code": "//On Android, using Java\n\nCarnival.registerMessageImpression(message, CarnivalImpressionType.IMPRESSION_TYPE_DETAIL_VIEW);\n", "language": "java" }, { "code": "//On Cordova, using JavaScript\n\nCarnival.registerImpression(Carnival.MessageImpressionType.DetailView, message);", "language": "javascript" }, { "code": "//On Unity, using C#\n\nCarnival.RegisterImpression(message, CarnivalImpressionType.DetailView); \n", "language": "csharp" } ] } [/block]