10 Xamarin Android Applications

If you use the Xamarin platform to develop Android apps, you can use the SDK that Oracle Mobile Cloud Service (MCS) provides for Xamarin Android apps. This SDK simplifies authentication with MCS and provides native wrapper classes for MCS platform APIs.

Getting the SDK for Xamarin Android

To get the MCS client SDK for Xamarin Android, go to the Oracle Technology Network’s MCS download page.

To use this SDK, you should have the following software on your system:

Adding the SDK to a Xamarin Android Project

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

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

  3. Make sure you can connect to the internet from Visual Studio connection so that NuGet packages are reachable.

  4. Add GCM and Facebook dependencies to your project:

    • If a Packages node appears in the Solution Explorer for your project, do the following:

      1. Right-click the Packages node.

      2. Type GCM in the search field, select Xamarin.GooglePlayServices.Gcm (not Crosslight.Xamarin.GooglePlayServices.GCM), and click Add Package. The remaining GCM dependencies will be added automatically.

      3. Accept the terms to add the packages successfully.

      4. Add Xamarin.Facebook.Android by searching for it in the NuGet packages and adding it in the same way you added the GCM packages.

    • If a Packages node doesn't appear in the Solution Explorer for your project, do the following:

      1. Select Tools > NuGet Package Manager > Manage NuGet Packages for Solution.

      2. Select the Browse tab.

      3. Type GCM in the search field, select Xamarin.GooglePlayServices.Gcm (not Crosslight.Xamarin.GooglePlayServices.GCM), select the checkbox for your app, and click Install. The remaining GCM dependencies will be added automatically.

      4. After previewing the changes, click OK.

      5. Add Xamarin.Facebook.Android by searching for it in the NuGet packages and adding it in the same way you added the GCM packages.

  5. At the end make sure you have all the below dependencies. If any of them are missing, search for them in the NuGet package manager.

    <packages>
      <package id="Bolts" version="1.4.0.1" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Annotations" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Compat" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Core.UI" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Core.Utils" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.CustomTabs" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Design" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Fragment" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Media.Compat" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Transition" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.v4" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.v7.AppCompat" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.v7.CardView" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.v7.RecyclerView" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Android.Support.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid71" />
      <package id="Xamarin.Build.Download" version="0.4.7" targetFramework="monoandroid80" />
      <package id="Xamarin.Facebook.Android" version="4.26.0" targetFramework="monoandroid80" />
      <package id="Xamarin.Google.ZXing.Core" version="3.3.0" targetFramework="monoandroid80" />
      <package id="Xamarin.GooglePlayServices.Base" version="42.1021.1" targetFramework="monoandroid71" />
      <package id="Xamarin.GooglePlayServices.Basement" version="42.1021.1" targetFramework="monoandroid71" />
      <package id="Xamarin.GooglePlayServices.Gcm" version="42.1021.1" targetFramework="monoandroid71" />
      <package id="Xamarin.GooglePlayServices.Iid" version="42.1021.1" targetFramework="monoandroid71" />
      <package id="Xamarin.GooglePlayServices.Tasks" version="42.1021.1" targetFramework="monoandroid71" />
    </packages>
  6. Add the SDK's DLL file to your app by right-clicking the project's References node and selecting Edit References or Add Reference (depending on which menu item is available).

    • If you select Edit References, click the .NET Assembly tab, and then browse to the Android.dll file in the extracted SDK zip.

    • If you select Add Reference, click the Browse tab, click the Browse button, and then navigate to the Android.dll file in the extracted SDK zip.

  7. Add the configuration file to the app by right-clicking the project's Assets node and selecting either Add > Add Files or Add > Existing File (depending which is available) and then navigating to the SDK's oracle_mobile_cloud_config.xml file.

  8. Select the node for oracle_mobile_cloud_config.xml so that it's properties are displayed in the Properties pane. Then make sure that the Build Action property is set to AndroidAsset.

  9. Open oracle_mobile_cloud_config.xml and fill in the environment details for the mobile backend that the app will be using. See Configuring SDK Properties for Xamarin Android.

  10. Update the AndroidManifest.xml file with the necessary properties as detailed in Configuring Your AndroidManifest.xml File.

