Search code examples
androidimeisotimobicontrol

How to read the Android Device IMEI on a SOTI managed device?


We are using Soti Mobicontrol Managed Android devices in production and since the IMEI access has been restricted after Android 10 I was wondering if Soti agent which has access to the Android Enterprise features can provide us the IMEI so we use it as the device unique ID.

By the way, the company owns the devices and I don't believe it is a user privacy violation!


Solution

  • I found a blurry and incomplete answer in the Soti Discussion Forum and after many testing finally, I managed to make it work!!!

    When you create an installation package for an Android APK file using the MobiControl Package Studio tool, you can contain Post-Install Soti Scripts that will run after installation is done:

    enter image description here

    One of the scripts is sendintent and, on the other hand, you also have access to some macros to get the device information namely %IMEI%, or %DEVICENAME% (which is not listed on the macro documentation!).

    It means by defining a script like this you can have a Broadcast Message intent containing the IMEI and Device Name on Soti Managed Devices!

    sendintent -b "intent:#Intent;action=com.mohsenoid.android.imei.ACTION;S.imei=%IMEI%;S.devicename=%DEVICENAME%;component=com.mohsenoid.android.imei/.ImeiReceiver;end;"
    

    This script acts exactly the same as this ADB Shell command:

    adb shell am broadcast -a com.mohsenoid.android.imei.ACTION --es imei "SOME\ IMEI" --es devicename "SOME\ DEVICE\ NAME" -n com.mohsenoid.android.imei/.ImeiReceiver
    

    The BroadcastReceiver inside your app can look something like this:

    class ImeiReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context?, intent: Intent?) {
            context ?: return
            intent ?: return
    
            val imei = intent.getStringExtra(IMEI_KEY) ?: return
            val deviceName = intent.getStringExtra(DEVICE_NAME_KEY) ?: return
    
            AppSettings.setValue(context, IMEI_KEY, imei)
            AppSettings.setValue(context, DEVICE_NAME_KEY, deviceName)
    
            Toast.makeText(context, "Received: IMEI: $imei - DeviceName: $deviceName", Toast.LENGTH_LONG).show()
        }
    
        companion object {
            const val IMEI_KEY = "imei"
            const val DEVICE_NAME_KEY = "devicename"
        }
    }
    

    Do not forget that you also need to add the Broadcast Receiver to your AndroidManifest file with a proper intent filter and action.

    <receiver
        android:name=".ImeiReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="com.mohsenoid.android.imei.ACTION" />
        </intent-filter>
    </receiver>
    

    This GitHub repository holds a test app that can be used for this purpose: https://github.com/mohsenoid/SOTI-IMEI

    I hope this answer helps anyone who is using this service.