Migration Guide

We use a three-level versioning system for SDK releases. The three-level versioning system guarantees backward compatibility between siblings in the second and third levels of release numbers in the form M.X.Y.

A variation in the third level of the version number (Y in the example above) indicates that only bug fixes and security patches have been included, so compatibility between siblings is guaranteed.

Variation in the second level (X in the example above) indicates that new methods and functionalities have been added, and that old methods or accessors may have been deprecated. Deprecation warnings are expected in these releases.

In the main level of version number (M in this case), we remove the previously announced deprecated functions and clean up the code, so binary compatibility with previous releases is not guaranteed.

This Versioning system starts in V3.

One of the main features added to the V3 release is support to configure the SDK via external configuration files. The original method of setting the SDK up via code is still supported. This support is different on iOS and in Android, as the SDK uses the recommended approach for each platform (.plists in iOS and a new XML file in Android).

iOS

Deprecated functions and classes


Class UnstoredIncomingMessage

In SDK V3 we've deprecated the class UnstoredIncomingMessage in favor of the new Message class. This new class simplifies the handling of Push notifications arriving to the SDK instance.

The new Message class has the exact same fields used by our REST API.

The attributes of this new class are:

String blastID
String id
String type
String from
String to
String subject
String text
String status
String statusDescription
String date
String timezone
String clientId
String appName
String platform
String metadata

The Method available from this class are

- (id) init;
- (NSDictionary *) toDictionary;
- (BOOL) save;
- (BOOL) delete;
+ (NSArray *) getAllMessages;
+ (NSArray *) getAllSortedMessages;

So you can retrieve all Messages stored in the device, and save, update or delete a single message in a simpler way.

Please refer to the REST API Documentation for more information.

Function messageLoadFinishedReturningMessage

This function has been deprecated in favor of pushReceived:(Message)message, using the new Message class and replicating the same functionality already present in the Android version of the SDK.

Configuring the Messangi SDK programmatically

The traditional method for initializing the Messangi SDK is still supported by adding the SDK credentials directly in the code inside the AppDelegate's didFinishLaunchingWithOptions method:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
    UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

     ...
     
     [[Messangi sharedInstance] setAppName: @"..."];
     [[Messangi sharedInstance] setClientID: @"..."];
     [[Messangi sharedInstance] setApiClientPrivateKey: @"..."];
    
     [[Messangi sharedInstance] setSubscriptionInstanceID:@"..."];
     [[Messangi sharedInstance] setSubscriptionURL:@"...."];

    [[Messangi sharedInstance] initSubscriptions];
    [[Messangi sharedInstance] initMessangi];
    [[Messangi sharedInstance] registerDialog];
     
     ...
    
    return YES;
}
Configuring the Messangi SDK via config files

You can now create a configuration file to store the SDK credentials, allowing an easy transition from Development to Production while testing the app:

1. Create the Config Files
  • in xCode click on the lower left corner “+” sign
  • Click in “File…” option
  • In the newly opened window select “Property List” in the Type of Files section. Add the name of the new file
  • Now need add these Properties

= Required =

name:   appName
type:   String
Description: The appName provided by Ogangi

name:   clientID
type:   String
Description: The cliendID provided by Ogangi

name:   apiClientPrivateKey
type:   String
Description: The privateKey provided by Ogangi

= Optional for subscriptions =

name:   subscriptionURL
type:   String
Description: The subscription URL provided by Ogangi
Default value: null

name:   subscriptionInstanceID
type:   String
Description: The workspace ID provided by Ogangi
Default value: null

= Optional for the Environment =

name:   maxStoredMessages
type:   Number
Description: The max number of messages to be stored in device, 0 for not limit
Default value: 0

name:   analyticsDisabled
type:   Boolean
Description: Send Analytic info to the BI platform
Default value: false

name:   locationDisabled
type:   Boolean
Description: Use location of the device (Geopush, Geofence, Beacon won't work if disabled)
Default value: false

name:   LoggingDisabled
type:   Boolean
Description: Show debug information of the SDK in the console
Default value: false    

The optional fields for subscriptions and environment can be stored in different files if needed.

2. Add this code to the didFinishLaunchingWithOptions function in your AppDelegate
    [[Messangi sharedInstance] loadMessangiCredentials:@"<Name of file with the Credentials>"];
    [[Messangi sharedInstance] loadSubscriptionsFromFile:@"<Name of file hawiths the Subscription>"];
    [[Messangi sharedInstance] loadEnvironmentFromFile:@"<Name of file with the Environment>"];

Example:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
    UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    [[Messangi sharedInstance] loadMessangiCredentials:@"messangiCredentials"];
    [[Messangi sharedInstance] loadSubscriptionsFromFile:@"messangiSubscriptionList"];
    [[Messangi sharedInstance] loadEnvironmentFromFile:@"messangiProperties"];

    [[Messangi sharedInstance] initSubscriptions];
    [[Messangi sharedInstance] initMessangi];
    [[Messangi sharedInstance] registerDialog];
    
    return YES;
}