Configuring SDK Properties for Xamarin Android

To use the SDK in an Android app, you need to add the oracle_mobile_cloud_config.xml configuration file to the app and fill it in with environment details for your mobile backend. In turn, the SDK classes use the information provided in this file to access the mobile backend and construct HTTP headers for REST calls made to APIs.

The following code sample shows the structure of a oracle_mobile_cloud_config.xml file:
<mobileBackends>
  <mobileBackend>
    <mbeName>MBE_NAME</mbeName>
    <mbeVersion>MBE_VERSION</mbeVersion>
    <default>true</default>
    <appKey>APPLICATION_KEY</appKey>
    <baseUrl>BASE_URL</baseUrl>
    <enableAnalytics>true</enableAnalytics>
    <enableLogger>true</enableLogger>
    <authorization>
      <offlineAuthenticationEnabled>true</offlineAuthenticationEnabled>
      <authenticationType>AUTH_TYPE</authenticationType>
      <oauth>
        <oAuthTokenEndPoint>OAUTH_URL</oAuthTokenEndPoint>
        <oAuthClientId>CLIENT_ID</oAuthClientId>
        <oAuthClientSecret>CLIENT_SECRET</oAuthClientSecret>
      </oauth>
      <basic>
        <mobileBackendID>MOBILE_BACKEND_ID</mobileBackendID>
        <anonymousKey>ANONYMOUS_KEY</anonymousKey>
      </basic>
    </authorization>
    <!-- additional properties go here -->
  </mobileBackend>
</mobileBackends>
Here’s a list of the file’s elements. The values that you need to fill in for a given mobile backend can be found on the Settings and Clients pages for that mobile backend.
  • mobileBackends — The config file’s root element, containing one or more mobileBackend elements.

  • mobileBackend — The element for a mobile backend.

  • mbeName — The name of the mobile backend associated with your app.

  • mbeVersion — The version number of your app (for example, 1.0).

  • default — If true, that mobile backend is treated as the default and thus can be easily referenced using the getDefaultMobileBackend(Context context) method in the SDK’s MobileBackendManager class.

  • appKey — The application key, which is a unique string assigned to your app when you register it as a client in MCS. See Registering an App as a Client in MCS.

  • baseUrl — The URL your app uses to connect to its mobile backend.

  • enableLogger — When set to true, logging is included in your app.

  • enableAnalytics — When set to true, analytics on the app’s use can be collected.

  • authorization — Use the sub-elements of this element to define the authentication the app will be using and specify the required credentials.

    • offlineAuthenticationEnabled — If set to true, offline login will be allowed. For this to work, you also need to add the following to the app’s AndroidManifest.xml file:
      <receiver android:name="oracle.cloud.mobile.network.NetworkHelper"
        <intent-filter>
          <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
      </receiver>
    • authenticationType — Define the kind of authentication mechanism being used to connect your app to MCS. Possible values are oauth (for OAuth Consumer) , basic (for HTTP Basic), sso, tokenAuth (for SSO token exchange), and facebook (for logging in with Facebook credentials). If this element isn’t specified, OAuth Consumer is used. The other contents and sub-elements of the authorization element depend on the type of authentication.

OAuth Consumer

For OAuth, set the value of the <authenticationType> element to oauth and fill in the OAuth credentials provided by the mobile backend.
  • oAuthTokenEndPoint — The URL of the OAuth server your app goes to, to get its authentication token.

  • oAuthClient — The unique client identifier assigned to all apps when they’re first created in your mobile backend.

  • oAuthClientSecret — The unique secret string assigned to all apps they’re first created in your mobile backend.

The resulting authorization element might look something like this:

<authorization>
  <offlineAuthenticationEnabled>true</offlineAuthenticationEnabled>
  <authenticationType>oauth</authenticationType>
  <oauth>
    <oAuthTokenEndPoint>http://oam-server.oracle.com/oam/oauth2/tokens</oAuthTokenEndPoint>
    <oAuthClient>f2d3ca5c-7e6f-4d1c-aabc-a2f3caf7ec4e</oAuthClient>
    <oAuthClientSecret>vZMRkgniIbhNUiPnSRT2</oAuthClientSecret>
  </oauth>
