Skip to content

Storage Service

The SAP Cloud Platform Mobile Services provides storage service for managing application-related settings.

Storage service provides management of data at three target levels:

  • Application
  • User
  • Device

Application level is the highest and Device level is the lowest.

For example, Loglevel in the application level is inherited by every user of the application. If the user changes the log level for the User Target, the change is applied only to that specific user. All the devices that authenticate with that specific user will have the user log level. If a log level is changed in Device Target level, it applies to only that specific device. The application and user log level will not change.

By default, if a target is not specified, Device-level data are provided. Additionally, mobile application developers can create their own data to be stored and retrieved using the Storage APIs. The Settings classes of foundation modules provide methods to store, read, and delete the Storage service data.

See Storage Service API in the SAP Cloud Platform Mobile Services documentation for more information.

Storage Data

Storage service supports the storing of JSON data. At the root level, mobile services-related settings are available under JSON node mobileservices/settingsExchange. The application may also store settings using custom nodes. Please refer to Storage Service API in the Mobile Services documentation for complete information. In a typical scenario, the mobile application developer only needs to be familiar with the common mobile services settings like log level.

Below is an example of a full settings document that has mobile service settings and custom settings.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    {
        "mobileservices": {
            "settingsExchange": {
                "passwordPolicy": {
                    "passwordPolicyMinLength": "8",
                    "passwordPolicyLowerRequired": "false",
                    "passwordPolicyDefaultPasswordAllowed": "false",
                    "passwordPolicyRetryLimit": "10",
                    "passwordPolicyUpperRequired": "false",
                    "passwordPolicyEnabled": "false",
                    "passwordPolicySpecialRequired": "false",
                    "passwordPolicyExpiresInNDays": "0",
                    "passwordPolicyLockTimeout": "300",
                    "passwordPolicyDigitRequired": "false",
                    "passwordPolicyMinUniqueChars": "0"
                },
                "featureVectorPolicies": {
                    "featureVectorPolicyAllEnabled": "true",
                    "restrictedPolicies": null
                },
                "logSettings": {
                    "logEntryExpiry": "7",
                    "logLevel": "NONE"
                },
                "blockWipingPolicy": {
                    "wipeDisconnectedPeriod": "0",
                    "blockWipeEnabled": "false",
                    "blockDisconnectedPeriod": "0"
                }
            }
        },
        "customAppDefinedConfigs1": {
            "appConfig1": "value1",
            "appConfig2": "value2"
        }
    }

Settings Target

Settings target refers to the level of storage data.

  • SettingTarget.APPLICATION – Any data at this level applies to all the users and mobile devices used by the mobile service application.

  • SettingTarget.USER – Any data at this level applies to all the devices for this user. By default when no node is overridden at this level, data from application level is inherited.

  • SettingTarget.DEVICE – Any data at this level applies to the device the mobile app is currently running on. By default, if no node is overridden at this level, data from user level is inherited.

In a typical usage scenario, you will be using SettingTarget.DEVICE.

Settings Path

Settings path refers to the JSON node path within the settings document.

For example, using mobileservices returns:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    {
      "settingsExchange": {
        "passwordPolicy": {
          "passwordPolicyMinLength": "8",
          "passwordPolicyLowerRequired": "false",
          "passwordPolicyDefaultPasswordAllowed": "false",
          "passwordPolicyRetryLimit": "10",
          "passwordPolicyUpperRequired": "false",
          "passwordPolicyEnabled": "false",
          "passwordPolicySpecialRequired": "false",
          "passwordPolicyExpiresInNDays": "0",
          "passwordPolicyLockTimeout": "300",
          "passwordPolicyDigitRequired": "false",
          "passwordPolicyMinUniqueChars": "0"
        },
        "featureVectorPolicies": {
          "featureVectorPolicyAllEnabled": "true",
          "restrictedPolicies": null
        },
        "logSettings": {
          "logEntryExpiry": "7",
          "logLevel": "NONE"
        },
        "blockWipingPolicy": {
            "wipeDisconnectedPeriod": "0",
            "blockWipeEnabled": "false",
            "blockDisconnectedPeriod": "0"
        }
      }
    }
mobileservices/settingsExchange/logSettings returns:

1
2
3
4
{
    "logEntryExpiry": "7",
    "logLevel": "NONE"
}

