77

I am getting the IMEI ID null from the telephonymanager. What to do?

is there any workaround for that?

Aman Verma
  • 3,155
  • 7
  • 30
  • 60
  • 1
    are you trying it on emulator? – Lorence Hernandez Mar 15 '19 at 00:31
  • 1
    No. Google Pixel 1. Enrolled hours back and found out that my app is not getting the IMEI number – Aman Verma Mar 15 '19 at 00:32
  • 1
    i havent tried android Q but ive read that they are limiting access to non resettable device identifiers – Lorence Hernandez Mar 15 '19 at 00:39
  • 1
    read this one: https://developer.android.com/preview/privacy/checklist – Lorence Hernandez Mar 15 '19 at 00:44
  • 3
    The thing is I am using IMEI for fraud detection. The alternate, like ANDROID_ID is not 100% reliable. I need something which is unique to the device in order to blacklist the device.. – Aman Verma Mar 15 '19 at 01:15
  • I need to access the phone's IMEI as well. Desperately trying to figure out a solution for this. – falkon21 Mar 19 '20 at 11:58
  • 2
    I am afraid there is no alternate for getting the IMEI prior to Android 10. You can have any other unique ID. It totally depends upon your use-case. If you want to track the unique devices, you can use ANDROID_ID which is different for different Package Name from Android 27 and unique for each device below 27. – Aman Verma Mar 19 '20 at 12:03

12 Answers12

65

Android Q has restricted to access for both IMEI and serial no. It is available only for platform and apps with special carrier permission. Also the permission READ_PRIVILEGED_PHONE_STATE is not available for non platform apps.

If you try to access it throws below exception

java.lang.SecurityException: getImeiForSlot: The user 10180 does not meet the requirements to access device identifiers.

Please refer documentation: https://developer.android.com/preview/privacy/data-identifiers#device-ids

Also refer Issue

takharsh
  • 2,258
  • 1
  • 21
  • 26
  • 1
    What about `TelephonyManager.getSubscriberId` , which is the only way to use for `NetworkStatsManager.queryDetailsForUid` ? – android developer Jun 10 '19 at 23:41
  • You are right. https://source.android.com/devices/tech/config/device-identifiers – zakjma Oct 10 '19 at 10:31
  • 1
    We can get the sim serial number and carrier info using TELEPHONY_SUBSCRIPTION_SERVICE ( > Android 5.1) . See my answer below for details. – Adarsh Chithran Jan 22 '20 at 12:37
  • This is way better approach and persists after phone factory reset. https://stackoverflow.com/a/59050182/675734 – gerfmarquez Feb 28 '20 at 23:24
  • 6
    Could anyone mention how to make a platform or apps with special carrier permission – Arul May 28 '20 at 06:24
  • 1
    in doc they says we can get imei if we have Admin Previllages but I am unable to success in it and also ANDROID_ID is not unique I dont know why it changes again and again – Ahmad Dec 29 '20 at 12:13
  • 2
    @ArulMani without trying it, but i guess there is no generic way to do so. You would need to root your device and grant root permissions to the app or flash the app to a custom rom or something. In general try to avoid these personalized data and create an anonymous unique id either on your own or by using firebase – Hatzen Feb 19 '21 at 22:47
25

I am late to post answer. I still believe my answer will help someone. Android 10 Restricted developer to Access IMEI number.

You can have a alternate solution by get Software ID. You can use software id as a unique id. Please find below code as i use in Application.

public static String getDeviceId(Context context) {

 String deviceId;

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        deviceId = Settings.Secure.getString(
                context.getContentResolver(),
                Settings.Secure.ANDROID_ID);
    } else {
        final TelephonyManager mTelephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (mTelephony.getDeviceId() != null) {
            deviceId = mTelephony.getDeviceId();
        } else {
            deviceId = Settings.Secure.getString(
                    context.getContentResolver(),
                    Settings.Secure.ANDROID_ID);
        }
    }

    return deviceId;
}
Satish
  • 527
  • 6
  • 13
15

This just would not work as of Android Q. Third party apps can not use IMEI nor the serial number of a phone and other non-resettable device identifiers.

The only permissions that are able to use those is READ_PRIVILEGED_PHONE_STATE and that cannot be used by any third party apps - Manufacture and Software Applications. If you use that method you will get an error Security exception or get null .

You can still try to get a unique id by using:

import android.provider.Settings.Secure;

private String android_id = Secure.getString(getContext().getContentResolver(),Secure.ANDROID_ID);
Luís Gonçalves
  • 338
  • 5
  • 17