</authorization>

Enterprise SSO

For SSO, set the value of the <authenticationType> element to sso, fill in the OAuth credentials provided by the mobile backend, and add the ssoTokenEndpoint.

The resulting authorization element might look something like this:

<authorization>
  <offlineAuthenticationEnabled>true</offlineAuthenticationEnabled>
  <authenticationType>sso</authenticationType>
  <oauth>
    <oAuthTokenEndPoint>host/mobile/platform/sso/token</oAuthTokenEndPoint>
    <oAuthClient>f2d3ca5c-7e6f-4d1c-aabc-a2f3caf7ec4e</oAuthClient>
    <oAuthClientSecret>vZMRkgniIbhNUiPnSRT2</oAuthClientSecret>
    <ssoTokenEndpoint>https://development-mcspmtrial90.mobileenv.oracle.com:443/mobile/platform/sso/token</ssoTokenEndpoint>
</oauth>
</authorization>

SSO with a Third Party Token

For SSO with a third-party token, set the value of the <authenticationType> element to tokenAuth and fill in the HTTP Basic auth credentials provided by the mobile backend (described next).

The resulting authorization element might look something like this:

<authorization>
  <offlineAuthenticationEnabled>true</offlineAuthenticationEnabled>
  <authenticationType>tokenAuth</authenticationType>
  <basic>
    <mobileBackendID>6d3744b8-cab2-479c-998b-ebba2c31560f</mobileBackendID>
    <anonymousKey>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTll</anonymousKey>
  </basic>
</authorization>

HTTP Basic

For HTTP Basic authentication, you need to set the value of the <authenticationType> element to basic and fill in the HTTP Basic auth credentials provided by the mobile backend.
  • mobileBackendID — The unique identifier assigned to a specific mobile backend. It gets passed in an HTTP header of every REST call made from your app to MCS, to connect it to the correct mobile backend. When calling platform APIs, the SDK handles the construction of the authentication headers for you.

  • anonymousKey — A unique string that allows your app to access APIs that don’t require login. In this scenario, the anonymous key is passed to MCS instead of an encoded user name and password combination.

The resulting authorization element might look something like this:

<authorization>
  <offlineAuthenticationEnabled>true</offlineAuthenticationEnabled>
  <authenticationType>basic</authenticationType>
  <basic>
    <mobileBackendID>6d3744b8-cab2-479c-998b-ebba2c31560f</mobileBackendID>
    <anonymousKey>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTll</anonymousKey>
  </basic>
</authorization>

Facebook

For Facebook login, you need to set the value of the <authenticationType> element to facebook, fill in the HTTP Basic auth credentials provided by the mobile backend, and add the facebook element, where you specify the Facebook credentials.
  • facebookAppId — The Facebook application ID.

  • scopes — You can use this element to specify Facebook permissions (optional).

The resulting authorization element might look something like this:

<authorization>
  <offlineAuthenticationEnabled>true</offlineAuthenticationEnabled>
  <authenticationType>facebook</authenticationType>
  <basic>
    <mobileBackendID>6d3744b8-cab2-479c-998b-ebba2c31560f</mobileBackendID>
    <anonymousKey>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTll</anonymousKey>
  </basic>
  <facebook>
    <facebookAppId>123456789012345</facebookAppId>
    <scopes>public_profile,user_friends,email,user_location,user_birthday</scopes>
  </facebook>
</authorization>

Configuring Your AndroidManifest.xml File

Permissions for operations such as accessing the network and finding the network state are controlled through permission settings in AndroidManifest.xml. These permissions are required:

  • permission.INTERNET — Allows your app to access open network sockets.

  • permission.ACCESS_NETWORK_STATE — Allows your app to access information about networks.

Other permissions are optional. For example, the Analytics platform API uses location to provide detailed information about the usage and performance of your app. If you’re using the Analytics library from the SDK, you’ll want to add these permissions as well.

  • permission.ACCESS_COARSE_LOCATION— Allows your app to access approximate location information, derived from sources such as wi-fi and cell tower positions.

  • permission.ACCESS_FINE_LOCATION — Allows your app to access precise location information, derived from sources such as GPS.

