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 Serial Number, the IMEI number, the Bluetooth Mac Address (and more, see below) of your Zebra device in one method call (see at the end of this document).
Have fun with Zebra's devices :)
DIHelper.getProductModel to retrieve the product model.
DIHelper.getIdentityDeviceID to retrieve the identity device ID.
DIHelper.getWifiMacAddress to retrieve the Wifi Mac Address.
DIHelper.getWifiAPMacAddress to retrieve the Wifi Access Point Mac Address.
DIHelper.getWifiSSID to retrieve the Wifi SSID.
DIHelper.getEthernetMacAddress to retrieve the Ethernet Mac Address if applicable.
See sample App for more information.
https://github.com/ltrudu/DeviceIdentifiersWrapper-Sample
Look for "TODO: MANDATORY FOR DeviceIdentifierWrapper" to find what you need to add to your AndroidManifest.xml and build files.
Added method DIHelper.getBtMacAddress to retrieve device's Bluetooth Mac Address
Added BIND_NOTIFICATION_LISTENER_SERVICE permission
Added com.symbol.emdk.emdkservice to the queries element of the AndroidManifest.xml
Added com.zebra.zebracontentprovider to the queries element of the AndroidManifest.xml
API updated to 33
Added basic cache mechanism.
The IMei and the Serial number will be cached once they get retrieved.
The cache can be reset with the method:
DIHelper.resetCachedValues()
Added a mechanism to wait for the EMDK if it is not available (when responding to the BOOT_COMPLETED event for ex.)
To be tested... feel free to report any issue regarding this feature.
Check the sample for a basic implementation.
Added lots of logs that will be sent to logCat or to the onDebugStatus callback method.
Updated gradle version to release 7.3.3
Update your graddle distribution to >= 7.3.3
update your compileSdkVersion to 30
Update your Manifest.xml file to add the Query element (as explained in this description)
Add jitpack.io repository to the project build.graddle file : maven { url 'https://jitpack.io' }
Update the dependency in the graddle application file: implementation 'com.github.ltrudu:DeviceIdentifiersWrapper:0.3' or replace 0.3 with + to get the latest version automatically
Everything is explained in detail in this documentation.
You can use the sample as a copy/paste source.
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/DeviceIdentifiersWrapper-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 has been added in V0.4 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 Serial Number and the IMEI number of an Android 10+ Zebra device.
How to access device identifiers such as serial number and IMEI on Zebra devices running Android 10
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.
Zebra mobile computers running Android 10 are able to access both the serial number and IMEI 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 10 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">
<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 DeviceIdentifierWrapper dependency to your application build.graddle file:
implementation 'com.github.ltrudu:DeviceIdentifiersWrapper:+'
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:DeviceIdentifiersWrapper:+'
}
Now you can use the following snippet codes to retrieve IMEI number and Serial Number information.
Snippet code to use to retrieve the Serial Number of the device:
private void getSerialNumber(Context context)
{
DIHelper.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)
{
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
}
});
}
Snippet code to use to retrieve the Bluetooth Mac Address of the device:
private void getBTMacAddress(Context context)
{
DIHelper.getBtMacAddress(context, new IDIResultCallbacks() {
@Override
public void onSuccess(String message) {
// We've got the bt mac address
String myBluetoothMacAddress = 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 both information, it is strongly recommended to call the second request inside the onSuccess or onError of the first request.
Sample code if you need to get both device identifiers:
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
}
});
}