Aditya Bhawsar
  • 156
  • 1
  • 2
  • 8
  • android studio alert is here: `Using getString to get device identifiers is not recommended.` https://developer.android.com/training/articles/user-data-ids.html – zakjma Oct 10 '19 at 10:34
  • what is the best way for getting a unique id? @zakjma – Amin Pinjari Oct 25 '19 at 11:20
  • what do u mean by "try to get a unique id". This try will always fail for non-system apps. right? – M. Usman Khan Jan 02 '20 at 16:39
  • @M.UsmanKhan no this would not fail as you are getting "AndroidId" here not "IMEI" there is no work around for "IMEI" number starting from Api level "29" – Aditya Bhawsar Oct 20 '20 at 14:23
10

The best way to get the IMEI number is as follows:

    public static String getIMEIDeviceId(Context context) {

        String deviceId;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
        {
            deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        } else {
            final TelephonyManager mTelephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (context.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                    return "";
                }
            }
            assert mTelephony != null;
            if (mTelephony.getDeviceId() != null)
            {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                {
                    deviceId = mTelephony.getImei();
                }else {
                    deviceId = mTelephony.getDeviceId();
                }
            } else {
                deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            }
        }
        Log.d("deviceId", deviceId);
        return deviceId;
    }

Just copy the method and use it. It will definitely. However, you might know you can't get IMEI in android Q (version 10). In this code, you can get a unique identifier (alternative id) through any device or any API level. It works 100% Thank You!! And Enjoy Coding :)

Vijay
  • 1,163
  • 8
  • 22
Technical Rival
  • 109
  • 1
  • 3
8

As the best practices suggest. " you can avoid using hardware identifiers, such as SSAID (Android ID) and IMEI, without limiting required functionality."

Rather go for an instance ID such as String uniqueID = UUID.randomUUID().toString(); or FirebaseInstanceId.getInstance().getId();

Joe Malebe
  • 614
  • 5
  • 6
  • 2
    Users may want to reset their preferences by reinstalling the app, therefore persisting information through app reinstalls is not best practice. That's why using hardware ID's is not recommended because they are scoped to the device and the user cannot reset them. An app scoped ID is sufficient in most cases. See best practices https://developer.android.com/training/articles/user-data-ids#java – Joe Malebe Oct 16 '19 at 04:26
  • what's the way to detect a specific App even after app reinstalls? – ruben Jan 09 '20 at 17:16
  • 1
    I suppose it would depend on the use case. As stated above, persisting user ID's after app reinstalls is not recommended as because the users are then subject to long term tracking and they cannot reset them. This article provides solutions for different use cases https://developer.android.com/training/articles/user-data-ids#java – Joe Malebe Jan 17 '20 at 05:55
7

you can change other way, i use uuid to replace devices id.

 String uniquePseudoID = "35" +
            Build.BOARD.length() % 10 +
            Build.BRAND.length() % 10 +
            Build.DEVICE.length() % 10 +
            Build.DISPLAY.length() % 10 +
            Build.HOST.length() % 10 +
            Build.ID.length() % 10 +
            Build.MANUFACTURER.length() % 10 +
            Build.MODEL.length() % 10 +
            Build.PRODUCT.length() % 10 +
            Build.TAGS.length() % 10 +
            Build.TYPE.length() % 10 +
            Build.USER.length() % 10;
    String serial = Build.getRadioVersion();
    String uuid = new UUID(uniquePseudoID.hashCode(), serial.hashCode()).toString();
    AppLog.d("Device ID",uuid);
Ven Ren
  • 1,584
  • 1
  • 13
  • 24
  • @MalwinderSinghM no need hardware permissions,seach as IMEI and it's The only one. – Ven Ren Dec 13 '19 at 11:31
  • @VenRen, Is the uniquePseudoID enough as a replacement for the imei or there will be a chance the uniquePseudoID will be the same to other phones especially identical phones. – Flux Jan 27 '20 at 02:59
  • 1
    Better add "Time of first app launch", would be vey unique – M. Usman Khan Mar 09 '20 at 05:10
  • I have read that tt'll be the same on identical devices from the same carrier, do You have posibility to check that? – Piotr Żak Jan 07 '21 at 09:03
7

Not sure about IMEI number, but you can get the simSerialNumber and other carrier info this way.

getSimSerialNumber() needs privileged permissions from Android 10 onwards, and third party apps can't register this permission.

See : https://developer.android.com/about/versions/10/privacy/changes#non-resettable-device-ids

A possible solution is to use the TELEPHONY_SUBSCRIPTION_SERVICE from Android 5.1, to retrieve the sim serial number. Steps below:

  • Check for READ_PHONE_STATE permission.
  • Get Active subscription list.( Returns the list of all active sim cards)
  • Retrieve the sim details from Subscription Object.

       if ( isPermissionGranted(READ_PHONE_STATE) ) {
    
            String simSerialNo="";
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
    
                SubscriptionManager subsManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 
    
                List<SubscriptionInfo> subsList = subsManager.getActiveSubscriptionInfoList();
    
                if (subsList!=null) {
                    for (SubscriptionInfo subsInfo : subsList) {
                        if (subsInfo != null) {
                            simSerialNo  = subsInfo.getIccId();
                        }
                    }
                }
            } else {
                TelephonyManager tMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                simSerialNo = tMgr.getSimSerialNumber();
            }
        }
    

Check if this helps

Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
Adarsh Chithran
  • 218
  • 3
  • 6
  • This shouldn't work. getSimSerialNumber should also have been moved from READ_PHONE_STATE to READ_PRIVELEGED_PHONE_STATE per https://developer.android.com/about/versions/10/privacy/changes#non-resettable-device-ids – Mike Stanley Jan 23 '20 at 00:16
  • 1
    @Mike This is tested and works well. getSimSerialNumber is out in the else block and will only be executed for devices < lollipop MR1. ( because telephony subscription service was introduxed from that verison). And getSimSerialNumber permission was moved only from Android 10 and higher. So it works fine for older versions ( here – Adarsh Chithran Jan 23 '20 at 17:14
  • It works for me too on android Q. Very odd indeed though, I wonder if the android team overlooked this ... – Jakob Harteg Apr 02 '20 at 17:44
  • In some cases, the sim serial number will be an empty string. – Abhijith Brumal Feb 15 '22 at 07:27
6

If your app targets Android 10 or higher, a SecurityException occurs.

Following modules are affected...

Build
    getSerial()
TelephonyManager
    getImei()
    getDeviceId()
    getMeid()
    getSimSerialNumber()
    getSubscriberId()

So you cant get IMEI no for android 10 , You have to used another unique identifier for this like Android ID

It unique 64 bit hex no for device

private String android_id = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID);

rawhost
  • 144
  • 1
  • 6
  • 3
    What You need to know is that ANDROID_ID is unique to each combination of app-signing key, user, and device. Values of ANDROID_ID are scoped by signing key and user. The value may change if a factory reset is performed on the device or if an APK signing key changes. – Piotr Żak Jan 07 '21 at 09:10
4

According to google docs.

Restriction on non-resettable device identifiers

Starting in Android 10, apps must have the READ_PRIVILEGED_PHONE_STATE privileged permission in order to access the device's non-resettable identifiers, which include both IMEI and serial number.

Caution: Third-party apps installed from the Google Play Store cannot declare privileged permissions.

So, Instead of imei you can get Android unique ID.

        String imei = "";
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                if (telephonyManager != null) {
                    try {
                        imei = telephonyManager.getImei();
                    } catch (Exception e) {
                        e.printStackTrace();
                        imei = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
                    }
                }
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_PHONE_STATE}, 1010);
            }
        } else {
            if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                if (telephonyManager != null) {
                    imei = telephonyManager.getDeviceId();
                }
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_PHONE_STATE}, 1010);
            }
        }
Ahsan
  • 131
  • 2
  • 3
3

Targeting Android Q, third party apps can't access IMEI at all. Android Q doc is misleading while stating

Starting in Android Q, apps must have the READ_PRIVILEGED_PHONE_STATE privileged permission in order to access the device's non-resettable identifiers, which include both IMEI and serial number. https://developer.android.com/preview/privacy/data-identifiers#device-ids

But when I actually tried to implement it, I am receiving this exception:

java.lang.SecurityException: getDeviceId: The user 10132 does not meet the requirements to access device identifiers.

Someone had reported this on google's issue tracker where a Googler said that this is intended behaviour and IMEI on Q+ is only available for system level apps.

Status: Won't Fix (Intended Behavior) This is Working As Intended. IMEI is a personal identifier and this is not given out to apps as a matter of policy. There is no workaround.

https://issuetracker.google.com/issues/129583175#comment10

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
Yousuf Sohail
  • 579
  • 5
  • 19
  • 4
    The docs you linked states also `Caution: Third-party apps installed from the Google Play Store cannot declare privileged permissions.`. So, only system apps can get the permission. It is still accessible for users with root, though. – Zaffy Jul 23 '19 at 15:52
1

They mentioned: If your app is the device or profile owner app, you need only the READ_PHONE_STATE permission to access non-resettable device identifiers, even if your app targets Android 10 or higher.

I tried deploying via EMM as device owner app but not success.

0

If you needed, you can try to install a work profile in to the mobile phone and include your app in the same package or vice versa.

I tried and it works, it's simple if yo follow this repo: https://github.com/googlesamples/android-testdpc

When you install the Work Profile your app is installed in this profile and you will have acces to the IMEI.

And now there is another example fixed yesterday to Android 10: https://github.com/android/enterprise-samples/pull/29

Joel Garcia
  • 61
  • 1
  • 12