7 Xamarin iOS Apps

If you use the Xamarin platform to develop iOS apps, you can use the SDK that Oracle Mobile Hub provides for Xamarin iOS apps. This SDK simplifies authentication with Mobile Hub and provides native wrapper classes for Mobile Hub platform APIs.

Get the SDK

To get the client SDK for Xamarin iOS, go to the Oracle Digital Assistant and Oracle Mobile Cloud Downloads page on OTN.

Create a Backend

You create a backend to serve as a secure gateway between your app and Mobile Hub features, such as platform and custom APIs. For your app to access these resources, it authenticates with a backend.
  1. Click icon to open the side menu to open the side menu and select Development > Backends.
  2. Click New Backend.
  3. Once you complete the dialog and the backend is created, keep the Settings page open.
    You’ll need to configure your app with some of this information.

Add the SDK

  1. If you haven’t already done so, extract the contents from the SDK zip.

  2. In Visual Studio, create a Visual C# iOS app.

  3. Add the SDK's DLL file to your app by right-clicking the project's References node and selecting Edit References, clicking the .NET Assembly tab, and then browsing to the IOS.dll file in the extracted SDK zip.

  4. Add the configuration file to the app by right-clicking the project's root node and selecting Add > Add Files and then navigating to the SDK's OMC.plist file.

  5. Select the node for OMC.plist so that it's properties are displayed in the Properties pane. Then make sure that the Build Action property is set to BundleResource.

  6. Add the SynchStore.momd folder to the app by right-clicking the project's root node and selecting Add > Add Existing Folder and then navigating to the SDK's SynchStore folder.

  7. For all of the files in the SynchStore.momd folder, make sure that the Build Action property is set to BundleResource.

The next step will be to fill in the OMC.plist file.

Configure SDK Properties

To use the client SDK in an iOS app, you need to add the OMC.plist configuration file to the app and fill it in with environment details for your backend in Oracle Mobile Hub, as well as other configuration information. In turn, the SDK classes use this information to help manage authorization, logging, event tracking, data synchronization, and other features.

You package the configuration file in the root of your app’s main bundle.

The file is essentially divided into the following parts:

  • The mobileBackend key and its contents.

    You include this part if you are using a backend with the app. The SDK classes use the environment and authentication details you specify there to access the backend and construct HTTP headers for REST calls made to APIs.

  • Keys that apply to the configuration as a whole, such as logLevel and oAuthTokenEndpoint. These keys generally, but don’t have to, appear at the top of the file.

Here’s the same file in text form:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"
<plist version="1.0">
<dict>
  <key>logLevel</key>
  <string>debug</string>
  <key>logHTTP</key>
  <true/>
  <key>oAuthTokenEndPoint</key>
  <string>https://MY_TOKEN_ENDPOINT</string>
  <key>mobileBackend</key>
  <dict>
    <key>name</key>
    <string>EasyShoppingMBE</string>
    <key>baseURL</key>
    <string>https://MY_CLOUD_DOMAIN.oracle.com</string>
    <key>authentication</key>
    <dict>
      <key>type</key>
      <string>oauth</string>
      <key>oauth</key>
      <dict>
        <key>clientID</key>
        <string>11dac238ffaa4b029e78e982114642ab</string>
        <key>clientSecret</key>
        <string>5624cbdd-a7c5-4c10-a758-6019a5ab8da8</string>
        <key>enableOffline</key>
        <true/>
      </dict>
    </dict>
  </dict>
</dict>
</plist>

