6 Xamarin Android Apps

If you use the Xamarin platform to develop Android apps, you can use the SDK that Oracle Mobile Hub provides for Xamarin Android 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 Android, 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# 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.

The next steps will be to fill in the appropriate data in the oracle_mobile_cloud_config.xml and AndroidManifest.xml files.

Configure SDK Properties

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

You package the configuration file in your app’s main bundle in the assets folder at the same level as the java and res folders. For example, in the sample GettingStarted app, it’s in /GettingStarted/src/main/assets.

The file is essentially divided into the following parts:

  • The mobileBackend element 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.

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

The following code sample shows the structure of a oracle_mobile_cloud_config.xml file.

<config>

  <!--This value is required if you are using OAuth to authenticate against the mobile backend-->
  <oAuthTokenEndPoint>YOUR_OAUTH_TOKEN_END_POINT<oAuthTokenEndPoint>
  <!--Set to true if you want to get logging information-->
  <enableLogger>true</enableLogger>
  <logLevel>DEBUG</logLevel>
  <!--Whether to log HTTP call request and response bodies and headers-->
  <logHTTP>true</logHTTP>

  <!-- Include the mobileBackend element and its sub-elements if you are going 
       to be using a backend to access custom and platform APIs.-->
  <mobileBackend>
    <name>MBE_NAME</name>
    <baseUrl>BASE_URL</baseUrl>
    <enableAnalytics>true</enableAnalytics>
    <authentication>
      <!--possible values for type are [oauth, basic, facebook, tokenExchange ]-->
      <type>AUTH_TYPE</type>
      <oauth>
        <clientId>CLIENT_ID</clientId>
        <clientSecret>CLIENT_SECRET</clientSecret>
        <enableOffline>true</enableOffline>
      </oauth>
      <basic>
        <mobileBackendId>MOBILE_BACKEND_ID</mobileBackendID>
        <anonymousKey>ANONYMOUS_KEY</anonymousKey>
        <enableOffline></enableOffline>
      </basic>
      <facebook>
        <appId>FACEBOOK_APP_ID</appId>
        <scopes>public_profile,user_friends,email,user_location,user_birthday</scopes>
        <basic>
          <mobileBackendId>MOBILE_BACKEND_ID</mobileBackendID>
          <anonymousKey>ANONYMOUS_KEY</anonymousKey>
        </basic>
      </facebook>
      <tokenExchange>
        <! tokenExchange can contain an 'oauth' sub-element or a 'basic' sub-element.
        <oauth>
          <clientId>CLIENT_ID</clientId>
          <clientSecret>CLIENT_SECRET</clientSecret>
        </oauth>
        <basic>
          <mobileBackendId>MOBILE_BACKEND_ID</mobileBackendID>
          <anonymousKey>ANONYMOUS_KEY</anonymousKey>
        </basic>
      <tokenExchange>
    </authentication>
    <!-- additional properties go here -->
  </mobileBackend>

</config>

The values that you need to fill in for a given backend can be found on the Settings and App Profile pages for that mobile backend.

Here are some more notes on the file’s elements.

  • oAuthTokenEndPoint — The URL of the OAuth server from where your application gets its authentication token. This key needs to be provided for all applications that rely on OAuth to authenticate. You get this from the backend’s Settings page.

  • logLevel — Determines how much SDK logging is displayed in the application'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 specify NONE.

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

  • logHTTP — When set to true, the SDK logs the HTTP and HTTPS headers in requests and responses.

  • mobileBackend — An element 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 the following sub-elements:

    • The type sub-element, with possible values of oauth, basic, facebook, and tokenExchange.

    • One or more sub-elements for authentication types, each containing authentication credentials.

      You can also add the offlineEnabled key and set its value to true.

  • enableOffline — If set to true, offline login will be allowed. This applies only to the Basic and OAuth login types. For this to work, you also need to add the following to the application'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>

Authentication Properties

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