For more information about permissions in your Android application, see Android Manifest Permissions in the Google documentation.

Add the permissions at the top of your AndroidManifest.xml file, as shown in the following example:


<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="oracle.cloud.mobile.photobox" >
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <application>
    <receiver android:name="oracle.cloud.mobile.network.NetworkHelper"
      <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
      </intent-filter>
    </receiver>
    (.....)
  </application>
</manifest>

If you are using the Notifications API in your app, you may also need to add a broadcast receiver element. See Setting Up a Mobile App for Notifications.

Loading a Mobile Backend's Configuration into a Xamarin Android App

For any calls to MCS APIs using the Xamarin Android SDK to successfully complete, you need to have the mobile backend’s configuration loaded from the app’s oracle_mobile_cloud_config.xml file. You do this using the MobileBackendManager class:

MobileBackendManager.Manager.GetMobileBackend(context,"GCMBackend");

Authenticating and Logging In Using the SDK for Xamarin Android

Here is some sample code that you can use for authentication through MCS in your Xamarin Android apps.

OAuth Consumer

First you initialize the authorization agent and set the authentication type to OAUTH.

MobileBackend mobileBackend;
IAuthorizationAgent mAuthorization;
mobileBackend = MobileBackendManager.Manager.GetDefaultMobileBackend(mCtx);
mAuthorization = mobileBackend.GetAuthorization(AuthType.Oauth);  

Then you use the authenticate method to attempt authentication. The call includes parameters for Android context, user name, password, and a callback that completes the authorization process.

TextView username, password;
username = (AutoCompleteTextView)FindViewById(Resource.Id.username);
password = (EditText)FindViewById(Resource.Id.password);
String userName = username.Text;
String passWord = password.Text;
mAuthorization.Authenticate(mCtx, userName, passWord, new AuthorizationCallback());

Here’s the definition for the callback.

Authorization CallBack
private class AuthorizationCallback : Java.Lang.Object, IAuthorizationCallback
{
    public void OnCompletion(ServiceProxyException exception)
    {
        if (exception != null)
        {
            Logger.Error(TAG, "Exception while receiving the Access Token", exception);
        }
        else
        {
            Logger.Error(TAG, "Authorization successful");
        }
    }
}

Enterprise SSO

mAuthorization.authenticateSSO(mCtx, false, new AuthorizationCallback());