And here is a description of some of the more important entries in the OMC.plist file.

  • oAuthTokenEndPoint — The URL of the OAuth server from where your application gets its authentication token. This key needs to be provided for all apps that rely on OAuth to authenticate. You get this from the backend’s Settings page. The endpoint should be only the base URL (in the form https://host.domain:port).

  • logLevel — Determines how much SDK logging is displayed in the app’s console. The default value is error. Other possible values (in increasing level of detail) are warning, info, and debug. It is also possible to set the value to none.

  • logHTTP — When set to true, the SDK logs the headers and bodies of all HTTP requests and responses.

  • mobileBackend — A dictionary entry containing authentication details for your backend and other optional details, such as synchronization properties.

    You get the authentication details, such as the OAuth and HTTP credentials, from the backend’s Settings page.

  • mobileBackend/baseUrl — The base URL for all APIs that you call through the backend. You get this from the backend’s Settings page.

  • mobileBackend/authentication — Contains a dictionary with the following elements:

    • The type sub-key, with possible (string) values of oauth, basic, facebook, and tokenExchange.

    • One or more sub-keys for authentication types, containing a dictionary with the authentication credentials.

      Within sub-keys for basic and oauth, you can also add the enableOffline key. By default, this property is set to true.

Authentication Properties

The contents and sub-elements of the mobileBackend/authentication key depend on what kind of authentication the app will be using.

OAuth
  • Set the value of the type key to oauth.

  • Create an oauth sub-key and fill in the clientID and clientSecret  credentials provided by the backend.

  • At the top level of the file, supply the oAuthTokenEndPoint value that is supplied but without the oauth2/v1/token that is appended on the backend’s Settings page.

  • Optionally, if you want to disable offline authentication, add the enableOffline sub-key and set it to false.

The resulting authorization property might look something like this:

<key>authentication</key>
<dict>
  <key>type</key>
  <string>oauth</string>
  <key>oauth</key>
  <dict>
    <key>clientID</key>
    <string>11dac238ffaa4b029e78e982114642ab</string>
    <key>clientSecret</key>
    <string>5624cbdd-a7c5-4c10-a758-6019a5ab8da8</string>
  </dict>
  <key>basic</key>
</dict>
HTTP Basic
  • Set the value of the type key to basic.

  • Create a basic sub-key and fill in the HTTP Basic credentials (mobileBackendID and anonymousKey) provided by the backend.

  • Optionally, if you want to disable offline authentication, add the enableOffline sub-key and set it to false.

The resulting authentication entry might look something like this:

<key>authentication</key>
<dict>
  <key>type</key>
  <string>basic</string>
  <key>basic</key>
  <dict>
    <key>mobileBackendID</key>
    <string>a8c6a34f-61bb-4bee-948c-d43dd2c077d7</string>
    <key>anonymousKey</key>
    <string>dXNlcmlkOnBhc3N3b3Jk</string>
  </dict>
</dict>
Token Exchange

If you are authenticating using a third-party token, do the following:

  • Set the value of the type key to tokenExchange.

  • Create a tokenExchange sub-key and fill in the OAuth Consumer credentials provided by the backend.

The resulting authentication section might look something like this:

<key>authentication</key>
<dict>
  <key>type</key>
  <string>tokenExchange</string>
  <key>tokenExchange</key>
  <dict>
    <key>oauth</key>
    <dict>
      <key>clientID</key>
      <string>b39ba08d30d54e24970332fcdffec3a7</string>
      <key>clientSecret</key>
      <string>23953fe8-76ed-4c89-a5cb-6042db10cfaf</string>
    </dict>
    <key>basic</key>
    <dict>
      <key>mobileBackendID</key>
      <string>8d3744b8-cab2-479c-998b-ebba2c31560f</string>
      <key>anonymousKey</key>
      <string>ZFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTll</string>
    </dict>
  </dict>
</dict>

Call Mobile APIs

Once you have added the SDK to your app and configured your OMC.plist file, here are the general steps for calling APIs from your iOS app:

  1. Add an SDK call to your app to load the configuration info.

  2. Add an SDK call to your app to handle authentication.

  3. Add any other SDK calls that you want to use.

Load the Backend's Configuration

For any calls to Mobile Hub APIs using the iOS SDK to successfully complete, you need to have the mobile backend’s configuration loaded from the app’s OMC.plist file. You do this using the OMCMobileBackend class:

OMCMobileBackend oMCMobileBackend = OMCMobileBackendManager.SharedManager.MobileBackendForName("MBE_FullCoverage");

Authenticate and Log In

Here is some sample code that you can use for authentication through Mobile Hub in your iOS apps.

OAuth

You can use the following method to handle a user logging in with a user name and password.

OMCAuthorization authorization = oMCMobileBackend.Authorization;
authorization.AuthenticationType = OMCAuthenticationType.OAuth;
authorization.Authenticate(username.Text, password.Text);

This method terminates the connection to Mobile Hub and clears the user name and password from the iOS keychain:

authorization.Logout(HandleOMCAuthorizationLogoutCompletionBlock);

void HandleOMCAuthorizationLogoutCompletionBlock(NSError nsError)
{
    if(nsError == null){
        Console.WriteLine("Logout success!");
    }
}
HTTP Basic

You can use the following method to handle a user logging in with a user name and password.

OMCAuthorization authorization = oMCMobileBackend.Authorization;
authorization.AuthenticationType = OMCAuthenticationType.HTTPBasic;
authorization.Authenticate(username.Text, password.Text);

This method terminates the connection to Mobile Hub and clears the user name and password from the iOS keychain:

authorization.Logout(HandleOMCAuthorizationLogoutCompletionBlock);

void HandleOMCAuthorizationLogoutCompletionBlock(NSError nsError)
{
    if(nsError == null){
        Console.WriteLine("Logout success!");
    }
}
SSO with a Third-Party Token

First, your app needs to get a token from the third-party token issuer. The way you can obtain the token varies by issuer.

Once you have the token, use it to authenticate. The example below checks to see if the token is already stored in Mobile Hub before logging in again.

Note:

The default expiration time for storing a third-party token in Mobile Hub is 6 hours. You can adjust this time by changing the Security_TokenExchangeTimeoutSecs policy.
OMCAuthorization oMCAuthorization = oMCMobileBackend.Authorization;
oMCAuthorization.AuthenticationType = OMCAuthenticationType.SSOTokenExchange;
NSError nSError =  oMCAuthorization.AuthenticateSSOTokenExchange(Token);

oMCAuthorization.AuthenticateSSOTokenExchange(Token, HandleOMCAuthorizationAuthCompletionBlock);

oMCAuthorization.AuthenticateSSOTokenExchange(Token, true, HandleOMCAuthorizationAuthCompletionBlock);

oMCAuthorization.AuthenticateSSOTokenExchange(Token, true);


bool iSLoaded = oMCAuthorization.LoadSSOTokenExchange;

oMCAuthorization.ClearSSOTokenExchange();
Facebook

For apps that allow login through Facebook, use:

oMCAuthorization.AuthenticationType = OMCAuthenticationType.Facebook;
oMCAuthorization.AuthenticateSocial(HandleOMCAuthorizationAuthCompletionBlock);	

If you haven’t already set up the app and its mobile backend to use Facebook as the identity provider, see Facebook Login in Mobile Hub.

Call Platform APIs

Once the mobile backend’s configuration info is loaded into the app and you have made a call to get the mobile backend, you can make calls to SDK classes to access platform features.

Here are some code snippets that illustrate how to access these APIs with the SDK.

User Management

Getting a User

OMCAuthorization oMCAuthorization = oMCMobileBackend.Authorization;
oMCAuthorization.GetCurrentUser(HandleOMCUserRegistrationCompletionBlockWithUser);
void HandleOMCUserRegistrationCompletionBlockWithUser(NSError nSError, OMCUser oMCUser)
{
    if(nSError == null){        
        output.Text = user.FirstName + " User details have been fetched successfully";
    }
}

Updating a User

user.SetValueForKey(new NSNumber(26),new NSString("age"));
user.SetValueForKey(new NSString("address"), new NSString("india"));
oMCAuthorization.UpdateCurrentUser(user,HandleOMCUserRegistrationCompletionBlock);

void HandleOMCUserRegistrationCompletionBlock(NSError nSError)
{
    if (nSError == null)
    {
        //user = oMCUser;
        if (user != null)
        {
            if (username.Text == null)
            {
                username.Text = "Welcome " + user.FirstName;
            }
            else output.Text = user.FirstName + " User details have been fetched successfully";
        }
    }
    else
    {
        output.Text = nSError.ToString();
    }
}

Location

Initialization

OMCLocation oMCLocation = oMCMobileBackend.Location;

Queries for Places, Devices, and Assets

private static OMCLocation oMCLocation;
private static OMCLocationPlace oMCLocationPlace;
private static OMCLocationDevice oMCLocationDevice;
private static OMCLocationAsset oMCLocationAsset;

oMCLocation = oMCMobileBackend.Location;  
OMCLocationPlaceQuery oMCLocationPlaceQuery = oMCLocation.BuildPlaceQuery;
oMCLocationPlaceQuery.Name = "West";
oMCLocationPlaceQuery.ExecuteWithCompletionHandler(completionHandler);
OMCLocationAssetQuery oMCLocationAssetQuery = oMCLocation.BuildAssetQuery;
oMCLocationAssetQuery.Name = "joe";
oMCLocationAssetQuery.ExecuteWithCompletionHandler(completionHandler);

OMCLocationDeviceQuery oMCLocationDeviceQuery = oMCLocation.BuildDeviceQuery;
oMCLocationDeviceQuery.Name = "Beacon";
oMCLocationDeviceQuery.ExecuteWithCompletionHandler(completionHandler);	

Fetching

Action<OMCLocationObjectQueryResult, NSError> completionHandler = new Action<OMCLocationObjectQueryResult, NSError>((OMCLocationObjectQueryResult arg1, NSError arg2) =>
{
	if (arg2 == null)
	{
        OMCLocationObject[] LocationObjects = arg1.Items;
        OMCLocationPlace oMCLocationPlace;
        OMCLocationDevice oMCLocationDevice;
        OMCLocationAsset oMCLocationAsset;

        foreach (OMCLocationObject locationObject in LocationObjects)
		{
            Console.WriteLine("Location Object " + locationObject.GetType() + "--> " + i + " is: " + locationObject.ToString());

            if(locationObject.GetType().Equals(typeof(OMCLocationPlace))){

                oMCLocationPlace = (OMCLocationPlace)locationObject;

                oMCLocation.PlaceWithID(oMCLocationPlace.Id_, placeCompletionHandler);
            }
            else if (locationObject.GetType().Equals(typeof(OMCLocationDevice)))
            {

                oMCLocationDevice = (OMCLocationDevice)locationObject;

                oMCLocation.DeviceWithID(oMCLocationDevice.Id_, deviceCompletionHandler);
            }
            else if (locationObject.GetType().Equals(typeof(OMCLocationAsset)))
            {

                oMCLocationAsset = (OMCLocationAsset)locationObject;

                oMCLocation.AssetWithID(oMCLocationAsset.Id_, assetCompletionHandler);
            }
		}
	}
});

private static void assetCompletionHandler(OMCLocationAsset arg0, NSError arg1)
{
    if (arg1 == null)
    {
        Console.WriteLine("Location Asset " + arg0.ToString());
    }
}

private static void deviceCompletionHandler(OMCLocationDevice arg0, NSError arg1)
{
    if (arg1 == null)
    {
        Console.WriteLine("Location Device " + arg0.ToString() );

    }
}

private static void placeCompletionHandler(OMCLocationPlace arg0, NSError arg1)
{
    if(arg1 == null){
        Console.WriteLine("Location Place " + arg0.ToString());
    }
}

Refreshing

Action<OMCLocationObjectQueryResult, NSError> completionHandler = new Action<OMCLocationObjectQueryResult, NSError>((OMCLocationObjectQueryResult arg1, NSError arg2) =>
{
	if (arg2 == null)
	{
        OMCLocationObject[] LocationObjects = arg1.Items;


        foreach (OMCLocationObject locationObject in LocationObjects)
		{
            Console.WriteLine("Location Object " + locationObject.GetType() + "--> " + i + " is: " + locationObject.ToString());

            if(locationObject.GetType().Equals(typeof(OMCLocationPlace))){

                oMCLocationPlace = (OMCLocationPlace)locationObject;

                oMCLocationPlace.RefreshWithCompletionHandler(placeCompletionHandler);
            }
            else if (locationObject.GetType().Equals(typeof(OMCLocationDevice)))
            {

                oMCLocationDevice = (OMCLocationDevice)locationObject;

                oMCLocationDevice.RefreshWithCompletionHandler(deviceCompletionHandler);
            }
            else if (locationObject.GetType().Equals(typeof(OMCLocationAsset)))
            {

                oMCLocationAsset = (OMCLocationAsset)locationObject;

                oMCLocationAsset.RefreshWithCompletionHandler(assetCompletionHandler);

            }
		}
	}
});

private static void placeCompletionHandler(NSError arg0)
{
    if (arg0 == null)
    {
        Console.WriteLine("Location Place " + oMCLocationPlace.ToString());
    }
}

private static void deviceCompletionHandler(NSError arg0)
{
    if (arg0 == null)
    {
        Console.WriteLine("Location Device " + oMCLocationDevice.ToString());

    }
}

private static void assetCompletionHandler(NSError arg0)
{
    if (arg0 == null)
    {
        Console.WriteLine("Location Asset " + oMCLocationAsset.ToString());
    }
}
Storage

Initialization

OMCStorage oMCStorage = oMCMobileBackend.Storage;

Getting a Collection

OMCStorageCollection oMCStorageCollection = oMCStorage.GetCollection("SharedCollection");

Getting an Object

oMCStorageObject =  collection.Get("Object Id");

System.Console.WriteLine("Storage Object1:  " + oMCStorageObject.ToString());

Getting All Objects from a Collection

NSMutableArray nSMutableArray = collection.Get(0, 100, true);
OMCStorageObject oMCStorageObject;
if (nSMutableArray != null && nSMutableArray.Count > 0)
{
    for (uint i = 0; i < nSMutableArray.Count; i++){
        oMCStorageObject = nSMutableArray.GetItem<OMCStorageObject>(i);
        System.Console.WriteLine("Storage Object1:  " + oMCStorageObject.ToString());
    }
}

Uploading a Text File

NSData text = "This is a sample Text file";
OMCStorageObject txtFile = new OMCStorageObject("Mytext.txt", text, "text/plain");

collection.Put(txtFile);

Uploading an Image File

UIImage image = new UIImage("MyImage.png");
NSData data = image.AsPNG();
OMCStorageObject imageFile = new OMCStorageObject("MyImage", data, "image/png");
collection.Put(imageFile);
Notifications

Initialization

OMCNotifications oMCNotifications = oMCMobileBackend.Notifications;

Registering for Notifications

oMCNotifications.RegisterForNotifications(appDelegate.DeviceToken, HandleOMC_Notifications_SuccessBlock, HandleOMC_Notifications_ErrorBlock);


void HandleOMC_Notifications_SuccessBlock(NSHttpUrlResponse nSHttpUrlResponse)
{
    if (nSHttpUrlResponse != null)
    {
        Console.WriteLine("Response from notification Server:  " + nSHttpUrlResponse.StatusCode);

    }
}

void HandleOMC_Notifications_ErrorBlock(NSError nSError)
{
    if (nSError != null)
    {
        Console.WriteLine("Error in fetching mobiel file:  " + nSError.LocalizedDescription);
    }
}

AppDelegate code

public NSData DeviceToken = string.Empty;
 
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    DeviceToken = deviceToken; // Do something to storage deviceToken.

    Console.WriteLine("Device Token:  " + DeviceToken.ToString());
}

