Overview

Skill Level: Intermediate

To get started configuring basic mobile app messaging in Android apps and iOS apps that are are developed in the Xamarin framework, implement the IBM Mobile App Messaging SDK for Xamarin, and then configure your iOS app and Android app. After you implement basic mobile app messaging, you can add advanced features, such as banners, video, and calendars.

WARNING: When IBM Mobile App Messaging stores data that you send, the data is not encrypted. IBM Mobile App Messaging recommends that you do not transmit sensitive information in inbox, inapp, and mobile app messages. We do not encrypt the data in our databases or log files, or when stored on the device. If you must transmit sensitive information, encrypt the data before sending it and decrypt the data in memory on the device.

Prerequisites

To get started, you need:

Step-by-step

  1. Set up the IBM Mobile App Messaging SDK for Xamarin

    1. Download and extract the latest version of the IBM Mobile App Messaging SDK for Xamarin.Forms as described in the Prerequisites. 
    2. Start Visual Studio.
    3. ¬†In your Shared Forms project, right-click the “Dependencies” entry, and click “Add Packages”. Add the following packages:
      • Xamarin.FFImageLoading.Forms
      • Newtonsoft.json
    4. In your Shared Forms project, right-click “Dependencies”, and then click “Edit References”. Next, select the .NET Assembly tab and click the Browse button. Select the {package}/sdk/IBMMobilePush.Forms.dll file to add the file to the project.
    5. Add the following imports to the App.xaml.cs file.
      using System;
      using IBMMobilePush.Forms;
      using Newtonsoft.Json.Linq;
      
    6. In your Forms project, edit the constructor in App.xaml.cs by adding the following code, where MainPage() is the appropriate page.
      public App(JObject jsonAction = null, JObject jsonPayload = null, String attribution = null, String mailingId = null, int id = 0) {
       // The root page of your application
       MainPage = new NavigationPage(new MainPage());
      
       if (jsonAction != null) {
         SDK.Instance.ExecuteAction(jsonAction, jsonPayload, attribution, mailingId, id);
       }
      }
      
    7. Update Xamarin.Forms to the latest version.
  2. Configure your iOS application

    Configuring your iOS application includes registering the iOS app with the Apple service provider, adding the iOS app to the Watson Campaign Automation, and implementing the IBM Mobile App Messaging SDK for Xamarin in your iOS app.

    Remember: Before you begin your development with the IBM Mobile App Messaging SDK for Xamarin.Forms, you must install the iOS development tools and have an iOS provisioning file to develop iOS applications. The following instructions assume familiarity with the iOS development process.

    1. Register iOS apps with Apple service provider. For instructions, see Set up your iOS app with Apple.
    2. Add apps to the Watson Campaign Automation.

      After you register your iOS app with Apple, add your app to the Watson Campaign Automation. Marketers use the Watson Campaign Automation to send relevant simple push notifications, rich notification, in-app content at the right time that target the right customers, based on customer profile and past mobile interations. For more information about adding your apps with Watson Campaign Automation, see Adding an App in Watson Campaign Automation. 
      Note: Watson Campaign Automation documentation contains information for marketers, app developers, and organization administrators and requires a user name and password. If you need a user name and password, contact your Client Services representative.

    3. Implement the IBM Mobile App Messaging SDK for Xamarin in your iOS application
      1. Copy the {package}/sdk/IBMMobilePush.Forms.iOS.cs file into your iOS project.
      2. In your IOS project, right-click Packages and then click Add Packages. Next, add the following packages
        • Newtonsoft.json
        • NodaTime
        • SQLite.Net.Async-PCL
        • SQLite.Net-PCL
        • Xamarin.FFImageLoading.Forms
      3. Update Xamarin.Forms to the latest version.
      4. Enable interaction between IBMMobilePush.iOS and the iOS SDK, and the iOS SDK and Apple by providing IBMMobilePush.iOS with required configuration variables. Follow these steps:
        1. Create MceConfig.json and add the file to the Resources folder of the iOS project in Visual Studio.
        2. Add the following code to MceConfig.json, where <APPKEY> is your app key from Watson Campaign Automation and <PROD APPKEY> is your project ID from Apple. 

          Note: baseUrl and appKey are required. All other values are optional. For the baseURL for your Pod, see¬†Setting the baseURL. For information about loglevels, see Setting log-level message types. For information about non-sticky MUIDs and the invalidateExistingUser option, see Assign new MUIDs to devices when reinstalling apps. For information about the autoReinitialize option that determines the SDK’s behavior when the GDPR state is “true”, see Re initializing the SDK after GDPR request for erasure.

          {
            "baseUrl": "https://sdk.ibm.xtify.com/3.0/",
            "appKey": {
              "dev": "<DEV APPKEY>",
              "prod": "<PROD APPKEY>"
            },
            "autoInitializeFlag": true,
            "sessionTimeout": 20,
            "metricTimeInterval": 180,
            "loglevel": "error",
            "logfile": false,
            "invalidateExistingUser": false
          }
          
      5. To add iOS App Delegate support, edit AppDelegate.cs by following these steps:
        1. Open AppDelegate.cs and add the following code to the using section. Note: FFImageLoading.Forms.Touch is optional. Include FFImageLoading.Forms.Touch only if you want to use image InApp or inbox templates.
          using IBMMobilePush.iOS;
          using IBMMobilePush.Forms;
          using IBMMobilePush.Forms.iOS;
          using FFImageLoading.Forms.Touch;
          using UserNotifications;
          
        2. Add the following code to the start of the FinishedLaunching method. Note: FFImageLoading.Forms.Platform.CachedImageRenderer.Init() is optional. Include FFImageLoading.Forms.Platform.CachedImageRenderer.Init() only if you want to use image InApp or inbox templates.

          FFImageLoading.Forms.Platform.CachedImageRenderer.Init();
          // IBMMobilePush Integration
          MCESdk.SharedInstance ().HandleApplicationLaunch ();
          
          // Setup Push Message Permission
          if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
          {
              Logging.Verbose("iOS > 10");
          
              UNUserNotificationCenter.Current.Delegate = MCENotificationDelegate.SharedInstance();
              UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.CarPlay | UNAuthorizationOptions.Sound, (approved, err) =>
              {
                  InvokeOnMainThread(() =>
                  {
                      UIApplication.SharedApplication.RegisterForRemoteNotifications();
                  });
              });
          }
          else if (UIDevice.CurrentDevice.CheckSystemVersion(8,0))
          {
              Logging.Verbose ("iOS > 8");
              var settings = UIUserNotificationSettings.GetSettingsForTypes (UIUserNotificationType.Sound |
                  UIUserNotificationType.Alert | UIUserNotificationType.Badge, null);
          
              UIApplication.SharedApplication.RegisterUserNotificationSettings (settings);
              UIApplication.SharedApplication.RegisterForRemoteNotifications ();
          }
          else
          {
              Logging.Verbose ("iOS < 8");
              UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(UIRemoteNotificationType.Badge |
                  UIRemoteNotificationType.Sound | UIRemoteNotificationType.Alert);
          }
          
        3. Add the following methods:

          public override void DidRegisterUserNotificationSettings(UIApplication application, UIUserNotificationSettings notificationSettings) {
           MCEEventService.SharedInstance().SendPushEnabledEvent();
          }
          
          public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error) {
           MCEEventService.SharedInstance().SendPushEnabledEvent();
          }
          
          public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) {
           MCESdk.SharedInstance().RegisterDeviceToken(deviceToken);
           MCEEventService.SharedInstance().SendPushEnabledEvent();
          }
          
          public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) {
           MCEInAppManager.SharedInstance().ProcessPayload(userInfo);
           MCESdk.SharedInstance().PresentOrPerformNotification(userInfo);
          }
          
          public override void ReceivedLocalNotification(UIApplication application, UILocalNotification notification) {
           MCEInAppManager.SharedInstance().ProcessPayload(notification.UserInfo);
           MCESdk.SharedInstance().PresentOrPerformNotification(notification.UserInfo);
          }
          
          [Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
          public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action < UIBackgroundFetchResult > completionHandler) {
           MCEInAppManager.SharedInstance().ProcessPayload(userInfo);
           MCESdk.SharedInstance().PresentDynamicCategoryNotification(userInfo);
          }
          
          public override void HandleAction(UIApplication application, String actionIdentifier, NSDictionary remoteNotificationInfo, Action completionHandler) {
           MCESdk.SharedInstance().ProcessCategoryNotification(remoteNotificationInfo, actionIdentifier);
          }
          
          public override void HandleAction(UIApplication application, String actionIdentifier, UILocalNotification localNotification, Action completionHandler) {
           MCESdk.SharedInstance().ProcessDynamicCategoryNotification(localNotification.UserInfo, actionIdentifier, null);
          }
          
          public override void HandleAction(UIApplication application, string actionIdentifier, UILocalNotification localNotification, NSDictionary responseInfo, Action completionHandler) {
           NSString response = null;
           if (responseInfo.ContainsKey(UIUserNotificationAction.ResponseTypedTextKey))
             response = (NSString) responseInfo.ObjectForKey(UIUserNotificationAction.ResponseTypedTextKey);
             MCESdk.SharedInstance().ProcessDynamicCategoryNotification(localNotification.UserInfo, actionIdentifier, response);
          }
          
      6. Add references to your iOS project by following these steps:
        1. In Visual Studio, right-click References in your iOS project and then click Edit References.
        2. Select the .Net Assembly tab.
        3. Click the Browse button and then add the following .dll files:
          • {package}/sdk/IBMMobilePush.Forms.dll
          • {package}/sdk/IBMMobilePush.iOS.dll
      7. To prevent the linker from removing parts of the Xamarin SDK that are not called directly, modify linker behavior by following these steps:
        1. In Visual Studio, double-click the iOS project.
        2. Select the iOS build, which is located on the left.
        3. Change the linker behavior by selecting Don’t Link.
  3. Configure your Android application

    Configuring your Android application includes registering the Android app, adding the Android app to the Watson Campaign Automation, and implementing the IBM Mobile App Messaging SDK for Xamarin.Forms in your Android app. It is recommended that you create separate projects for your development and production builds so that you can align testing best practices.

    Remember: It is not recommended to allow your mobile app to be installed on external storage cards for several reasons that Google states on their developer site at http://developer.android.com/guide/topics/data/install-location.html#ShouldNot. Your app should be installed on internal memory.

    Important Note: When implementing a new project, IBM recommends that you use FCM because Google has deprecated GCM and will soon disable it entirely. If you have an existing project that uses GCM, it is recommended that you and migrate from GCM to FCM. For information, see Migrating from Google Cloud Messaging (GCM) to Firebase Cloud Messaging (FCM) to get your code running under FCM.

    1. Before you can send mobile app messages to app users, you must register your app with a service provider. To register with Firebase Cloud Messaging (FCM), go to the Getting Started with mobile app messaging in Android apps (FCM) tutorial and perform Step 1, Create a Google API project with Firebase Cloud Messaging. If you want to register with Google Cloud Messaging (GCM), go to the Getting started with mobile app messaging in Android apps (GCM) tutorial and perform step 1, Create a Google API project with Google Cloud Messaging (GCM) and then verify your GCM API Key. (Using GCM is not recommended.)  
    2. After you register your Android app, add your app to the Watson Campaign Automation. Marketers use the Watson Campaign Automation to send relevant simple push notifications, rich notification, in-app content at the right time that target the right customers, based on customer profile and past mobile iterations. For more information about adding your apps with Watson Campaign Automation, see Configure an App in Watson Campaign Automation. Note: Watson Campaign Automation documentation contains information for marketers, app developers, and organization administrators and requires a user name and password. If you need a user name and password, contact your Client Services representative.
    3. Copy the {package}/sdk/IBMMobilePush.Forms.Droid.cs file into your Android project.
    4. In your Android project, perform one of the following steps: 
      • If you’re using FCM, select Add Google Play Service and then add the Firebase – Messaging package. After the Firebase – Messaging package is installed, drag the google-services.json file into the Android subproject at the root of the subproject. Next, change the build option to GoogleServices.json.
        NOTE: You may need to restart Visual Studio for the build option to become available.
      • If you’re using GCM, select Add Packages and then add the Xamarin.GooglePlayServices.Gcm package.
    5. In your Android project, right-click Packages and then click Add Packages. Next, add the following packages:
      • Newtonsoft.json
      • NodaTime
      • SQLite.Net.Async-PCL
      • SQLite.Net-PCL
      • Xamarin.FFImageLoading.Forms
      • Xamarin.Android.Support.v7.AppCompat
      • Xamarin.Android.Support.Design
      • Xamarin.Android.Support.v7.CardView
      • Xamarin.Android.Support.v7.MediaRouter
    6. In your Android project, right-click References, click Edit References, select the .NET Assembly tab, and click the Browse button. Next, select the following files to add them your project:
      • IBMMobilePush.Forms.dll
      • IBMMobilePush.Droid.dll
    7. Enable interaction between IBMMobilePush.Droid and the Android SDK, and the Android SDK and Google Cloud Messaging by providing IBMMobilePush.Droid with required configuration variables. Follow these steps:
      1. Create MceConfig.json and add the file to the Assets folder of the Android project in Visual Studio.
      2. Add the following code to MceConfig.json, where <APPKEY> is your app key from Watson Campaign Automation and <SENDER ID> is the project number that Google created for you when you created the project. If you are using Firebase Cloud Messaging, replace <SENDER ID> with an empty string, and in messagingService, replace “gcm” with “fcm”.

        Note: baseUrl, appKey, and senderId are required. All other values are optional. For the baseURL for your Pod, see Setting the baseURL. For information about loglevels, see Setting log-level message types. For information about non-sticky MUIDs and the invalidateExistingUser option, see Assign new MUIDs to devices when reinstalling apps. For information about the autoReinitialize option that determines the SDK’s behavior when the GDPR state is “true”, see Re initializing the SDK after GDPR request for erasure.

        {
         "baseUrl": "https://sdk.ibm.xtify.com/3.0", 
         "appKey": 
         {
           "prod":"<APPKEY>"
         },
         "senderId": "<SENDER ID>",
         "sessionsEnabled": true,
         "sessionTimeout": 20,
         "metricTimeInterval": 30,
         "loglevel": "error",
         "logfile": false,
         "messagingService": "gcm",
         "invalidateExistingUser": false
        }
        
      3. Update properties for MceConfig.json and set Build Action to AndroidAsset.
    8. To allow the Android SDK to execute push services for your Android application, edit the AndroidManifest.xml file by following these steps:
      1. Open Properties/AndroidManifest.xml file in your Android project.
      2. Change the application class name by setting the “android:name” property to “com.ibm.mce.sdk.api.MceApplication” in the AndroidManifest.xml <application> node.
        For example:
        <application android:label="app.name" android:name="com.ibm.mce.sdk.api.MceApplication">
        
      3. Click the Source view tab and add the following code to the <manifest> node, where <APP_PACKAGE_NAME> is your application package name:
         <!-- C2D_MESSAGE is required for receiving GCM messages -->
         <permission android:name="<APP_PACKAGE_NAME>.permission.C2D_MESSAGE" android:protectionLevel="signature" />
        
         <!-- C2D_MESSAGE is required for receiving GCM messages -->
         <uses-permission android:name="<APP_PACKAGE_NAME>.permission.C2D_MESSAGE" />
        
         <!-- c2dm.permission.RECEIVE is required for receiving GCM messages -->
         <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
        
         <!-- INTERNET is required for calling the MCE server -->
         <uses-permission android:name="android.permission.INTERNET" />
        
         <!-- WAKE_LOC is required for running scheduled tasks -->
         <uses-permission android:name="android.permission.WAKE_LOCK" />
        
         <!-- RECEIVE_BOOT_COMPLETED is required for performing SDK task on device startup -->
         <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
        
         <!-- VIBRATE is required for notification configuration -->
         <uses-permission android:name="android.permission.VIBRATE" />
        
         <!-- CALL_PHONE is optional. It is only required is the dial action is used -->
         <uses-permission android:name="android.permission.CALL_PHONE" />
        
         <!-- ACCESS_FINE_LOCATION is optional. It is only required if location services needs to use GPS location -->
         <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        
         <!-- ACCESS_COARSE_LOCATION is optional. It is only required if location services needs to use network location -->
         <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        
         <!-- BLUETOOTH is optional. It is only required if iBeacons are supported -->
         <uses-permission android:name="android.permission.BLUETOOTH" />
        
         <!-- BLUETOOTH_ADMIN is optional. It is only required if iBeacons are supported -->
         <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
        
      4. Add the following code to the <application> node, where <APP_PACKAGE_NAME> is your application name:
         <!-- This is required for google play services -->
         <meta-data android:name = "com.google.android.gms.version" android:value = "@integer/google_play_services_version" />
        
         <!-- The provider is needed for the SDK database -->
         <provider android:name = "com.ibm.mce.sdk.db.Provider" android:authorities = "<APP_PACKAGE_NAME>.MCE_PROVIDER" android:exported = "false" />
        
         <!-- NotifActionReceiver is required for notification handling -->
         <receiver android:name = "com.ibm.mce.sdk.notification.NotifActionReceiver" />
        
         <!-- AlarmReceiver is required for SDK scheduled tasks and device status updates -->
         <receiver android:name = "com.ibm.mce.sdk.wi.AlarmReceiver">
           <intent-filter>
             <action android:name = "android.intent.action.BOOT_COMPLETED" />
           </intent-filter>
           <intent-filter>
             <action android:name = "android.intent.action.TIMEZONE_CHANGED" />
           </intent-filter> 
           <intent-filter>
             <action android:name = "android.intent.action.PACKAGE_REPLACED" />
             <data android:scheme = "package" />
           </intent-filter> 
           <intent-filter>
             <action android:name = "android.intent.action.LOCALE_CHANGED" />
           </intent-filter> 
         </receiver>
        
         <service android:name = "com.ibm.mce.sdk.session.SessionTrackingIntentService" />
        
         <!-- LocationUpdateCaller is used for scheduling location updates -->
         <receiver android:name = "com.ibm.mce.sdk.location.LocationUpdateCaller" />
        
         <!-- EventsAlarmListener is required for event handling -->
         <service android:name = "com.ibm.mce.sdk.events.EventsAlarmListener" />
        
         <!-- PhoneHomeIntentService is required to allow the client to contact the server to update state -->
         <service android:name = "com.ibm.mce.sdk.registration.PhoneHomeIntentService" />
        
         <!-- RegistrationIntentService is required for SDK registration -->
         <service android:name = "com.ibm.mce.sdk.registration.RegistrationIntentService" />
        
         <!-- AttributesQueueConsumer is required for attributes handling -->
         <service android:name = "com.ibm.mce.sdk.attributes.AttributesQueueConsumer" />
        
         <!-- SnoozeIntentService is optional. It is required only if snooze action is used -->
         <service android:name = "com.ibm.mce.sdk.plugin.snooze.SnoozeIntentService" />
        
         <!-- InboxUpdateService is optional. It is used for retrieving ibox updates from the MCE server. It is required only if inbox is used -->
         <service android:name = "com.ibm.mce.sdk.plugin.inbox.InboxUpdateService" />
        
         <!-- LocationRetrieveService is optional. It is used for retrieving the device location. It is required only if locations are enabled -->
         <service android:name = "com.ibm.mce.sdk.location.LocationRetrieveService" />
        
         <!-- GeofenceIntentService is optional. It is used to receive geofence events. It is required only if locations are enabled and geofences are used -->
         <service android:name = "com.ibm.mce.sdk.location.GeofenceIntentService" />
        
         <!-- LocationRetrieveService is optional. It is used to handle location events backoff. It is required only if locations are enabled -->
        
         <service android:name = "com.ibm.mce.sdk.location.LocationEventsIntentService" />
         <!-- LocationSyncAlarmListener is optional. It is used to scheduled location sync. It is required only if inbox is used -->
        
         <service android:name = "com.ibm.mce.sdk.location.LocationSyncAlarmListener" />
        
         <!-- MceBluetoothScanner is optional. It is used to run the bluetooth scan. It is required only if iBeacons is used -->
         <service android:name = "com.ibm.mce.sdk.beacons.MceBluetoothScanner" />
        
         <!-- MceBluetoothScanner is optional. It is used to verify bluetooth scan. It is required only if iBeacons is used -->
         <service android:name = "com.ibm.mce.sdk.beacons.BeaconsVerifier" />
        
         <!-- MdeJobService is used for launching a job while the app is in the foreground. This is only used in Android O and above -->
         <service android:name = "com.ibm.mce.sdk.job.MceJobService" android:permission = "android.permission.BIND_JOB_SERVICE" />
        

        If you’re using GCM, add:

        <service android:name="com.ibm.mce.sdk.gcm.MceGcmListenerService" android:exported="false">
          <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
          </intent-filter>
        </service>
        
        <receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:priority="999">
         <intent-filter android:permission="com.google.android.c2dm.permission.SEND">
           <action android:name="com.google.android.c2dm.intent.RECEIVE" />
             <category android:name="<APP_PACKAGE_NAME>" />
           </intent-filter>
           <intent-filter android:permission="com.google.android.c2dm.permission.SEND" android:priority="999">
             <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
             <category android:name="<APP_PACKAGE_NAME>" />
           </intent-filter>
        </receiver>
        

        If you’re using FCM, add:

        <!-- FCM Registration -->
        <service android:name = "com.ibm.mce.sdk.fcm.FcmInstanceIdService" >
          <intent-filter >
            <action android:name = "com.google.firebase.INSTANCE_ID_EVENT" />
          </intent-filter> 
        </service>
        
        <!-- FCM Messages -->
        <service android:name = "com.ibm.mce.sdk.fcm.FcmMessagingService" >
         <intent-filter >
           <action android:name = "com.google.firebase.MESSAGING_EVENT" />
         </intent-filter> 
        </service>
        
        <!-- https://github.com/xamarin/GooglePlayServicesComponents/issues/20 -->
        <!-- put this inside your application element -->
        <receiver android:name = "com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported = "false" />
        
        <receiver android:name = "com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported = "true" android:permission = "com.google.android.c2dm.permission.SEND" >
          <intent-filter >
            <action android:name = "com.google.android.c2dm.intent.RECEIVE" />
            <action android:name = "com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name = "<APP_PACKAGE_NAME>" />
          </intent-filter> 
        </receiver>
        
    9. Edit the MainActivity.cs file by following these steps:
      1. Remove Theme = “@style/MyTheme” from Activity definition.
      2. Add the following code to the OnCreate method: 
        FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true);
        base.OnCreate(savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        
        var jsonActionString = this.Intent.GetStringExtra("action");
        if (jsonActionString != null) {
         var jsonAction = JObject.Parse(jsonActionString);
         JObject jsonPayload = null;
         if (this.Intent.HasExtra("payload")) {
           jsonPayload = JObject.Parse(this.Intent.GetStringExtra("payload"));
         }
         var attribution = this.Intent.GetStringExtra("attribution");
         int id = 0;
         try {
           id = Int32.Parse(this.Intent.GetStringExtra("id"));
         } catch {}
        
         var mailingId = this.Intent.GetStringExtra("mailingId");
         LoadApplication(new App(jsonAction, jsonPayload, attribution, mailingId, id));
        } else {
         LoadApplication(new App());
        }
        

        Note: FFImageLoading.Forms.Platform.CachedImageRenderer.Init() is optional. Include FFImageLoading.Forms.Platform.CachedImageRenderer.Init() only if you want to use image InApp or Inbox templates.

      3. Add the following code to the top of the MainActivity.cs file:
        using IBMMobilePush.Droid.API;
        using FFImageLoading.Forms.Droid;
        using Newtonsoft.Json.Linq;
        using Org.Json;
        

        Note: FFImageLoading.Forms.Droid is optional. Include FFImageLoading.Forms.Droid only if you want to use image InApp or Inbox templates.

      4. Change MainActivity superclass to “global::Xamarin.Forms.Platform.Android.FormsApplicationActivity, ActivityCompat.IOnRequestPermissionsResultCallback”
      5. Remove the following lines:
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;
        
      6. Add the following methods:
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults) {
         if (requestCode == 0) {
           // Check if the only required permission has been granted
           if (grantResults.Length == 1 &amp;&amp; grantResults[0] == Permission.Granted) {
             Logging.Info("Location permission was granted.");
             SDK.Instance.ManualLocationInitialization();
           } else {
             Logging.Info("Location permission was NOT granted.");
           }
         } else {
           base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
         }
        }
        
      7. Add the following:

        <div style="background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
        <pre style="margin: 0; line-height: 125%;"><span style="color: #008800; font-weight: public static MainActivity Current { private set; get; }
                protected override void OnCreate(Bundle savedInstanceState)
                {
                    Current = this;
                    if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
                    {
                        createNotificationChannel();
                    }
                    ...
        
        void createNotificationChannel() {
                    var channelId = "mce_sample_channel";
                    var name = new Java.Lang.String("MCE SDK Notification Channel");
                    var description = "This is the notification channel for the MCE SDK sample application";
                    var importance = Android.App.NotificationImportance.High;
        
                    var context = Android.App.Application.Context;
        
                    var notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);
                    var channel = notificationManager.GetNotificationChannel(channelId);
                    if (channel == null)
                    {
                        channel = new NotificationChannel(channelId, name, importance);
                        channel.Description = description;
        
                        var notificationsPreference = MceSdk.NotificationsClient.NotificationsPreference;
                        notificationsPreference.SetNotificationChannelId(context, channelId);
                        notificationManager.CreateNotificationChannel(channel);
                    }
        
                }
        
    10. Update Xamarin.Forms to the latest version.
    11. Disable linker from iOS and Android by following these steps:
      1. Double-click the Android project.
      2. Select the Android build, which is located on the left.
      3. Change the linker behavior by selecting Don’t Link.
  4. Test push notifications for your iOS and Android apps

    After you implement the IBM Mobile App Messaging SDK for Xamarin and configure your iOS and Android applications, use the sample app that is provided by the IBM Mobile App Messaging SDK for Xamarin to test push notifications. The sample app demonstrates end-to-end functions, including basic mobile app messages. 

     

    The sample app provides a safe environment where you can teach yourself how to build mobile app messages for iOS and Android apps. The sample app provides the following information:

    • Credential and ID screens that display the following values: user ID, channel ID, development app key, and production app key.
    • Push action screen that displays the default and custom push actions that might be used when you send a mobile app message to your app users.
    • Custom action screen that displays details about the example categories you might use with the sample app.
    • Test events so you can send events to the server.
    • Test user attributes so you can send a user attribute to the server.
    1. Disable App Transport Security (ATS). ATS is an Apple technology that disables access to HTTP resources that are not white-listed. Disable ATS before testing your iOS device. Later, after you complete your testing, you can enable ATS again. To disable ATS, open the Info.plist file and add the following code:
       
      <key>NSAppTransportSecurity</key>
      <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
      </dict>
      
    2. iOS apps: Build sample app and test push notifications for iOS apps:
      1. Make sure that the Apple Push Notification Service is enabled for your App ID, which is verified in the Apple Provisioning Portal. An Apple ID and password is required.
      2. Create an iPhone app key on the Watson Campaign Automation console and upload the APNS certificate.
      3. Open the sample application in Visual Studio.
      4. Update MceConfig.json by replacing the devAppKey and prodAppKey values with your development app key and production app key. Also, make sure the baseURL matches the server that is registered with your application key.
      5. Update the bundle identifier with the bundle ID that was set up within Apple’s provisioning website.
      6. Verify that the code signing is correctly configured.
    3. Android apps: Build sample app and test push notifications for Android apps: 
      1. Go to ibm-mobile-push-xamarin-sdk-<version number>/samples/sample. Make sure Demo is selected.
      2. Update MceConfig.json by replacing prodAppKey with your production your app key and the senderid with your Google sender ID. Also, make sure the baseURL matches the server that is registered with your application key.
      3. If you’re not using the US server, go to MceConfig.json and update your server. For example, eu is for European Union and a URL is for a different MCE server.
      4. When you create your Android Virtual Device (AVD), you must build a virtual device that is based on the Google Messaging API. A normal AVD results in silent failure.
        1. In Visual Studio, select Tools > Open Android SDK Manager and make sure the baseUrl matches the server that is registered with your application key.
        2. In Visual Studio, select Tools > Android Devices > Create Emulator.
          1. Select New, and enter a name.
          2. Under Target, make sure to select an option that uses Google APIs, such as Google APIs (Google Inc.) – API Level 16.
          3. After the device is created and started, you must also add an active Google account to the device through Settings > Accounts.
      5. Plug in an Android device into your machine, and run the app. Your emulator must be connected to a Google account for the GCM/FCM push to work. You can verify that the connection is initially working by sending an email to an account that was set up on your emulator.
  5. Prepare iOS app for App store distribution

    Before you submit your app to the App Store, you must properly configure and test an ad hoc build of your app.

    It can be a bit confusing when you first encounter all of the different profiles, certificates, and keys that are required for implementing mobile app messages within your app.

    There are two types of profiles Apple offers for testing and releasing iOS applications: Development and Distribution. These profiles also relate to the application type that you set up with IBM Mobile Push Notification in the console. Applications that are built with the Apple development profile need to be assigned to the development or testing application type in the console. Similarly, applications that are built with the Apple distribution profile need to be assigned to the production application type in the console.

    There are two subclasses of Apple distribution profiles: Ad hoc and App Store. Before you submit your app to the App Store, you should absolutely build a version of your app with an ad hoc distribution profile. In this way, you are able to associate your production application with your test devices. This helps you review the experience that your users have when they use IBM Mobile Push Notification and Apple production push facilities, and have confidence that your app works properly.

    Here is a quick walkthrough on how to set up your app with an ad hoc distribution profile.

    1. Follow the instructions for integrating mobile app messages with your app. Within the application configuration section of the Apple Provisioning Portal, make sure that you enable your application for use with the Production APNS service. The certificate that you generate and upload to IBM Mobile Push Notification must be in production in order for your ad hoc app build to work.
    2. Go to the Apple iOS Provisioning Portal.
      1. Click Devices, and add your test device IDs. You can get your device ID through the Xcode organizer or through iTunes. You can find the instructions at https://developer.apple.com/library/ios/recipes/xcode_help-devices_organizer/articles/locate_device_identifier.html#//apple_ref/doc/uid/TP40010392-CH17.
      2. Click Provisioning > Distribution > New Profile.
        1. Select Distribution Method: Ad hoc.
        2. Select the appropriate app ID associated with the production push service.
        3. Select your test devices. Note: Your ad hoc build does not work on devices that are not set up here.
        4. Click Submit. Download your new ad hoc distribution profile to your computer, and install it in Xcode by double-clicking it.
    3. Go back to your app in Xcode.
      1. Go to Project Build Settings.
      2. Under Code Signing > Release, select your new Distribution Profile.
      3. Make sure to do the same under Target Build Settings as well.
    4. Delete the development version of your app from your device. If you try to build your production ad hoc version of your app over your development version, it may not recognize the production entitlements and you will not receive a push.
    5. Make sure that your app is set up correctly in the IBM Mobile Push Notification console.¬†Note: This is the step that most first-timers get wrong and is the root cause of about 90% of the support requests that “I’m not getting a mobile app message sent to my phone.” Make sure to double check this step.
      1. The Application Key Type must be Production.
      2. The .p12 file that you uploaded must be the production-version of the certificate you created in Step 1 within Apple’s iOS Provisioning Portal.
      3. With your device connected to your computer, build the app on your phone, and watch the Xcode console for the string Attempt to register after your app fires up. You should see success messages for both Apple push services and IBM Mobile Push Notification registration and your token. Note: If you see the same token as your development build, then there is a provisioning profile mismatch in Xcode.
    6. Build your application. Connect your iOS device to your computer and build it. Your app and ad hoc provisioning profile are loaded onto your device, and you can begin testing right away.
    7. Send your app to other test devices.
      1. You can either connect your other test devices to your computer and build the app for it, if their device ID was associated to the ad hoc profile in the Apple Provisioning Portal. You can email the compiled .app on your computer and the downloaded provisioning profile to your testers and they can drag/drop/sync in iTunes.
      2. You can use the Over the Air method. Search for how to engage this method.
    8. After you successfully tested your app, perform the following steps.
      1. Edit MceConfig.json and set xLogging to false.
      2. Go back to Apple iOS Provisioning Portal > Provisioning, and create an App Store distribution profile instead of ad hoc.
      3. Also, read the information about dirtied provisioning profiles at http://stackoverflow.com/questions/5681172/bundle-identifier-and-push-certificate-aps-environment-entitlement-error. In certain circumstances, your app may not receive the appropriate entitlements when going into the App Store.
      4. Download the new Distribution Profile and associate it with your Project and Target Build Settings for Release.
      5. You can verify that your Distribution Profile is correct by opening it in a text editor and verifying that it has the correct production values. It must contain the following key/value: aps-environment production.
      6. Build the app.
      7. Go to iTunes Connect, and follow the instructions for submitting your app for approval. For more information about iTunes Connect, see https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa.
      8. If you are incorporating location-based services within your app, it is important to disclose to Apple exactly how you use this data. For example, “My app can, at the user’s option, use location data to present relevant and timely content.”
      9. Wait for approval.

    Remember: 97% are approved within five business days.

Expected outcome

This tutorial takes you through the basic steps to configure mobile app messages in Android apps and iOS apps that are developed in the Xamarin.Forms framework. It explains how to implement the IBM Mobile App Messaging SDK for Xamarin and then configure your Android apps and your iOS apps. After configuring basic mobile app messages, you can configure advanced mobile app messaging features, such as banners, video, and calendars. For information about advanced features, see the Documentation.

Go Back to Mobile App Messaging home page.

 

Join The Discussion

Your email address will not be published. Required fields are marked *