private class AuthorizationCallback : Java.Lang.Object, IAuthorizationCallback
{
    public void OnCompletion(ServiceProxyException exception)
    {
        if (exception != null)
            Logger.Debug(TAG, "Exception " + exception.Message;
        else
        {
            Logger.Debug(TAG, "SSO Auth Succeeded");
        }
    }
}

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. For detailed information on obtaining third-party tokens and configuring identity providers in MCS, see Third-Party SAML and JWT Tokens.

Once you have the token, initialize the authorization agent and use the token in your authorization call. The example below checks to see if the token is already stored in MCS before logging in again.

Note:

The default expiration time for storing a third-party token in MCS is 6 hours. You can adjust this time by changing the Security_TokenExchangeTimeoutSecs policy.
IAuthorizationAgent mAuthorization;
MobileBackend mobileBackend;
mobileBackend = MobileBackendManager.Manager.GetDefaultMobileBackend(mCtx);
mAuthorization = mobileBackend.GetAuthorization(AuthType.Tokenauth);

// Check whether credential exists in secure store
Boolean isCredentialLoaded = mAuthorization.LoadSSOTokenExchange(mCtx);

if(isCredentialLoaded){
    // Credentials found in secure store - redirect to main activity
    Logger.Info(TAG, "Credentials got loaded successfully from secure store.");
    Intent intent = new Intent(mCtx, typeof(ContentActivity));
    StartActivity(intent);

} else {
    // Credentials not found - authenticate using token exchange 
    Logger.Info(TAG, "Credentials could not be found in secure store.");
    mAuthorization.AuthenticateUsingTokenExchange(mCtx, token, true, mLoginCallback);
}

Here’s the callback:

private class AuthorizationCallback : Java.Lang.Object, IAuthorizationCallback
{
    public void OnCompletion(ServiceProxyException exception)
    {
        if (exception == null)
        {
            //log event with Analytics
            mAnalyticsAgent.LogEvent("Login with 3rd party token successfully");
            mAnalyticsAgent.Flush();

            //redirect to another Activity after login
            Intent intent = new Intent(mCtx, typeof(ContentActivity));
            LoginActivity.activity.StartActivity(intent);

        } else {
            Logger.Error(TAG, "Exception during token exchange:", exception);
            LoginActivity.activity.Finish();
        }
    }
}

HTTP Basic Authentication

The code for handling login with HTTP Basic is nearly the same as the code for OAuth.

First you initialize the authorization agent and set the authentication type to BASIC_AUTH.

MobileBackend mobileBackend;
IAuthorizationAgent mAuthorization;
mobileBackend = MobileBackendManager.Manager.GetDefaultMobileBackend(mCtx);
mAuthorization = mobileBackend.GetAuthorization(AuthType.BasicAuth);

Then you use the Authenticate method to attempt authentication. The call includes parameters for Android context, user name, password, and a callback that completes the authorization process.

TextView username, password;
username = (AutoCompleteTextView)FindViewById(Resource.Id.username);
password = (EditText)FindViewById(Resource.Id.password);
String userName = username.Text;
String passWord = password.Text;
mAuthorization.Authenticate(mCtx, userName, passWord, new AuthorizationCallback());

Here’s the definition for the callback.

private class AuthorizationCallback : Java.Lang.Object, IAuthorizationCallback
{
    public void OnCompletion(ServiceProxyException exception)
    {
        Logger.Debug(TAG, "OnCompletion Auth Callback");
        if (exception != null)
        {
            Logger.Error(TAG, "Exception while receiving the Access Token", exception);
        }
        else
        {
            Logger.Error(TAG, "Authorization successful");
        }
    }
}

Facebook

First you initialize the authorization agent and set the authentication type to Facebook.

ISocialAuthorizationAgent mAuthorization;
SocialMobileBackend socialMobileBackend;
socialMobileBackend = SocialMobileBackendManager.Manager.GetDefaultMobileBackend(context);
mAuthorization = socialMobileBackend.GetSocialAuthorization(SocialAuthType.Facebook);
mAuthorization.SetAuthType(AuthType.Facebook);

Using a CallbackManager object from Facebook’s SDK, initiate authentication.

ICallbackManager callbackManager;
mAuthorization.Setup(context, new FacebookCallback());
callbackManager = mAuthorization.CallBackManager;
mAuthorization.AuthenticateSocial(activity);

Here’s code you can use for the callback that is passed above.

private class FacebookCallback : Java.Lang.Object, IFacebookCallback
{
	public void OnSuccess(Java.Lang.Object loginResult)
    {
        Logger.Error(TAG, "facebook login successful.");
    }

	public void OnCancel()
	{
	}

	public void OnError(FacebookException error)
	{
	}
}

Override the OnActivityResult() method to use the callback.

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
	Logger.Debug(TAG, "In OnActivity Result    onActivityResult");

	base.OnActivityResult(requestCode, resultCode, data);
	callBackManger.OnActivityResult(requestCode, (int)resultCode, data);
}

Calling Platform APIs Using the SDK for Xamarin Android

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 use SDK classes for various platform APIs.

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

User Management

Getting a User

IAuthorizationAgent authorizationAgent = authentication.Authorization;
authorizationAgent.FetchCurrentUser(new UserRegistrationCallback());
private class UserRegistrationCallback : Java.Lang.Object, IUserRegistrationCallback
{
	public void OnComplete(ServiceProxyException exception, User user)
	{
		if (exception == null)
		{
			mUser = user;
			setText("User " + mUser.Username + " details have been fetched successfully.");
		}
		else
		{
			//Handle Error
		}
	}
}

Updating a User