public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
    Console.WriteLine("FailedToRegisterForRemoteNotifications.. :(");
}

public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
    ProcessNotification(userInfo, false);

}

void ProcessNotification(NSDictionary options, bool fromFinishedLaunching)
{
    // Check to see if the dictionary has the aps key.  This is the notification payload you would have sent
    if (null != options && options.ContainsKey(new NSString("aps")))
    {
        //Get the aps dictionary
        NSDictionary aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
        string alertTitle = string.Empty;
        string alert = string.Empty;
        string sound = string.Empty;
        int badge = -1;

        //Extract the alert text
        // NOTE: If you're using the simple alert by just specifying
        // "  aps:{alert:"alert msg here"}  ", this will work fine.
        // But if you're using a complex alert with Localization keys, etc.,
        // your "alert" object from the aps dictionary will be another NSDictionary.
        // Basically the JSON gets dumped right into a NSDictionary,
        // so keep that in mind.
        if (aps.ContainsKey(new NSString("alert")))
            alert = (aps[new NSString("alert")] as NSString).ToString();
        if (aps.ContainsKey(new NSString("alert")))
              alert = (aps[new NSString("alert")] as NSString).ToString();

          if (options.ContainsKey(new NSString("alertTitle")))
              alertTitle = (options[new NSString("alertTitle")] as NSString).ToString();

          //Extract the sound string
          if (aps.ContainsKey(new NSString("sound")))
              sound = (aps[new NSString("sound")] as NSString).ToString();

          //Extract the badge
          if (aps.ContainsKey(new NSString("badge")))
          {
              string badgeStr = (aps[new NSString("badge")] as NSObject).ToString();
              int.TryParse(badgeStr, out badge);
          }

        if (!fromFinishedLaunching)
        {
            //Manually show an alert
            if (!string.IsNullOrEmpty(alert))
            {
                UIAlertView avAlert = new UIAlertView("Notification", alert, null, "OK", null);
                avAlert.Show();
            }
        }
    }
}

