Overview
This guide describes how to use Secure Storage Manager (SSM) for secure deployment of files for configuring Zebra apps and/or sharing data. Files can be deployed for use by other apps (or by the originating app itself) either through Zebra OEMConfig and StageNow, a company's own EMM or programmatically from within an application.
Requirements
- Zebra device(s) running Android 11 (or later)
- Zebra MX 11.3 (or later) on device (Which version is present?)
- A staging tool (e.g. DNA Cloud, OEMConfig, StageNow, etc.)
Process Summary
- Create a Profile in the staging tool for deploying a file.
- Set the Profile to deploy using File Manager "Deploy a file for an application" File Action or the equivalent function.
- Enter the "Target Application File Definition" from the Zebra App Deployment Files table (below) corresponding to the file's Source* app.
- Enter the name of the signature file for the Source app (optional for StageNow deployment).
Zebra recommends using Step 4 for added security. Learn more. - Source Access Method: "File in the Device File System"
- Select Media type on a local Device: "Others"
- Enter File Name: Enter the "Source Path and File Name" for the app from the Zebra App Deployment Files table (below).†
* The "Source" app is the Zebra app originating the file for sharing with others. Note: The source app can be the same app as the one consuming the shared file. For example, this is usually the case when deploying app-configuration files.
† Where appropriate, replace the example file name with the chosen file name.
Also See
- SSM and DataWedge | Secure deployment of files for DataWedge configuration and Profiles
- SSM and WorkStation Connect | Secure deployment of files for Zebra Workstation Connect configuration and shortcuts
Deploy via Application
This section describes how to use SSM to securely deploy a file to a device. A DataWedge Profile is used as an example.
In the app's AndroidManifest.xml
file:
Add the following permissions:
<uses-permission android:name="com.zebra.securestoragemanager.securecontentprovider.PERMISSION.WRITE" /> <uses-permission android:name="com.zebra.securestoragemanager.securecontentprovider.PERMISSION.READ" />
Add the following queries to allow the app to interact with SSM:
<queries> <package android:name="com.zebra.securestoragemanager" /> <provider android:authorities="com.zebra.securestoragemanager.securecontentprovider"/> </queries>
Add the following code to define a FileProvider that allows the app to grant read permissions to files. Replace
com.app.package.name
with the package name of the app.<provider android:name="androidx.core.content.FileProvider" android:authorities="com.your.package.name.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/> </provider>
In the app's project:
In the "xml" subfolder under the "res" parent folder, add a file named
provider_paths.xml
with the following content:<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <root-path path="/data/tmp/public" name="public"/> <root-path path="/enterprise/usr" name="user"/> <external-path path="." name="external_files"/> <files-path path="." name="template"/> </paths>
Create a directory (e.g. ConfigDBs) inside the "assets" folder and copy the DataWedge Profile and/or config file within this folder:
In the app, add a function called
uploadTemplates()
, which copies files from the "assets" directory and uploads them via the copy functioncopyFileViaSSM()
.public void uploadConfigDB(boolean isFullDB) {
} private void integrateFile(AssetManager assetManager, String filename) { InputStream in = null; OutputStream out = null;AssetManager assetManager = getAssets(); String[] files = null; try { files = assetManager.list(ASSET_DB_DIR); } catch (IOException e) { Log.e(TAG, "Failed to get asset file list: " + e.getMessage()); } if (files != null) { for (String filename : files) { if (isFullDB && filename.equals("datawedge.db")) { integrateFile(assetManager, filename); } else if (!isFullDB && filename.startsWith("dwprofile_")) { integrateFile(assetManager, filename); } } } else { Log.d(TAG, "asset file list is null"); }
} private void copyFile(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int read; while ((read = in.read(buffer)) != -1) { out.write(buffer, 0, read); } } public void copyFileViaSSM(String sourcePath, String type) {try { in = assetManager.open(ASSET_DB_DIR + "/" + filename); String outDir = getFilesDir().getAbsolutePath() + "/"; File outFile = new File(outDir, filename); out = new FileOutputStream(outFile); copyFile(in, out); in.close(); out.flush(); out.close(); copyFileViaSSM(outFile.getAbsolutePath(), "config"); } catch (IOException e) { Log.e("tag", "Failed to copy asset file: " + filename, e); }
}File file = new File(sourcePath); Uri contentUri = FileProvider.getUriForFile(this, this.getPackageName() + ".provider", file); this.getApplicationContext().grantUriPermission("com.zebra.securestoragemanager", contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); // Needed to grant permission for SSM to read the uri Uri cpUriQuery = Uri.parse(AUTHORITY_FILE + this.getPackageName()); try { ContentValues values = new ContentValues(); values.put("target_app_package", String.format("{\"pkgs_sigs\": [{\"pkg\":\"%s\",\"sig\":\"%s\"}]}", "com.symbol.datawedge", signature)); values.put("data_name", String.valueOf(contentUri)); // Passes the content uri as a input source values.put("data_type", "3"); values.put("data_value", "com.symbol.datawedge/" + type + "/" + file.getName()); // Replace “targetPath” with the package name of the target app that is accessing the deployed file (or retrieve the app package using context.getPackageName()) followed by "/" and the full path of the file, e.g. "context.getPackageName()/A.txt" values.put("data_persist_required", false); Uri createdRow = this.getContentResolver().insert(cpUriQuery, values); Log.i(TAG, "SSM Insert File: " + createdRow.toString()); } catch (Exception e) { Log.e(TAG, "SSM Insert File - error: " + e.getMessage() + "\n\n"); }
Call the method
uploadConfigDB(boolean isFullDB)
to upload the configuration DB files from the asset folder to DataWedge.- If uploading a full configuration DB, pass "true" for the "isFullDB" parameter
- If uploading a profile DB, pass "false" for the "isFullDB" parameter
Zebra App Deployment Files
Use the values below to deploy, share or consume files between and among Zebra apps on a device.