Android

Support for Android 6 (API Level 23)

Starting in Android 6, Android introduces a new permissions model where users can now directly manage app permissions at runtime. Users can grant or revoke permissions individually for installed apps.

To handle these permissions within your app you need override the function onRequestPermissionsResult on the app's MainActivity:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    ...
}

The Messangi SDK adds a new function in the Messangi Instance to handle internal permissions needed by the SDK. This function needs to be called inside the previous overridden function.

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    try {
        Messangi.getInstance().onRequestPermissionsResult(requestCode,permissions,grantResults);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

This is required to successfully support Android 6 and later.

Configuring the Messangi SDK programmatically

The traditional way to configure the Messangi SDK by adding the custom credentials to the onCreate function in the app's MainActivity is still supported:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    // Messangi Credentials
    Messangi.getInstance().setAppName("...");
    Messangi.getInstance().setApiClientPrivateKey("...");
    Messangi.getInstance().setClientId("...");

    // GCM Credentials
    Messangi.getInstance().setGcmApiKey("...");
    Messangi.getInstance().setGcmProjectId("...");

    // Subscription manager
    Messangi.getInstance().setSubscriptionURL("...");
    Messangi.getInstance().setSubscriptionInstanceId("...");


    Messangi.getInstance().init(this);
    Messangi.getInstance().addMessangiListener(this);
    Messangi.getInstance().registerDialog(this, this);
}

Configuring the Messangi SDK via config files

Now you can create a configuration file to include the SDK settings, allowing for an easy transition from Development to Production during the development proces:

1. Create the Config Files
  • In androidStudio right click on some folder inside the main “res” folder
  • Select New > XML Resource file
  • Enter the name for the XML file in the New File window
  • Add the properties:

= Required =

name:   messangi_app_name
type:   string
Description: The appName provided by Ogangi

name:   client_id
type:   string
Description: The cliendID provided by Ogangi

name:   api_client_private_key
type:   string
Description: The privateKey provided by Ogangi

name:   gcm_api_key
type:   string
Description: This api key is provided by Google when you create the credentials for push notifications

name:   gcm_project_id
type:   string
Description: This Project ID is provided by Google when you create the credentials for push notifications

= Optional for subscriptions =

name:   subscription_url
type:   string
Description: The subscription URL provided by Ogangi
Default value: null

name:   subscription_id
type:   string
Description: The workspace ID provided by Ogangi
Default value: null

= Optional for the Environment =

name:   max_stored_messages
type:   integer
Description: The max number of messages to be stored in device, 0 for not limit
Default value: 0

name:   analytics_allowed
type:   bool
Description: Send Analytics info to the BI platform
Default value: true

name:   location_allowed
type:   bool
Description: Use the device's location services (Geopush, Geofence, Beacon won't work)
Default value: true

name:   logging_allowed
type:   bool
Description: Show debug information of the SDK in the console
Default value: true 

Example:

<resources>
    <string name="messangi_app_name" translatable="false" templateMergeStrategy="preserve">
        Messangi
    </string>
    <string name="api_client_private_key" translatable="false" templateMergeStrategy="preserve">
        wzuuzVeVA4hR9Xc8kWQB
    </string>
    <string name="client_id" translatable="false" templateMergeStrategy="preserve">
        D79BFFVx2TjXcJrrnktB
    </string>
    <string name="gcm_api_key" translatable="false" templateMergeStrategy="preserve">
        AIzaSyDoThF8Mbagpnt4sDUy5ENf-GwfbU4zoEc
    </string>
    <string name="gcm_project_id" translatable="false" templateMergeStrategy="preserve">
        554154250704
    </string>
    <string name="subscription_url" translatable="false" templateMergeStrategy="preserve">
        {base_url}/rest/api
    </string>
    <string name="subscription_id" translatable="false" templateMergeStrategy="preserve">
        8
    </string>
    <bool name="analytics_allowed">true</bool>
    <bool name="location_allowed">true</bool>
    <bool name="logging_allowed">true</bool>
    <integer name="max_stored_messages">15</integer>
</resources>

The optional fields for subscriptions and environment can be stored in difference files if needed.

2. Add this code to the onCreate function in your MainActivity
    Messangi.getInstance().loadCredentials(this);
    Messangi.getInstance().loadSubscriptionCredentials(this);
    Messangi.getInstance().loadEnvironment(this);

Example:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    Messangi.getInstance().loadCredentials(this);
    Messangi.getInstance().loadSubscriptionCredentials(this);
    Messangi.getInstance().loadEnvironment(this);

    Messangi.getInstance().init(this);
    Messangi.getInstance().addMessangiListener(this);
    Messangi.getInstance().registerDialog(this, this);
}