public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
    ProcessNotification(userInfo, false);
}

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{

    Window = new UIWindow(UIScreen.MainScreen.Bounds);

    ViewController viewController = new ViewController("LoginScreen", null);
    Window.RootViewController = viewController;
    Window.MakeKeyAndVisible();

    if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
    {
        var notificationSettings = UIUserNotificationSettings.GetSettingsForTypes(
                                       UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound, null
                                   );

        UIApplication.SharedApplication.RegisterUserNotificationSettings(notificationSettings);
        UIApplication.SharedApplication.RegisterForRemoteNotifications();
    }
    else
    {
        //==== register for remote notifications and get the device token
        // set what kind of notification types we want
        UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge;
        // register for remote notifications
        UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
    }

    return true;

}
Analytics

Initialization

OMCAnalytics oMCAnalytics = oMCMobileBackend.Analytics;

Logging an Event

oMCAnalytics.LogEvent("this is test event "+ i +" from xamarin");

Setting Context Location

oMCAnalytics.SetContextLocationCountry("india", "Telangana", "Hyderabad", "500081");

Flushing an Event

oMCAnalytics.Flush();
App Policies

Loading the App Config and Getting Policies

oMCMobileBackend.AppConfigWithCompletionHandler(HandleOMCAppConfigCompletionBlock);