//creating map with properties
IDictionary<string, Object> map = new Dictionary<string,Object>();
map.Add("age", 26);
map.Add("address", "india"); 
authorizationAgent.UpdateUser(new UserRegistrationCallback(), map);

private class UserRegistrationCallback : Java.Lang.Object, IUserRegistrationCallback
{
	public void OnComplete(ServiceProxyException exception, User user)
	{

		if (exception == null)
		{
			setText("User " + user.Username + " details have been updated successfully.");
		}
		else
		{
			/Handle Error
		}
	}
}

Location

Initialization

Location location = (Location)mobileBackend.GetServiceProxy(Class.FromType(typeof(Location));

Places, Devices, and Assets

static Location location;
static LocationPlace place;
static LocationDevice device;
static LocationAsset asset;


location = (Location)mobileBackend.GetServiceProxy(Class.FromType(typeof(Location)));

LocationPlaceQuery locationPlaceQuery = location.BuildPlaceQuery();

locationPlaceQuery.Name = "West";

locationPlaceQuery.OrderByAttributeType = LocationDeviceContainerQuery.LocationDeviceContainerQueryOrderByAttributeType.LocationDeviceContainerQueryOrderByAttributeTypeName;
locationPlaceQuery.Format = LocationObjectQuery.LocationObjectQueryFormatType.LocationObjectQueryFormatTypeShort;

locationPlaceQuery.Execute(new LocationObjectQueryCallback());

LocationDeviceQuery locationDeviceQuery = location.BuildDeviceQuery();

locationDeviceQuery.Name = "Beacon";

locationDeviceQuery.OrderByAttributeType = LocationDeviceQuery.LocationDeviceQueryOrderByAttributeType.LocationDeviceQueryOrderByAttributeTypeName;
locationDeviceQuery.Format = LocationObjectQuery.LocationObjectQueryFormatType.LocationObjectQueryFormatTypeShort;

locationDeviceQuery.Execute(new LocationObjectQueryCallback());



LocationAssetQuery locationAssetQuery = location.BuildAssetQuery();

locationAssetQuery.Name = "Joe";

locationAssetQuery.OrderByAttributeType = LocationDeviceContainerQuery.LocationDeviceContainerQueryOrderByAttributeType.LocationDeviceContainerQueryOrderByAttributeTypeName;
locationAssetQuery.Format = LocationObjectQuery.LocationObjectQueryFormatType.LocationObjectQueryFormatTypeShort;

locationAssetQuery.Execute(new LocationObjectQueryCallback());

Fetching a Place

private class LocationObjectQueryCallback : Java.Lang.Object, ILocationObjectsQueryCallback
{

    public void OnComplete(LocationObjectQueryResult queryResult, ServiceProxyException exception)
    {
        if (mProgressDialog != null && mProgressDialog.IsShowing)
        {
            mProgressDialog.Dismiss();
        }

        if (exception != null)
        {
            Logger.Debug(TAG, exception.Message);

            setText(exception.Message);
        }
        else
        {
            
            foreach (LocationObject locationobject in queryResult.Items)
            {

                if (locationobject.GetType().Equals(typeof(LocationPlace))) { 

                    place = (LocationPlace)locationobject;

                    location.FetchPlace(place.Id, new LocationObjectFetchCallback());

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

                    Logger.Debug(TAG, place.Name +"  " + place.HasChildren);
                }
                else if(locationobject.GetType().Equals(typeof(LocationDevice)))
                {

                    device = (LocationDevice)locationobject;

                    location.FetchDevice(device.Id, new LocationObjectFetchCallback());

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

                    Logger.Debug(TAG, device.Name + "  ");
                }
                else if (locationobject.GetType().Equals(typeof(LocationAsset)))
                {

                    asset = (LocationAsset)locationobject;

                    location.FetchAsset(asset.Id, new LocationObjectFetchCallback());

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

                    Logger.Debug(TAG, asset.Name + "  ");
                }

            }
        }
    }
}


private class LocationObjectFetchCallback : Java.Lang.Object, ILocationObjectFetchCallback
{

    public void OnComplete(LocationObject locationObject, ServiceProxyException exception)
    {
        if (mProgressDialog != null && mProgressDialog.IsShowing)
        {
            mProgressDialog.Dismiss();
        }

        if (exception != null)
        {
            Logger.Debug(TAG, exception.Message);

            setText(exception.Message);
        }
        else
        {
            Logger.Debug(TAG, locationObject.Name );

        }

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

    }
}

Refreshing

private class LocationObjectQueryCallback : Java.Lang.Object, ILocationObjectsQueryCallback
{

    public void OnComplete(LocationObjectQueryResult queryResult, ServiceProxyException exception)
    {
        if (mProgressDialog != null && mProgressDialog.IsShowing)
        {
            mProgressDialog.Dismiss();
        }

        if (exception != null)
        {
            Logger.Debug(TAG, exception.Message);

            setText(exception.Message);
        }
        else
        {
            
            foreach (LocationObject locationobject in queryResult.Items)
            {

                if (locationobject.GetType().Equals(typeof(LocationPlace))) { 

                    place = (LocationPlace)locationobject;

                    place.Refresh(new LocationObjectFetchCallback());

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

                    Logger.Debug(TAG, place.Name +"  " + place.HasChildren);
                }
                else if(locationobject.GetType().Equals(typeof(LocationDevice)))
                {

                    device = (LocationDevice)locationobject;

                    device.Refresh(new LocationObjectFetchCallback());

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

                    Logger.Debug(TAG, device.Name + "  ");
                }
                else if (locationobject.GetType().Equals(typeof(LocationAsset)))
                {

                    asset = (LocationAsset)locationobject;

                    asset.Refresh(new LocationObjectFetchCallback());

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

                    Logger.Debug(TAG, asset.Name + "  ");
                }

            }
        }
    }
}

private class LocationObjectFetchCallback : Java.Lang.Object, ILocationObjectFetchCallback
{

    public void OnComplete(LocationObject locationObject, ServiceProxyException exception)
    {
        if (mProgressDialog != null && mProgressDialog.IsShowing)
        {
            mProgressDialog.Dismiss();
        }

        if (exception != null)
        {
            Logger.Debug(TAG, exception.Message);

            setText(exception.Message);
        }
        else if(locationObject != null)
        {
            Logger.Debug(TAG, locationObject.Name );

        }

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

    }
}

Storage

Initialization

Storage storage = (Storage)mobileBackend.GetServiceProxy(Class.FromType(typeof(Storage)));

Getting a Collection

StorageCollection storageCollection = storage.GetStorageCollection("FullCoverage_Private");
StorageObject storageObject = storageCollection.Get("ab911696-7e61-4fcd-a244-b26adb6183ba");
string str = Encoding.UTF8.GetString(Decompress(storageObject.GetPayloadBytes()));

Getting an Object

storageObject = storageCollection.Get("d4400472-b912-4f7a-b4f5-e32523e5c1f3");
Logger.Debug(TAG, "Storage Object:  " + storageObject.DisplayName);

Getting All Objects

IList<StorageObject> list =  storageCollection.Get(0, 100, true);

IEnumerator<StorageObject> iEnumerator = list.GetEnumerator();
while(iEnumerator.MoveNext()){
    storageObject = iEnumerator.Current;
    Logger.Debug(TAG, "Storage Object:  " + storageObject.DisplayName);

}

Uploading a Text File

Java.Lang.String str = new Java.Lang.String("This is sample txt file");

storageObject = new StorageObject("textfile.txt");
storageObject.SetPayload(str.GetBytes(), "text/plain");
storageCollection.Put(storageObject);

Uploading an Image

System.IO.Stream imageBytes = getFileFromAssets("mcs_oracle.png");

storageObject = new StorageObject("mcs_oracle.png", imageBytes, "image/jpeg");
var imagePosted = storageCollection.Post(storageObject);

Decompressing

static byte[] Decompress(byte[] data)
{
    using (var compressedStream = new MemoryStream(data))
    using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
    using (var resultStream = new MemoryStream())
    {
        zipStream.CopyTo(resultStream);
        return resultStream.ToArray();
    }
}

Notifications

Initialization

LocalBroadcastManager.GetInstance(context)
        .RegisterReceiver(new MBroadcastReceiver(), 
        new IntentFilter(NotificationsConfig.RegistrationComplete));

Notifications notifications = (Notifications)mobileBackend.GetServiceProxy(Java.Lang.Class.FromType(typeof(Notifications)));

Registering for Notifications

bool result = notifications.Initialize(context, "Sender ID");

Broadcast Receiver

private class MBroadcastReceiver : BroadcastReceiver
{

    public override void OnReceive(Context context, Intent intent)
    {

        if (mProgressDialog != null && mProgressDialog.IsShowing)
        {
            mProgressDialog.Dismiss();
        }

        ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(context);
        bool sentToken = prefs.GetBoolean(NotificationsConfig.SentTokenToServer, false);
        if (sentToken)
        {
            Logger.Debug(TAG, "Token retrieved and sent to server! App can use GCM");
        }
        else
        {
            Logger.Debug(TAG, "An error occurred while either fetching the InstanceID");
        }

    }
}

Analytics

Initialization

static Analytics analyticsAgent = 
        (Analytics)mobileBackend
        .GetServiceProxy(Class.FromType(typeof(Analytics)));
analyticsAgent.SetContext(activity);

Logging an Event

if (analyticsAgent != null)
	analyticsAgent.LogEvent("This is Event No. : " + i);

Setting Context Location

analyticsAgent.SetContextLocation("India", "Telangana", "Hyderabad", "500081");

Flushing an Event

analyticsAgent.Flush();

App Policies

Loading the App Config and Getting Policies

if (mobileBackend != null)
{
     mobileBackend.LoadAppConfig(new AAppConfigCallBack());
     mProgressDialog = ProgressDialog.Show(activity, "Please Wait", "App Config is being loaded.");

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

     AppConfig oMCAppConfig = mobileBackend.AppConfig;


//Getting String:

     string str = oMCAppConfig.GetString("Test_String", "No value configured");

     setText("AppConfig: String:  " + str);


//Getting Number
     Number number = oMCAppConfig.GetNumber ("Test_number", new Java.Lang.Double(1.0));

     setText("AppConfig: Number:  " + number);


//Getting boolean
     bool boolean = oMCAppConfig.GetBoolean("Test_Boolean", false);

     setText("AppConfig: Boolean:  " + boolean);

}

private class AAppConfigCallBack : AppConfigCallback
{
     public override void OnResult(Oracle.Cloud.Mobile.Utils.McsError error, AppConfig config)
  {
      if (mProgressDialog != null && mProgressDialog.IsShowing)
      {
          mProgressDialog.Dismiss();
      }

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

Calling Custom APIs Using the SDK for Xamarin Android

The SDK provides the CustomHttpResponse class, the GenericCustomCodeClientCallBack interface, and the InvokeCustomCodeJSONRequest method in the authorization classes to simplify the calling of custom APIs in MCS. 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.

You use GenericCustomCodeClientCallBack to create a handler for the response (which is returned in the form of a CustomHttpResponse object.)

Then, to call the custom API, you call InvokeCustomCodeJSONRequest(GenericCustomCodeClientCallBack restClientCallback, JSONObject data, String functionName, RestClient.HttpMethod httpMethod) on your Authorization object.

To make a call to a custom API endpoint, you could use something like this:

IAuthorizationAgent mAuthorization = MobileBackendManager.Manager.GetDefaultMobileBackend(context).Authorization;

mAuthorization.Authenticate(mActivity, "user1", "pass1", new AuthorizationCallback());

........
// after the user successfully authenticates, make a call to the custom API endpoint
mAuthorization.InvokeCustomCodeJSONRequest(new GenericCustomCodeClientCallBack(), null, "TaskApi/tasks", RestClient.HttpMethod.Get);


private class GenericCustomCodeClientCallBack : Java.Lang.Object, IGenericCustomCodeClientCallBack
{
	public void RequestCompleted(CustomHttpResponse response, JSONObject data, Java.Lang.Exception exception)
	{
		Logger.Debug(TAG, response.HttpStatus + "");
	}
}