Please be aware that this library / application / sample is provided as a community project without any guarantee of support
Forget about StageNow, EMDK, certificates, application signature... complexity....
Just get the OEM Infos of your Zebra device in one method call (see at the end of this document).
Have fun with Zebra's devices :)
Please, take the time to read the OEM Info documentation to see what information you can get.
https://techdocs.zebra.com/oeminfo/consume/
See sample App for a quick implementation of the library.
https://github.com/ltrudu/ZebraOEMInfoWrapper-Sample
Look for "TODO: MANDATORY FOR ZebraOEMInfoWrapper" section of this Readme to find what you need to add to your AndroidManifest.xml to use this wrapper.
Due to usage of the EMDK and the need to register the application, it is strongly advised to call the methods in your application class
Check https://github.com/ltrudu/ZebraOEMInfoWrapper-Sample implementation.
It's a basic implementation using static members.
Feel free to remove statics and replace them with a better code in terms of architecture.
The goal was to pass the idea that theses number should be retrieved only once, and the best place for it is the Application class.
Note that a mechanism is available to wait for the EMDK in case it would not be available (the classic use case is when your app respond to the BOOT_COMPLETED event that occurs way before the EMDK finishes its initialization)
A wrapper to easily retrieve the Zebra's OEM Information of an Android 11+ Zebra device.
How to access these informations on Zebra devices running Android 11
Android 10 limited access to device identifiers for all apps running on the platform regardless of their target API level. As explained in the docs for Android 10 privacy changes this includes the serial number, IMEI and some other identifiable information.
Android 11 and 13 removed more access to these information for security reasons.
Some of them are not available on classic Android OS (Wan information for example, Ethernet Mac Address).
Zebra mobile computers running Android 11 are able to access all these information however applications need to be explicitly granted the ability to do so and use a proprietary API.
To access to this API, you must first register your application using the AccessMgr MX's CSP.
You can do it using StageNow, more details here: https://github.com/darryncampbell/EMDK-DeviceIdentifiers-Sample
Or you can use this wrapper that will automatically register your application if it is necessary.
To use this helper on Zebra Android devices running Android 11 or higher, first declare a new permission in your AndroidManifest.xml
<uses-permission android:name="com.zebra.provider.READ"/>
<uses-permission android:name="com.symbol.emdk.permission.EMDK" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
Then add a query element to retrive the data
<queries>
<provider android:authorities="oem_info" />
<package android:name="com.symbol.emdk.emdkservice" />
<package android:name="com.zebra.zebracontentprovider"/>
</queries>
Then add the uses-library element to your application
<uses-library android:name="com.symbol.emdk" />
Sample AdroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zebra.emdk_deviceidentifiers_sample">
<!--> TODO: Add these permissions to your manifest </-->
<uses-permission android:name="com.zebra.provider.READ"/>
<uses-permission android:name="com.symbol.emdk.permission.EMDK" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
<!--> TODO: Add query element to your manifest </-->
<queries>
<provider android:authorities="oem_info" />
<package android:name="com.symbol.emdk.emdkservice" />
<package android:name="com.zebra.zebracontentprovider"/>
</queries>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--> TODO: Add the uses-library EMDK to your manifest </-->
<uses-library android:name="com.symbol.emdk" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Update your project build.graddle file to add jitpack repository
maven { url 'https://jitpack.io' }
Sample project build.gradle
buildscript {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
google()
maven { url 'https://jitpack.io' }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Finally, add ZebraOEMInfoWrapper dependency to your application build.graddle file:
implementation 'com.github.ltrudu:ZebraOEMInfoWrapper:+'
Sample application build.graddle:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.github.ltrudu:ZebraOEMInfoWrapper:+'
}
- Helper_SecureInfo : Provides access to sensitive information like IMEI, Serial Number, Bluetooth Mac Address, Wifi Mac Address,...
- Helper_OSUpdateInfo : Provides access to information on the status of the current OS update process
- Helper_SoftwareInfo : Provides information on the versions of the softwares installed on the device like OS Baseline, OS Fingerprint, OS Patch version, ZDM Version, MX Version,...
- Helper_WanInfo : Provides information on the Wan config of the current device like Eid, Telephony Sim Operator, CarrierName, IccId, etc...
The full list of available values can be found on the Zebra website: https://techdocs.zebra.com/oeminfo/consume/
Only the values marked as "Varies by Android version" are not implemented.
Feel free to add them and do a pull request on this code if you need them :)
Now you can use the following snippet codes to retrieve OEM information.
Snippet code to use to retrieve the Serial Number of the device:
private void getSerialNumber(Context context)
{
Helper_SecureInfo.getSerialNumber(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// The message contains the serial number
String mySerialNumber = message;
}
@Override
public void onError(String message) {
// An error occurred
}
@Override
public void onDebugStatus(String message) {
// You can use this method to get verbose information
// about what's happening behind the curtain
}
});
}
Snippet code to use to retrieve the IMEI of the device:
private void getIMEINumber(Context context)
{
Helper_SecureInfo.getIMEINumber(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// We've got an EMEI number
String myIMEI = message;
}
@Override
public void onError(String message) {
// An error occurred
}
@Override
public void onDebugStatus(String message) {
// You can use this method to get verbose information
// about what's happening behind the curtain
}
});
}
Snippet code to use to retrieve the MX Version installed on the device:
private void getMXVersion(Context context)
{
Helper_SoftwareInfo.getMX_Version(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// We've got the mx version
String myMXVersion = message;
}
@Override
public void onError(String message) {
// An error occurred
}
@Override
public void onDebugStatus(String message) {
// You can use this method to get verbose information
// about what's happening behind the curtain
}
});
}
Snippet code to use to retrieve the the OS Build Version Security Patch installed on the device:
private void getBuildVersionSecurityPatch(Context context)
{
Helper_SoftwareInfo.getBuild_Version_Security_Patch(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// We've got the build version security patch
String myBuildVersionSecurityPatch = message;
}
@Override
public void onError(String message) {
// An error occurred
}
@Override
public void onDebugStatus(String message) {
// You can use this method to get verbose information
// about what's happening behind the curtain
}
});
}
As the previous methods are asynchronous, if you need more than one information, it is strongly recommended to call the next request inside the onSuccess or onError of the first request.
See implementation of ZebraIdentifiersApplication inside the ZebraOEMInfoWrapper-Sample for a basic chain implementation.
Sample code if you need to get the serial number and the IMEI number of a device:
private void getDevicesIdentifiers(Context context)
{
// We first ask for the SerialNumber
DIHelper.getSerialNumber(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// The message contains the serial number
String mySerialNumber = message;
// We've got the serial number, now we can ask for the IMEINumber
DIHelper.getIMEINumber(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// We've got an EMEI number
String myIMEI = message;
}
@Override
public void onError(String message) {
// An error occurred
}
@Override
public void onDebugStatus(String message) {
// You can use this method to get verbose information
// about what's happening behind the curtain
}
});
}
@Override
public void onError(String message) {
// An error occured
// Do something here with the error message
// We had an error with the Serial Number, but it
// doesn't prevent us from calling the getIMEINumber method
DIHelper.getIMEINumber(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// We've got an EMEI number
String myIMEI = message;
}
@Override
public void onError(String message) {
// An error occurred
}
@Override
public void onDebugStatus(String message) {
// You can use this method to get verbose information
// about what's happening behind the curtain }
});
}
@Override
public void onDebugStatus(String message) {
// You can use this method to get verbose information
// about what's happening behind the curtain
}
});
}
All the methods from all the helpers implement the same mechanism.
You can just copy paste the current snippet and change the helper class and the method call to get the information you need.