lock(obj){
 Monitor.Wait(obj);
}

OMCAppConfig oMCAppConfig = oMCMobileBackend.AppConfig;


//Getting String

String str = oMCAppConfig.StringForProperty("Test_String", "No value configured");

Console.WriteLine("oMCAppConfig: String:  " + str);


//Getting Number
NSNumber number = oMCAppConfig.NumberForProperty("Test_number", -1);

Console.WriteLine("oMCAppConfig: Number:  " + number);


//Getting Boolean
Boolean boolean = oMCAppConfig.BooleanForProperty("Test_Boolean", false);

Console.WriteLine("oMCAppConfig: Boolean:  " + boolean.ToString());



void HandleOMCAppConfigCompletionBlock(OMCAppConfig oMCAppConfig, NSError arg1)
{
  if(arg1 == null){
      Console.WriteLine("oMCAppConfig: " + oMCAppConfig.ToString());
  }
}

Call Custom APIs

The SDK provides the CustomCodeClient class to simplify the calling of custom APIs in Mobile Hub. You can call a REST method (GET, PUT, POST, or DELETE) on an endpoint where the request payload is JSON or empty and the response payload is JSON or empty.

Using this class, you invoke a REST method (GET, PUT, POST, or DELETE) on an endpoint where the request payload is JSON or empty and the response payload is JSON or empty.

In addition you can provide a completion handler to be called when the method invocation is complete (meaning that the handler runs asynchronously).

Use of CustomCodeClient might look something like this:

oMCMobileBackend.CustomCodeClient.InvokeCustomRequest("mcs_examples_sync_salesplus/reminders", "get", null, HandleOMCCustomRequestCompletionHandler);

void HandleOMCCustomRequestCompletionHandler(NSError arg0, NSHttpUrlResponse arg1, NSObject nSObject)
{
	if (nSObject != null)
	{
		System.Console.WriteLine("response object:  " + nSObject.ToString());
	}
}