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
Add the SDK
-
If you haven’t already done so, extract the contents from the SDK zip.
-
In Visual Studio, create a Visual C# Android app.
-
Make sure you can connect to the internet from Visual Studio connection so that NuGet packages are reachable.
-
Add GCM and Facebook dependencies to your project:
-
If a Packages node appears in the Solution Explorer for your project, do the following:
-
Right-click the Packages node.
-
Type
GCM
in the search field, selectXamarin.GooglePlayServices.Gcm
(notCrosslight.Xamarin.GooglePlayServices.GCM
), and click Add Package. The remaining GCM dependencies will be added automatically. -
Accept the terms to add the packages successfully.
-
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:-
Select Tools > NuGet Package Manager > Manage NuGet Packages for Solution.
-
Select the Browse tab.
-
Type
GCM
in the search field, selectXamarin.GooglePlayServices.Gcm
(notCrosslight.Xamarin.GooglePlayServices.GCM
), select the checkbox for your app, and click Install. The remaining GCM dependencies will be added automatically. -
After previewing the changes, click OK.
-
Add
Xamarin.Facebook.Android
by searching for it in the NuGet packages and adding it in the same way you added the GCM packages.
-
-
-
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>
-
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.
-
-
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. -
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 toAndroidAsset
.
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
andoAuthTokenEndpoint
. 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 isERROR
. Other possible values (in increasing level of detail) areWARNING
,INFO
, andDEBUG
. It is also possible to specifyNONE
. -
enableLogger
— When set totrue
, logging is included in your application. -
logHTTP
— When set totrue
, 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 ofoauth
,basic
,facebook
, andtokenExchange
. -
One or more sub-elements for authentication types, each containing authentication credentials.
You can also add the
offlineEnabled
key and set its value totrue
.
-
-
enableOffline
— If set totrue
, 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'sAndroidManifest.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 tooauth
. -
Fill in the
clientID
andclientSecret
credentials provided by the backend. -
Optionally, if you want to disable offline authentication, add the
enableOffline
element and set it tofalse
. -
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 tobasic
. -
Fill in the
mobileBackendID
andanonymousKey
that are provided by the backend. -
Optionally, if you want to disable offline authentication, add the
enableOffline
sub-element and set it tofalse
.
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 totokenExchange
. -
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 tofacebook
. -
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:
-
Add an SDK call to your app to load the configuration info.
-
Add an SDK call to your app to handle authentication.
-
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");
}
}
}
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 + "");
}
}