2 Android Apps
Oracle Mobile Cloud Enterprise (OMCe) provides an SDK for Android that makes it easy to use OMCe’s features.
Getting the SDK
To get the OMCe client SDK for Android, go to the Oracle Mobile Cloud Enterprise Downloads page on OTN.
Creating a Backend
You create a backend to serve as a secure gateway between your app and OMCe features, such as platform and custom APIs. For your app to access these resources, it authenticates with a backend.
-
Click to open the side menu and select Mobile Apps > Backends.
-
Click New Backend.
-
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.
Adding the SDK
Assuming a basic app setup, without intervening frameworks, here’s what you would do to add the Android client SDK to an app
-
If you haven’t already done so, unzip the Android client SDK zip.
-
Copy the SDK jars into the
libs
folder in your app's project. If this folder doesn't exist, create it at the same level in your hierarchy as yoursrc
andbuild
folders. -
Import the
IDMMobileSDK.jar
into the project. (In Android Studio, select File > New > New Module, click Import .JAR/.AAR Package, click Next, selectIDMMobileSDK.jar
and click Next.) -
In the source tree for the application, create a folder called
assets
(at the same level as thejava
andres
folders). -
In the SDK bundle, locate the
oracle_mobile_cloud_config.xml
file and copy it to theassets
folder. -
In your app's
build.gradle
file, make sure the following are among the dependencies registered so that the SDK libraries are available to the app.dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.squareup.okhttp3:okhttp:3.9.0' compile 'org.slf4j:slf4j-jdk14:1.7.13' //to enable the app to receive notifications, include the following: compile 'com.google.firebase:firebase-messaging:11.0.2' }
-
Open
assets/oracle_mobile_cloud_config.xml
and fill in the environment details for the mobile backend that the app will be using.
Configuring 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 OMCe. In turn, the SDK classes use this information to construct HTTP headers for REST calls made to OMCe.
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 apps 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 app’s console. The default value isERROR
. Other possible values (in increasing level of detail) areWARNING
,INFO
, andDEBUG
. It is also possible to specifyNONE
. -
enableAnalytics
— When set totrue
, analytics are collected for system and custom events that were defined with the legacy Mobile Cloud Service analytics features. This option has no impact on the current analytics features. -
enableLogger
— When set totrue
, logging is included in your app. -
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
.
See Authentication Properties for examples of each authentication type.
-
-
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 app’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>
Configuring 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 for the app to be able to receive 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>
<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. For more information, see Setting Up a Mobile App for Notifications.
Calling Mobile APIs
In OMCe, a backend is a logical grouping of custom APIs, storage collections, and other resources that you can use in your apps. The backend also provides the security context for accessing those resources.
Here are the general steps for using a backend in your Android app:
-
Add the client SDK to your app.
-
Fill in the
oracle_mobile_cloud_config.xml
with environment and authentication details for the backend. -
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.
Loading the Backend's Configuration
For any calls to OMCe 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)
Authenticating and Logging In
Here is some sample code that you can use for authentication through OMCe in your Android apps.
OAuth Consumer
First you initialize the authorization agent and set the authentication type to OAUTH
:
private AuthorizationAgent mAuthorization;
private MobileBackend mobileBackend;
try {
mobileBackend = MobileManager.getManager().getMobileBackend(this);
} catch (ServiceProxyException e) {
e.printStackTrace();
}
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 = (TextView) findViewById(R.id.username);
password = (TextView) findViewById(R.id.password);
String userName = username.getText().toString();
String passWord = password.getText().toString();
mAuthorization.authenticate(mCtx, userName, passWord, mLoginCallback);
Here’s the definition for the callback:
AuthorizationCallback mLoginCallback = new AuthorizationCallback() {
@Override
public void onCompletion(ServiceProxyException exception) {
Log.d(TAG, "OnCompletion Auth Callback");
if (exception != null) {
Log.e(TAG, "Exception while receiving the Access Token", exception);
} else {
Log.e(TAG, "Authorization successful");
}
}
}
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 OMCe, see Third-Party SAML and JWT Tokens.
Once you have the token, initialize the authorization agent and use the token in your authorization call.
private AuthorizationAgent mAuthorization;
private MobileBackend mobileBackend;
Context mCtx = getApplicationContext();
try {
mobileBackend = MobileManager.getManager().getMobileBackend(this);
} catch (ServiceProxyException e) {
e.printStackTrace();
}
mAuthorization = mobileBackend.getAuthorization(AuthType.TOKENEXCHANGE);
Then you use the authenticateUsingTokenExchange
method to attempt authentication.
mAuthorization.authenticateUsingTokenExchange(mCtx, token, false, mLoginCallback);
Here’s the callback:
AuthorizationCallback mLoginCallback = new AuthorizationCallback() {
@Override
public void onCompletion(ServiceProxyException exception) {
if (exception == null) {
//redirect to another Activity after login
Intent intent = new Intent(mCtx, ContentActivity.class);
startActivity(intent);
} else {
Log.e(TAG, "Exception during token exchange:", exception);
finish();
}
}
};
Note:
The default expiration time for storing a third-party token in OMCe is 6 hours. You can adjust this time by changing theSecurity_TokenExchangeTimeoutSecs
policy. See Modifying Policies in Administering Oracle Mobile Cloud, Enterprise.
SSO with a Third-Party Token — Staying Logged In
You can also code the app to keep the user logged in, even when closing and restarting the app.
In the above example, the authenticateUsingTokenExchange()
method is called with the third parameter (storeToken
) set to false
. If you set this parameter to true
and the token exchange is successful, the MCS token is stored in a secure store and the user remains logged in until the token expires.
You can then use the loadSSOTokenExchange
method on the Authorization
object to load the stored token. If a token can’t be retrieved from the secure store, the method returns false
.
Here’s some code that tries to load a saved token and, if it fails, restarts the authentication process:
try {
mAuthorization = MobileManager.getManager().getMobileBackend(this).getAuthorization();
if (!mAuthorization.loadSSOTokenExchange(mCtx)) {
//user not logged in, so need to initiate login
mAuthorization.authenticateUsingTokenExchange(mCtx, token, true, mLoginCallback);
}
When you have the token stored in the secure store, it remains associated with the mobile backend that the app originally used. Therefore, if the app is updated to use a different mobile backend (or mobile backend version), you need to clear the saved token and re-authenticate.
mAuthorization.clearSSOTokenExchange(mCtx);
mAuthorization.authenticateUsingTokenExchange(mCtx, token, true, mLoginCallback);
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
:
private AuthorizationAgent mAuthorization;
private MobileBackend mobileBackend;
try {
mobileBackend = MobileManager.getManager().getMobileBackend(this);
} catch (ServiceProxyException e) {
e.printStackTrace();
}
mAuthorization = mobileBackend.getAuthorization(AuthType.BASIC_AUTH)
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 = (TextView) findViewById(R.id.username);
password = (TextView) findViewById(R.id.password);
String userName = username.getText().toString();
String passWord = password.getText().toString();
mAuthorization.authenticate(mCtx, userName, passWord, mLoginCallback);
Here’s the definition for the callback:
AuthorizationCallback mLoginCallback = new AuthorizationCallback() {
@Override
public void onCompletion(ServiceProxyException exception) {
Log.d(TAG, "OnCompletion Auth Callback");
if (exception != null) {
Log.e(TAG, "Exception while receiving the Access Token", exception);
} else {
Log.e(TAG, "Authorization successful");
}
}
}
For Facebook login, you use classes in the oracle_mobile_android_social
library.
First you initialize the authorization agent and set the authentication type to Facebook
:
SocialAuthorizationAgent mAuthorization;
SocialMobileBackend socialMobileBackend;
try {
socialMobileBackend = SocialMobileBackendManager.getManager().getMobileBackend(mCtx);
} catch(ServiceProxyException e){
e.printStackTrace();
}
mAuthorization = socialMobileBackend.getSocialAuthorization(); mAuthorization.setAuthType(AuthType.FACEBOOK);
Using a CallbackManager
object from Facebook’s SDK, initiate authentication.
private CallbackManager callbackManager;
mAuthorization.setup(getApplicationContext(), callback);
callbackManager = mAuthorization.getCallBackManager();
mAuthorization.authenticateSocial(mCtx);
Here’s code you can use for the callback
that is passed above:
private FacebookCallback<LoginResult> callback = new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
Log.e(TAG, "facebook login successful.");
}
@Override
public void onCancel() {
}
@Override
public void onError(FacebookException e) {
}
};
Override the onActivityResult()
method to use the callback:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
Calling Platform APIs
Once the mobile backend’s configuration info is loaded into the app, you can make calls to client SDK classes.
The root object in the Android SDK is MobileManager
. The MobileManager
object manages MobileBackend
objects.
The MobileBackend
object manages connectivity, authentication, and other transactions between your application and its associated backend, including calls to platform APIs and any custom APIs you have defined. It manages calls to platform APIs through instances of ServiceProxy
such as Storage
and Location
.
Here’s an example of how you would use these classes to upload an image using the Storage API:
try {
Storage storage = MobileManager.getManager().getMobileBackend(this).getServiceProxy(Storage.class);
StorageCollection imagesCollection = storage.getStorageCollection("FIF_Images");
StorageObject imageToUpload = new StorageObject(null, imageBytes, "image/jpeg");
StorageObject uploadedImage = imagesCollection.post(imageToUpload);
} catch(ServiceProxyException e) {int errorCode = e.getErrorCode();
...
}
The ServiceProxy
instance created there manages calls to the Storage platform API, including the constructing of the HTTP headers with the mobile backend credentials necessary to access the API.
And here’s how you could retrieve an image using the Storage API:
try {
Storage storage = MobileManager.getManager().getMobileBackend(this).getServiceProxy(Storage.class);
StorageCollection imagesCollection = storage.getStorageCollection("FIF_Images");
StorageObject image = imagesCollection.get("3x4mp1e-st0r4g3-0bj3ct-k3y");byte[] imageBytes = image.getPayloadBytes();
} catch(ServiceProxyException e) {int errorCode = e.getErrorCode();
...
}
Calling Custom APIs
The client SDK provides the CustomHttpResponse
class, the GenericCustomCodeClientCallBack
interface, and the invokeCustomCodeJSONRequest
method in the authorization classes to simplify the calling of custom APIs in OMCe. 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:
import org.json.JSONObject;
import oracle.cloud.mobile.customcode.CustomHttpResponse;
import oracle.cloud.mobile.customcode.GenericCustomCodeClientCallBack;
import oracle.cloud.mobile.mobilebackend.MobileManager;
.......
final GenericCustomCodeClientCallBack genericCustomCodeClientCallBack = new GenericCustomCodeClientCallBack() {
@Override
public void requestCompleted(CustomHttpResponse response, JSONObject data, Exception e) {
boolean getResponse = (response.getHttpStatus() >=200 && response.getHttpStatus() <300);
// write any logic based on above response
}
};
AuthorizationAgent authorization = MobileManager.getManager().getMobileBackend(this).getAuthorization();
authorization.authenticate(mActivity, "user1", "pass1", successCallback);
........
// after the user successfully authenticates, make a call to the custom API endpoint
authorization.invokeCustomCodeJSONRequest(genericCustomCodeClientCallBack, null, "TaskApi/tasks", RestClient.HttpMethod.GET);
Libraries and Dependencies
Libraries
The following SDK libraries (JAR files) are included in the Android client SDK:
-
omce-android-sdk-shared-<version-number>.jar
- The base library for the SDK, including functionality required by the other libraries as well as utility classes for accessing and authenticating with mobile backends. -
IDMMobileSDK.jar
- The identity management library used by all applications. -
omce-android-sdk-location-<version-number>
- The Location library, which lets you access details about location devices that have been registered in OMCe and the places and assets they are associated with. -
omce-android-sdk-notifications-<version-number>.jar
- The Notifications library, which lets you set up your application to receive notifications sent from your mobile backend. -
omce-android-sdk-social-<version-number>
- The Social Login library, which allows you to set up your app to use Facebook login. -
omce-android-sdk-storage-<version-number>.jar
- The Storage library, which lets you write code to access storage collections that are set up with your mobile backend. -
omce-android-sdk-sync-<version-number>
- The Sync Client library, which allows you to cache application data when the device running your app is disconnected from the network, then sync up the data when the network connection is reestablished.
Dependencies
The SDK is modular, so you can package just the libraries that your app needs. Just be aware of the following dependencies:
-
Every Android application developed for OMCe must have the shared (
oracle-mobile_android_shared-<version-number>.jar
) andIDMMobileSDK.jar
libraries. -
If the Storage library is installed, the Sync Client library must also be installed.