OAuth
  • Set the value of the <type> element to oauth.

  • Fill in the clientID and clientSecret  credentials provided by the backend.

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

  • At the top level of the file, supply the oAuthTokenEndPoint value.

The resulting authentication element might look something like this:

<oAuthTokenEndPoint>http://oam-server.oracle.com/oam/oauth2/tokens</oAuthTokenEndPoint>

<authentication>
  <type>oauth</type>
  <oauth>
    <clientId>f2d3ca5c-7e6f-4d1c-aabc-a2f3caf7ec4e</clientId>
    <clientSecret>vZMRkgniIbhNUiPnSRT2</clientSecret>
    <enableOffline>false</enableOffline>
  </oauth>
</authentication>
HTTP Basic
  • Set the value of the type element to basic.

  • Fill in the mobileBackendID and anonymousKey that are provided by the backend.

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

The resulting authentication element might look something like this:

<authentication>
  <type>basic</type>
  <basic>
    <mobileBackendID>6d3744b8-cab2-479c-998b-ebba2c31560f</mobileBackendID>
    <anonymousKey>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTll</anonymousKey>
    <enableOffline>false</enableOffline>
  </basic>
</authentication>
Token Exchange

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

  • Set the value of the <type> element to tokenExchange.

  • Create a <basic> sub-element and fill in the OAuth Consumer credentials provided by the backend.

The resulting authentication element might look something like this:

<authentication>
  <type>tokenExchange</type>
    <basic>
      <mobileBackendID>6d3744b8-cab2-479c-998b-ebba2c31560f</mobileBackendID>
      <anonymousKey>UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTll</anonymousKey>
    </basic>
  <tokenExchange>
</authentication>
Facebook Login

For Facebook login:

  • Set the value of the <type> property to facebook.

  • Create a <facebook> sub-element.

  • Fill in the <appID> for the Facebook app.

  • Fill in <scopes> with any relevant Facebook permissions (optional).

  • Within <facebook>, created a <basic> element and fill in the HTTP Basic credentials provided by the backend.

The resulting authentication element might look something like this:

<authentication>
  <type>facebook</type>
  <facebook>
    <basic>
      <mobileBackendId>MOBILE_BACKEND_ID</mobileBackendId>
      <anonymousKey>ANONYMOUS_KEY</anonymousKey>		
    </basic>
    <appID>123456789012345</appId>
    <scopes>public_profile,user_friends,email,user_location,user_birthday</scopes>
  </facebook>
<authentication>

Configure Your Android Manifest File

Permissions for operations such as accessing the network and finding the network state are controlled through permission settings in your application's manifest file, 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, there are a number of permissions necessary so the app can get notifications. For a rundown on the available permissions, 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.sample" >
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <application>
<provider
	android:name="com.facebook.FacebookContentProvider"
	android:authorities="com.facebook.app.FacebookContentProvider430660953811847"
	android:exported="true" />    
<receiver 
	android:name="oracle.cloud.mobile.network.NetworkHelper"
      <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
      </intent-filter>
    </receiver>

    (.....)
  </application>
</manifest>

Adding the client SDK to your application may require you to configure your AndroidManifest.xml file to add new permissions or activities. For example, if you add the Notifications individual SDK library, you may also need to add a new broadcast receiver.

Call Mobile APIs

Here are the general steps for calling mobile APIs:

  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 Oracle Mobile Hub APIs using the Android client SDK to successfully complete, you need to have the backend’s configuration loaded from the app’s oracle_mobile_cloud_config.xml file. You do this using the MobileManager class:

MobileManager.getManager().getMobileBackend(this)

Authenticate and Log In

Here is some sample code that you can use for authentication through the service in your 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");
        }
    }
}
SSO with a Third-Party Token

First, your app needs to get a token from the third-party token issuer.

Once you have the token, initialize the authorization agent and use the token in your authorization call.

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();
        }
    }
}

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.

HTTP Basic

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);
}

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 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);    
      }
  }
}

Call Custom APIs

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 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.

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 + "");
	}
}