Usage

Loading Settings

The load method loads settings values from mobile services. Specify the desired Settings Target and Settings Path to load. If the target is not specified, the Device Target is used as default. If NULL is used for the path, the settings from the root level are retrieved.

This method must be invoked from the UI thread. It takes SettingTarget and KeyPath as parameters. The callback methods are invoked on the UI thread.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   //Initialize the target URI string
   OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
   SettingsParameters settingsParameters = new SettingsParameters(HCPMS_URL, APPID, ANDROID_ID, "1.0");
   final Settings settings = new Settings(okHttpClient, settingsParameters);
   settings.load(Settings.SettingTarget.DEVICE, Settings.KeyPath.MOBILESERVICES,
      new Settings.CallbackListener() {
          @Override
          public void onSuccess(JSONObject jsonObject) {
            //Here goes the code for processing successful response...
            //Use JSONObject API for processing the results
            //See https://developer.android.com/reference/org/json/JSONObject.html, for more detail
            //Add here code for processing successful response. For example see the code below
            int valueForPasswordPolicyTimeout = jsonObject.getJSONObject("passwordPolicy").getInt("passwordPolicyLockTimeout");
          }

          @Override
          public void onError(Throwable result) {
            //Place your failure handling code here...
            if (result instanceof HttpException) {
                //HttpException type com.sap.cloud.mobile.foundation.networking.HttpException
                HttpException ne = (HttpException)result;
                Log.e("Http Exception: " , ne.message() + ", with Error code: " + ne.code());
            } else {
                Log.e("Exception occurred: ", result.getMessage());
            }
          }
    });
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    //Initialize the target URI string
    val okHttpClient = OkHttpClient.Builder().build()
    val settingsParameters = SettingsParameters(HCPMS_URL, APPID, ANDROID_ID, "1.0")
    val settings = Settings(okHttpClient, settingsParameters)
    settings.load(Settings.SettingTarget.DEVICE, Settings.KeyPath.MOBILESERVICES,
        object : Settings.CallbackListener {
            override fun onSuccess(jsonObject: JSONObject) {
                //Here goes the code for processing successful response...
                //Use JSONObject API for processing the results
                //See https://developer.android.com/reference/org/json/JSONObject.html, for more detail
                //Add here code for processing successful response. For example see the code below
                val valueForPasswordPolicyTimeout = jsonObject.getJSONObject("passwordPolicy").getInt("passwordPolicyLockTimeout")
            }

            override fun onError(result: Throwable) {
                //Place your failure handling code here...
                if (result is HttpException) {
                    //HttpException type com.sap.cloud.mobile.foundation.networking.HttpException
                    Log.e("Http Exception: ", result.message() + ", with Error code: " + result.code())
                } else {
                    Log.e("Exception occurred: ", result.message)
                }
            }
    })

Storing Settings

Storing settings is done by calling store method. The store method can be used to create new values or to update existing values.

This method must be invoked from the UI thread. It takes SettingTarget, KeyValue, and the JSON value as parameters. The callback methods are invoked on the UI thread.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
   OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
   SettingsParameters settingsParameters = new SettingsParameters(HCPMS_URL, APPID, ANDROID_ID, "1.0");
   final Settings settings = new Settings(okHttpClient, settingsParameters);

   JSONObject jsonVal = null;
    try {
        jsonVal = new JSONObject("{'appConfig1':'value1', 'appConfig2':'value2'}");
    } catch (JSONException e) {
        //Handle your exception here
    }

    settings.store(Settings.SettingTarget.DEVICE, "customAppDefinedConfigs1", jsonVal,
        new Settings.CallbackListener() {
           @Override
           public void onSuccess(JSONObject o) {
             //Here goes the code for processing successful result
             try {
                    Integer responseCode = o.getInt("code");
                    String  responseMessage = o.getString("message");
                    Log.d("Settings: " , responseMessage +", code: " + responseCode);
                } catch (JSONException je) {
                    Log.e("Exception occurred: " , je.getMessage());
                }
           }

           @Override
           public void onError(Throwable result) {
               //Place your failure handling code here...
               if (result instanceof HttpException) {
                  //HttpException type com.sap.cloud.mobile.foundation.networking.HttpException
                  HttpException ne = (HttpException)result;
                  Log.e("Http Exception: " , ne.message() + ", with Error code: " + ne.code());
               } else {
                    Log.e("Exception occurred: " , result.getMessage());
            }
           }
        }
    );       
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
val okHttpClient = OkHttpClient.Builder().build()
val settingsParameters = SettingsParameters(HCPMS_URL, APPID, ANDROID_ID, "1.0")
val settings = Settings(okHttpClient, settingsParameters)

