Secure Storage Manager 1.0


This section provides the Content Provider Interface APIs for Secure Storage Manager (SSM).

Content Provider Interface APIs

Action Method
Add new data.
See Android reference.
Uri insert (Uri uri, ContentValues values)
Modify/Update existing data.
See Android reference.
int update (Uri uri, ContentValues values, String selection, String[] selectionArgs)
Return data based on selection criteria.
See Android reference.
Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
Delete data.
int delete (Uri uri, String selection, String[] selectionArgs)

Content Provider parameters:

Key Value Mandatory/Optional
target_app_package Package name and signature of the target app in a json array. Multiple target apps and signatures can also be given in a json array. The signature must be provided in Base64 format. To generate the signature of any APK, See Get the signature of an Android APK. Mandatory
data_name Unique name to identify data. Mandatory
data_value Any data (string or json). Mandatory
data_persist_required ASet whether persistence is required after Enterprise Reset (true/false). Mandatory
data_input_form Set whether data received should be encrypted:
plaintext =1, encrypted=2
data_output_form Set whether data passed to the intended recipient should be encrypted.:
plaintext =1, encrypted=2


  • Querying persistent data after reboot could be delayed until the system is completely initialized.
  • Querying persistent data could be slower than non-persistent data, since SSM stores persistent data in a device-persistent location.
  • Data names (data_name) cannot be duplicated in the same application when inserting data. If an app tries to insert a duplicate data name, it throws a Duplicate Data Name exception.
  • Apps can store data only up to 10 KB in a single record. If any single data record is larger than 10 KB, it must be split and stored as multiple records with unique data names.

Get the Android APK signature

To generate the signature (signing certificate) of any APK:

  1. Go to the Zebra App Signature Tool page.

  2. Follow instructions for downloading and using the tool.

  3. Use the command below (adapt as needed)

    Java -jar SigTools.jar GetCert -INFORM APK -OUTFORM BASE64 -IN Client.apk -OUTFILE Client.txt


  • “Client.apk” represents the app for which a signature is obtained.
  • Signature (as a Base64 format string) is saved as “Client.txt” in the example.
  • Contents of “Client.txt” can be copied as the target-package app signature.
  • If a signature must be read from a file, rename “Client.txt” to “packageName.txt” (substitute “packageName” with that of the target app) and place the file in the /assets directory on the device.

Sample Code

Insert / Update Data in a Single App

Sample code to securely insert data in plain text:

    private String TARGET_APP_PACKAGE = "target_app_package";
    private String DATA_NAME = "data_name";
    private String DATA_VALUE = "data_value";
    private String DATA_INPUT_FORM = "data_input_form";
    private String DATA_OUTPUT_FORM = "data_output_form";
    private String DATA_PERSIST_REQUIRED = "data_persist_required";
    private String MULTI_INSTANCE_REQUIRED = "multi_instance_required";

    AUTHORITY = "content://com.zebra.securestoragemanager.securecontentprovider/data";
    Uri cpUri = Uri.parse(AUTHORITY);
    ContentValues values = new ContentValues();

    // TARGET_APP_PACKAGE gives both package name info and signature info in single entry. This can be either single target app or even multiple target apps.

            "{\"pkgs_sigs\": [{\"pkg\":\"com.ztestapp.clientapplication\",\"sig\":\"ABSFFSDF… WREWED\"}]}");

    // Dummy sig is placed here. use SigTool to get this base64 String.

    values.put(DATA_NAME, “unique name to identify data in UTF-8 encoded format"); 
    values.put(DATA_VALUE, “any string data/json data"); 
    values.put(DATA_INPUT_FORM, "1"); //plaintext =1, encrypted=2
    values.put(DATA_OUTPUT_FORM, "1"); //plaintext=1, encrypted=2, keystrokes=3
    values.put(DATA_PERSIST_REQUIRED, "false");
    values.put(MULTI_INSTANCE_REQUIRED, "false");        
    values.put(AUTO_DELETE_REQUIRED, "false");

    Uri createdRow = getContentResolver().insert(cpUri, values);

    Log.d(TAG, "Created row: " + createdRow.toString());

The return URI provides the URI of the newly inserted row.

Insert / Update Data in Multiple Apps

Sample code to insert the package name and signature of all target apps as a json array in the content values object, which must then be passed to the Insert/Update method:

    //Code snippet - single app support:


    //Code snippet - multiple app support:

    values.put(COLUMN_TARGET_APP_PACKAGE, "{\"pkgs_sigs\":[

The return URI provides the number of rows updated.


Sample code to return the package name and other parameter data:

    Uri cpUriQuery = Uri.parse(AUTHORITY + "/[com.ztestapp.clientapplication]");

    String selection = "target_app_package = '" + packageName + "'" +"AND "+ "data_persist_required = '" + "false" + "'" +
            "AND "+"multi_instance_required = '"+ "true" + "'";
    Cursor cursor = null;

    try {
        cursor = getContentResolver().query(cpUriQuery, null, selection, null, null);
    } catch (Exception e) {
        Log.d(TAG, "Error: "+ e.getMessage());
    // Then traverse the cursor object to get the required field values using the standard Android method. Not shown here. 

Limitation: When querying data from persistent storage (i.e data_persist_required = true), large data sets are not supported due to Android parcel size limitations. “TransactionTooLargeException” is encountered if the query result data size is too large.


Sample code to delete the package name and other parameter data:

    Uri cpUriDelete = Uri.parse(AUTHORITY + "/[com.ztestapp.clientapplication]");

    String whereClause = "target_app_package = '" + packageName + "'" +"AND "+ "data_persist_required = '" + "false" + "'" +
            "AND "+"multi_instance_required = '"+ "true" + "'";

    int rowsDeleted = getContentResolver().delete(cpUriDelete, whereClause , null);

See also: