I am getting IMEI null in Android Q?
Asked Answered
P

12

78

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

is there any workaround for that?

Population answered 15/3, 2019 at 0:13 Comment(7)
are you trying it on emulator?Zacarias
No. Google Pixel 1. Enrolled hours back and found out that my app is not getting the IMEI numberPopulation
i havent tried android Q but ive read that they are limiting access to non resettable device identifiersZacarias
read this one: developer.android.com/preview/privacy/checklistZacarias
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..Population
I need to access the phone's IMEI as well. Desperately trying to figure out a solution for this.Sharpe
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.Population
I
66

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

Inconsonant answered 9/4, 2019 at 12:8 Comment(7)
What about TelephonyManager.getSubscriberId , which is the only way to use for NetworkStatsManager.queryDetailsForUid ?Conveyor
You are right. source.android.com/devices/tech/config/device-identifiersFredi
We can get the sim serial number and carrier info using TELEPHONY_SUBSCRIPTION_SERVICE ( > Android 5.1) . See my answer below for details.Invisible
This is way better approach and persists after phone factory reset. https://mcmap.net/q/266226/-android-10-imei-no-longer-available-on-api-29-looking-for-alternativesChavez
Could anyone mention how to make a platform or apps with special carrier permissionDoomsday
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 againCollaboration
@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 firebaseClonus
M
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;
}
Misguide answered 12/3, 2020 at 12:5 Comment(2)
This won't cause a problem ? Because Secure.ANDROID_ID is also not recommended by GoogleXavierxaviera
will it change if the software got updated?Encumber
C
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);
Cilka answered 19/7, 2019 at 5:38 Comment(4)
android studio alert is here: Using getString to get device identifiers is not recommended. developer.android.com/training/articles/user-data-ids.htmlFredi
what is the best way for getting a unique id? @FrediSensible
what do u mean by "try to get a unique id". This try will always fail for non-system apps. right?Okay
@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"Cilka
Z
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 :)

Zarf answered 15/7, 2020 at 9:7 Comment(1)
Settings.Secure.ANDROID_ID is not an IMEI numberCranio
T
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();

Thundering answered 30/9, 2019 at 8:49 Comment(3)
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 developer.android.com/training/articles/user-data-ids#javaThundering
what's the way to detect a specific App even after app reinstalls?Moorish
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 developer.android.com/training/articles/user-data-ids#javaThundering
P
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);
Pilcher answered 8/11, 2019 at 5:16 Comment(4)
@MalwinderSinghM no need hardware permissions,seach as IMEI and it's The only one.Pilcher
@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.Steppe
Better add "Time of first app launch", would be vey uniqueOkay
I have read that tt'll be the same on identical devices from the same carrier, do You have posibility to check that?Duplet
I
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

Invisible answered 2/1, 2020 at 9:19 Comment(4)
This shouldn't work. getSimSerialNumber should also have been moved from READ_PHONE_STATE to READ_PRIVELEGED_PHONE_STATE per developer.android.com/about/versions/10/privacy/…Rhaetia
@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 <Lollipop MR1)Invisible
It works for me too on android Q. Very odd indeed though, I wonder if the android team overlooked this ...Embank
In some cases, the sim serial number will be an empty string.Sowers
C
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);
Changeup answered 20/12, 2019 at 11:11 Comment(1)
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.Duplet
E
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);
            }
        }
Entrepreneur answered 12/3, 2020 at 8:14 Comment(0)
B
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

Bali answered 28/6, 2019 at 13:36 Comment(1)
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.Singles
H
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.

Hypothesis answered 18/10, 2019 at 7:35 Comment(0)
B
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

Bob answered 19/2, 2020 at 15:40 Comment(5)
Hello Joel, Can you please provide more information on this. I'm trying but still unable to get the IMEI.Federate
Hello Yusuph, what is your problem? What version of Android are you using?Bob
I am using Android 10Federate
But what is your problem? Why is not working? Can you put a log or something like a log? I tested in many devices and it workedBob
I have installed test DPC -> now what are the steps i should followBahadur

© 2022 - 2024 — McMap. All rights reserved.