var jsonVal: JSONObject? = null
try {
    jsonVal = JSONObject("{'appConfig1':'value1', 'appConfig2':'value2'}")
} catch (e: JSONException) {
    //Handle your exception here
}

settings.store(Settings.SettingTarget.DEVICE, "customAppDefinedConfigs1", jsonVal!!,
    object : Settings.CallbackListener {
        override fun onSuccess(o: JSONObject) {
            //Here goes the code for processing successful result
            try {
                val responseCode = o.getInt("code")
                val responseMessage = o.getString("message")
                Log.d("Settings: ", "$responseMessage, code: $responseCode")
            } catch (je: JSONException) {
                Log.e("Exception occurred: ", je.message)
            }
        }

        override fun onError(result: Throwable) {
            //Place your failure handling code here...
            if (result is HttpException) {
                //HttpException type com.sap.cloud.mobile.foundation.networking.HttpException
                Log.e("Http Exception: ", result.message() + ", with Error code: " + result.code())
            } else {
                Log.e("Exception occurred: ", result.message)
            }
        }
    }
)

Deleting Settings

Deleting settings is done using the delete method. Delete is used for settings that usually the mobile application created using the store method. Deletion of settings under the mobileservices key is not allowed. If an attempt to delete any item under mobileservices is done, the onError callback is called with a Throwable object that provides the details of the error.

This method must be invoked from the UI thread. It takes SettingTarget and KeyPath as parameters. The callback methods are invoked on the UI thread.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
   SettingsParameters settingsParameters = new SettingsParameters(HCPMS_URL, APPID, ANDROID_ID, "1.0");
   final Settings settings = new Settings(okHttpClient, settingsParameters);

    settings.delete(Settings.SettingTarget.DEVICE, "customAppDefinedConfigs1/appConfig1",
       new Settings.CallbackListener() {
        {@literal @Override}
           public void onSuccess(JSONObject o) {
           //Here goes the code for processing successful response...
                try {
                    Integer responseCode = o.getInt("code");
                    String  responseMessage = o.getString("message");
                    Log.d("JSONException: ",responseMessage + ", with Error code: " + responseCode);
                } catch (JSONException e) {
                    e.getMessage();
                }
           }

            {@literal @Override}
           public void onError(Throwable result) {
               //Place your failure handling code here...
               if (result instanceof HttpException) {
                   //HttpException type com.sap.cloud.mobile.foundation.networking.HttpException
                  HttpException ne = (HttpException)result;
                  Log.e("Http Exception: " , ne.message() + ", with Error code: " + ne.code());
               } else {
                   Log.e("Exception occurred: ", result.getMessage());
              }
           }

    });
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
val okHttpClient = OkHttpClient.Builder().build()
val settingsParameters = SettingsParameters(HCPMS_URL, APPID, ANDROID_ID, "1.0")
val settings = Settings(okHttpClient, settingsParameters)

settings.delete(Settings.SettingTarget.DEVICE, "customAppDefinedConfigs1/appConfig1",
    object : Settings.CallbackListener {
        override fun onSuccess(o: JSONObject) {
            //Here goes the code for processing successful response...
            try {
                val responseCode = o.getInt("code")
                val responseMessage = o.getString("message")
                Log.d("JSONException: ", "$responseMessage, with Error code: $responseCode")
            } catch (e: JSONException) {
                e.message
            }
        }

        override fun onError(result: Throwable) {
            //Place your failure handling code here...
            if (result is HttpException) {
                //HttpException type com.sap.cloud.mobile.foundation.networking.HttpException
                Log.e("Http Exception: ", result.message() + ", with Error code: " + result.code())
            } else {
                Log.e("Exception occurred: ", result.message)
            }
        }

})

Permissions

It should be noted that the access to settings (read/write/delete) is controlled by the user role permissions set by your mobile services administrator. Please see Storage Service API for more information.