How to get the device's IMEI/ESN programmatically in android? - android

To identify each devices uniquely I would like to use the IMEI (or ESN number for CDMA devices). How to access this programmatically?

You want to call android.telephony.TelephonyManager.getDeviceId().
This will return whatever string uniquely identifies the device (IMEI on GSM, MEID for CDMA).
You'll need the following permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
in order to do this.
That being said, be careful about doing this. Not only will users wonder why your application is accessing their telephony stack, it might be difficult to migrate data over if the user gets a new device.
Update: As mentioned in the comments below, this is not a secure way to authenticate users, and raises privacy concerns. It is not recommended. Instead, look at the Google+ Login API if you want to implement a frictionless login system.
The Android Backup API is also available if you just want a lightweight way to persist a bundle of strings for when a user resets their phone (or buys a new device).

In addition to the answer of Trevor Johns, you can use this as follows:
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.getDeviceId();
And you should add the following permission into your Manifest.xml file:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
In emulator, you'll probably get a like a "00000..." value. getDeviceId() returns NULL if device ID is not available.

I use the following code to get the IMEI or use Secure.ANDROID_ID as an alternative, when the device doesn't have phone capabilities:
/**
* Returns the unique identifier for the device
*
* #return unique identifier for the device
*/
public String getDeviceIMEI() {
String deviceUniqueIdentifier = null;
TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
if (null != tm) {
deviceUniqueIdentifier = tm.getDeviceId();
}
if (null == deviceUniqueIdentifier || 0 == deviceUniqueIdentifier.length()) {
deviceUniqueIdentifier = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
}
return deviceUniqueIdentifier;
}

Or you can use the ANDROID_ID setting from Android.Provider.Settings.System (as described here strazerre.com).
This has the advantage that it doesn't require special permissions but can change if another application has write access and changes it (which is apparently unusual but not impossible).
Just for reference here is the code from the blog:
import android.provider.Settings;
import android.provider.Settings.System;
String androidID = System.getString(this.getContentResolver(),Secure.ANDROID_ID);
Implementation note: if the ID is critical to the system architecture you need to be aware that in practice some of the very low end Android phones & tablets have been found reusing the same ANDROID_ID (9774d56d682e549c was the value showing up in our logs)

From: http://mytechead.wordpress.com/2011/08/28/how-to-get-imei-number-of-android-device/:
The following code helps in obtaining IMEI number of android devices :
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String device_id = tm.getDeviceId();
Permissions required in Android Manifest:
android.permission.READ_PHONE_STATE
NOTE: In case of tablets or devices which can’t act as Mobile Phone
IMEI will be null.

to get IMEI (international mobile equipment identifier)
public String getIMEI(Activity activity) {
TelephonyManager telephonyManager = (TelephonyManager) activity
.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getDeviceId();
}
to get device unique id
public String getDeviceUniqueID(Activity activity){
String device_unique_id = Secure.getString(activity.getContentResolver(),
Secure.ANDROID_ID);
return device_unique_id;
}

For Android 6.0+ the game has changed so i suggest you use this;
The best way to go is during runtime else you get permission errors.
/**
* A loading screen after AppIntroActivity.
*/
public class LoadingActivity extends BaseActivity {
private static final int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 0;
private TextView loading_tv2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loading);
//trigger 'loadIMEI'
loadIMEI();
/** Fading Transition Effect */
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
/**
* Called when the 'loadIMEI' function is triggered.
*/
public void loadIMEI() {
// Check if the READ_PHONE_STATE permission is already available.
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// READ_PHONE_STATE permission has not been granted.
requestReadPhoneStatePermission();
} else {
// READ_PHONE_STATE permission is already been granted.
doPermissionGrantedStuffs();
}
}
/**
* Requests the READ_PHONE_STATE permission.
* If the permission has been denied previously, a dialog will prompt the user to grant the
* permission, otherwise it is requested directly.
*/
private void requestReadPhoneStatePermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// For example if the user has previously denied the permission.
new AlertDialog.Builder(LoadingActivity.this)
.setTitle("Permission Request")
.setMessage(getString(R.string.permission_read_phone_state_rationale))
.setCancelable(false)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//re-request
ActivityCompat.requestPermissions(LoadingActivity.this,
new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
})
.setIcon(R.drawable.onlinlinew_warning_sign)
.show();
} else {
// READ_PHONE_STATE permission has not been granted yet. Request it directly.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
}
/**
* Callback received when a permissions request has been completed.
*/
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == MY_PERMISSIONS_REQUEST_READ_PHONE_STATE) {
// Received permission result for READ_PHONE_STATE permission.est.");
// Check if the only required permission has been granted
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// READ_PHONE_STATE permission has been granted, proceed with displaying IMEI Number
//alertAlert(getString(R.string.permision_available_read_phone_state));
doPermissionGrantedStuffs();
} else {
alertAlert(getString(R.string.permissions_not_granted_read_phone_state));
}
}
}
private void alertAlert(String msg) {
new AlertDialog.Builder(LoadingActivity.this)
.setTitle("Permission Request")
.setMessage(msg)
.setCancelable(false)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do somthing here
}
})
.setIcon(R.drawable.onlinlinew_warning_sign)
.show();
}
public void doPermissionGrantedStuffs() {
//Have an object of TelephonyManager
TelephonyManager tm =(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
//Get IMEI Number of Phone //////////////// for this example i only need the IMEI
String IMEINumber=tm.getDeviceId();
/************************************************
* **********************************************
* This is just an icing on the cake
* the following are other children of TELEPHONY_SERVICE
*
//Get Subscriber ID
String subscriberID=tm.getDeviceId();
//Get SIM Serial Number
String SIMSerialNumber=tm.getSimSerialNumber();
//Get Network Country ISO Code
String networkCountryISO=tm.getNetworkCountryIso();
//Get SIM Country ISO Code
String SIMCountryISO=tm.getSimCountryIso();
//Get the device software version
String softwareVersion=tm.getDeviceSoftwareVersion()
//Get the Voice mail number
String voiceMailNumber=tm.getVoiceMailNumber();
//Get the Phone Type CDMA/GSM/NONE
int phoneType=tm.getPhoneType();
switch (phoneType)
{
case (TelephonyManager.PHONE_TYPE_CDMA):
// your code
break;
case (TelephonyManager.PHONE_TYPE_GSM)
// your code
break;
case (TelephonyManager.PHONE_TYPE_NONE):
// your code
break;
}
//Find whether the Phone is in Roaming, returns true if in roaming
boolean isRoaming=tm.isNetworkRoaming();
if(isRoaming)
phoneDetails+="\nIs In Roaming : "+"YES";
else
phoneDetails+="\nIs In Roaming : "+"NO";
//Get the SIM state
int SIMState=tm.getSimState();
switch(SIMState)
{
case TelephonyManager.SIM_STATE_ABSENT :
// your code
break;
case TelephonyManager.SIM_STATE_NETWORK_LOCKED :
// your code
break;
case TelephonyManager.SIM_STATE_PIN_REQUIRED :
// your code
break;
case TelephonyManager.SIM_STATE_PUK_REQUIRED :
// your code
break;
case TelephonyManager.SIM_STATE_READY :
// your code
break;
case TelephonyManager.SIM_STATE_UNKNOWN :
// your code
break;
}
*/
// Now read the desired content to a textview.
loading_tv2 = (TextView) findViewById(R.id.loading_tv2);
loading_tv2.setText(IMEINumber);
}
}
Hope this helps you or someone.

As in API 26 getDeviceId() is depreciated so you can use following code to cater API 26 and earlier versions
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String imei="";
if (android.os.Build.VERSION.SDK_INT >= 26) {
imei=telephonyManager.getImei();
}
else
{
imei=telephonyManager.getDeviceId();
}
Don't forget to add permission requests for READ_PHONE_STATE to use the above code.
UPDATE:
From Android 10 its is restricted for user apps to get non-resettable hardware identifiers like IMEI.

New Update:
For Android Version 6 And Above, WLAN MAC Address has been deprecated , follow Trevor Johns answer
Update:
For uniquely Identification of devices, You can Use Secure.ANDROID_ID.
Old Answer:
Disadvantages of using IMEI as Unique Device ID:
IMEI is dependent on the Simcard slot of the device, so it is not
possible to get the IMEI for the devices that do not use Simcard.
In Dual sim devices, we get 2 different IMEIs for the same device as it has 2 slots for simcard.
You can Use The WLAN MAC Address string (Not Recommended For Marshmallow and Marshmallow+ as WLAN MAC Address has been deprecated on Marshmallow forward. So you'll get a bogus value)
We can get the Unique ID for android phones using the WLAN MAC address also. The MAC address is unique for all devices and it works for all kinds of devices.
Advantages of using WLAN MAC address as Device ID:
It is unique identifier for all type of devices (smart phones and
tablets).
It remains unique if the application is reinstalled
Disadvantages of using WLAN MAC address as Device ID:
Give You a Bogus Value from Marshmallow and above.
If device doesn’t have wifi hardware then you get null MAC address,
but generally it is seen that most of the Android devices have wifi
hardware and there are hardly few devices in the market with no wifi
hardware.
SOURCE : technetexperts.com

The method getDeviceId() of TelephonyManager returns the unique device ID, for example, the IMEI for GSM and the MEID or ESN for CDMA phones. Return null if device ID is not available.
Java Code
package com.AndroidTelephonyManager;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.widget.TextView;
public class AndroidTelephonyManager extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView textDeviceID = (TextView)findViewById(R.id.deviceid);
//retrieve a reference to an instance of TelephonyManager
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
textDeviceID.setText(getDeviceID(telephonyManager));
}
String getDeviceID(TelephonyManager phonyManager){
String id = phonyManager.getDeviceId();
if (id == null){
id = "not available";
}
int phoneType = phonyManager.getPhoneType();
switch(phoneType){
case TelephonyManager.PHONE_TYPE_NONE:
return "NONE: " + id;
case TelephonyManager.PHONE_TYPE_GSM:
return "GSM: IMEI=" + id;
case TelephonyManager.PHONE_TYPE_CDMA:
return "CDMA: MEID/ESN=" + id;
/*
* for API Level 11 or above
* case TelephonyManager.PHONE_TYPE_SIP:
* return "SIP";
*/
default:
return "UNKNOWN: ID=" + id;
}
}
}
XML
<linearlayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
<textview android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="#string/hello">
<textview android:id="#+id/deviceid" android:layout_height="wrap_content" android:layout_width="fill_parent">
</textview></textview></linearlayout>
Permission Required
READ_PHONE_STATE in manifest file.

You can use this TelephonyManager TELEPHONY_SERVICE function to get unique device ID,
Requires Permission: READ_PHONE_STATE
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Example, the IMEI for GSM and the MEID or ESN for CDMA phones.
/**
* Gets the device unique id called IMEI. Sometimes, this returns 00000000000000000 for the
* rooted devices.
**/
public static String getDeviceImei(Context ctx) {
TelephonyManager telephonyManager = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getDeviceId();
}
Return null if device ID is not available.

Try this(need to get first IMEI always)
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(LoginActivity.this,Manifest.permission.READ_PHONE_STATE)!= PackageManager.PERMISSION_GRANTED) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mTelephony.getPhoneCount() == 2) {
IME = mTelephony.getImei(0);
}else{
IME = mTelephony.getImei();
}
}else{
if (mTelephony.getPhoneCount() == 2) {
IME = mTelephony.getDeviceId(0);
} else {
IME = mTelephony.getDeviceId();
}
}
} else {
IME = mTelephony.getDeviceId();
}

Use below code gives you IMEI number:
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
System.out.println("IMEI::" + telephonyManager.getDeviceId());

The method getDeviceId() is deprecated.
There a new method for this getImei(int)
Check here

You'll need the following permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
To get IMEI (international mobile equipment identifier) and if It is above API level 26 then we get telephonyManager.getImei() as null so for that, we use ANDROID_ID as a Unique Identifier.
public static String getIMEINumber(#NonNull final Context context)
throws SecurityException, NullPointerException {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imei;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
assert tm != null;
imei = tm.getImei();
//this change is for Android 10 as per security concern it will not provide the imei number.
if (imei == null) {
imei = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
} else {
assert tm != null;
if (tm.getDeviceId() != null && !tm.getDeviceId().equals("000000000000000")) {
imei = tm.getDeviceId();
} else {
imei = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
}
return imei;
}

For Android 10 Following code is working for me.
val uid: String = Settings.Secure.getString(ctx.applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
if (ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
imei = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
uid
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
telephonyManager.imei
}
else -> {
telephonyManager.deviceId
}
}
}

for API Level 11 or above:
case TelephonyManager.PHONE_TYPE_SIP:
return "SIP";
TelephonyManager tm= (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
textDeviceID.setText(getDeviceID(tm));

Kotlin Code for getting DeviceId ( IMEI ) with handling permission & comparability check for all android versions :
val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED) {
// Permission is granted
val imei : String? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) telephonyManager.imei
// older OS versions
else telephonyManager.deviceId
imei?.let {
Log.i("Log", "DeviceId=$it" )
}
} else { // Permission is not granted
}
Also add this permission to AndroidManifest.xml :
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- IMEI-->

use below code:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String[] permissions = {Manifest.permission.READ_PHONE_STATE};
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, READ_PHONE_STATE);
}
} else {
try {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
String imei = telephonyManager.getDeviceId();
} catch (Exception e) {
e.printStackTrace();
}
}
And call onRequestPermissionsResult method following code:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case READ_PHONE_STATE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
try {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
String imei = telephonyManager.getDeviceId();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Add following permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

For those looking for a Kotlin version, you can use something like this;
private fun telephonyService() {
val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
val imei = if (android.os.Build.VERSION.SDK_INT >= 26) {
Timber.i("Phone >= 26 IMEI")
telephonyManager.imei
} else {
Timber.i("Phone IMEI < 26")
telephonyManager.deviceId
}
Timber.i("Phone IMEI $imei")
}
NOTE: You must wrap telephonyService() above with a permission check using checkSelfPermission or whatever method you use.
Also add this permission in the manifest file;
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

There is no Way you can get imei number from andorid 10+ or 29+ mobiles here is the alternative function that will be used for creating imei number for devices.
public static String getDeviceID(){
String devIDShort = "35" + //we make this look like a valid IMEI
Build.BOARD.length()%10+ Build.BRAND.length()%10 +
Build.CPU_ABI.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 ; //13 digits
return devIDShort;
}

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.

Related

How to Get IMEI or Serial Number for Android 10+ [duplicate]

I am getting the IMEI ID null from the telephonymanager. What to do?
is there any workaround for that?
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
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;
}
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);
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 :)
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();
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
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);
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);
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);
}
}
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
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.
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

Android API 29 Permission Error READ_PRIVILEGED_PHONE_STATE [duplicate]

I am getting the IMEI ID null from the telephonymanager. What to do?
is there any workaround for that?
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
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;
}
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);
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 :)
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();
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
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);
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);
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);
}
}
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
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.
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

I am getting IMEI null in Android Q?

I am getting the IMEI ID null from the telephonymanager. What to do?
is there any workaround for that?
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
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;
}
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);
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 :)
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();
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
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);
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);
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);
}
}
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
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.
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

On Oreo (8.1.0) not getting the correct Wifi SSID. It's showing <unknown ssid> though it is connected to a wifi with SSID

I need to check the current connected wifi SSID on android. I checked with Nokia 6 and OnePlus 5 with respectively Oreo 8.1.0 and Oreo 8.0. Other phones with different OS version is working fine with this code. Is there anything wrong with my code?
private WifiInfo wifiInfo;
private String ssid = "";
private WifiManager wifiManager;
private boolean getWifiStatus() {
wifiManager= (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiInfo = wifiManager.getConnectionInfo();
ssid = "";
ssid = wifiInfo.getSSID();
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isWiFi = false;
if(activeNetwork != null){
isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
}
Log.d(TAG, "getWifiStatus: " + ssid);
if(ssid.contains("TripleMZim") && wifiManager.isWifiEnabled() && isWiFi ){
return true;
}
else{
return false;
}
}
permission in Manifest file:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
There are different approaches how you can get the WIFI information (such as SSID) in android.
Some of them already listed here, for example WifiManager service.
But for OP question:
Is there anything wrong with my code?
No, the problem is not in your code.
The main reason for the unexpected behavior, is because of the security patch of the last android releases.
Before the patch (or any device that didn't get an update), the hackers could steal sensitive information that was leaked through the wifi info.
For example the hackers could obtain the device geolocation, that should be accessible only with the Dangerous Permission LOCATION, that should be requested at runtime and can be revoked at any moment. But in the other hand - the WifiInfo is accessible only with the Normal Permission android.permission.ACCESS_WIFI_STATE which is granted at install time and cannot be revoked.
That way, hackers could bypass the permission mechanism and access the data from dangerous permission using only normal permission.
The issue was reported and tracked by CVE-2018-9489, you can read more about it here: Sensitive information expose via WIFI
So the reason why you having those problems is because now android blocks the sensitive wifi info, unless the app holds the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION.
So, if you request those permissions explicitly (and allowed by the user), your code should work fine.
For example:
Manifest
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Activity
private static final int LOCATION = 1;
protected void onStart() {
super.onStart();
//Assume you want to read the SSID when the activity is started
tryToReadSSID();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED && requestCode == LOCATION){
//User allowed the location and you can read it now
tryToReadSSID();
}
}
private void tryToReadSSID() {
//If requested permission isn't Granted yet
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//Request permission from user
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION);
}else{//Permission already granted
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
if(wifiInfo.getSupplicantState() == SupplicantState.COMPLETED){
String ssid = wifiInfo.getSSID();//Here you can access your SSID
System.out.println(ssid);
}
}
}
Oreo 8.1+ devices require the coarse location runtime permission as well as location services to be turned on before being able to retrieve the connected SSID as it can infer the users location.
Further information is available here
Which relates to this
In Android Oreo you could use ConnectivityManager to know your wifi SSID.
Permission
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Code to get SSID
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
String ssid = info.getExtraInfo();
Log.d(TAG, "WiFi SSID: " + ssid);
}
This is tested in Android Oreo 8.1.0. You will get SSID enclosed with double quotes.
You need to request permission in manifest :
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
and request it in your activity :
private void grantPermm()
{
try
{
if (ContextCompat.checkSelfPermission(MainScreenActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
}
else
{
ActivityCompat.requestPermissions(MainScreenActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
101);
}
}
catch (Exception xx){}
}
then use this function :
public static String getWifiName(Context context)
{
String result="";
try {
WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if (manager.isWifiEnabled())
{
WifiInfo wifiInfo = manager.getConnectionInfo();
if (wifiInfo != null)
{
NetworkInfo.DetailedState state = WifiInfo.getDetailedStateOf(wifiInfo.getSupplicantState());
if (state == NetworkInfo.DetailedState.CONNECTED || state == NetworkInfo.DetailedState.OBTAINING_IPADDR)
{
result = wifiInfo.getSSID();
if(result.equalsIgnoreCase("<unknown ssid>"))
{
Toast.makeText(context,"You are connected to mobile data", Toast.LENGTH_SHORT).show();
result="";
}
return result;
}
else
{
Toast.makeText(context,"WIFI not connected", Toast.LENGTH_SHORT).show();
return "";
}
}
else
{
Toast.makeText(context,"No WIFI Information", Toast.LENGTH_SHORT).show();
return "";
}
}
else
{
Toast.makeText(context,"WIFI not enabled", Toast.LENGTH_SHORT).show();
return "";
}
}
catch (Exception xx)
{
Toast.makeText(context, xx.getMessage().toString(), Toast.LENGTH_SHORT).show();
return "";
}
}
If you're targeting API 29 (Android 10) then the location permission requested must now be for ACCESS_FINE_LOCATION, not just ACCESS_COARSE_LOCATION. Most of the above sample code is fine, however some answers could be misleading in the text.
https://developer.android.com/about/versions/10/privacy/changes
If you face issues even after trying the Yaswant Narayan and behelit answers, make sure you have enabled the Location/GPS in the device while trying to get the SSID. Even though, you have acquired the relevant permissions in Android Oreo and above devices, if the Location/GPS is turned off by the user, then you will get the from those devices.
You need to ask for runtime permission of read phone state. This is included for better security.
code is as follows:-
TelephonyManager telephonyManager = (TelephonyManager) getContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String IMEI ="";
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.READ_PHONE_STATE},
123);
}
int permission = ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.READ_PHONE_STATE);
if(permission == PackageManager.PERMISSION_GRANTED){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
IMEI = telephonyManager.getImei();
}
else{
IMEI = telephonyManager.getDeviceId();
}
}

Will TelephonyManger.getDeviceId() return device id for Tablets like Galaxy Tab...?

I want to get the device id that will be unique for each Android device. I am presently developing for a Tablet device. Want to get unique device id and store the corresponding values...
So, i want to know whether Tablet devices will return a value if i use TelephonyManager.getDeviceId()...???Or is there any other value that is unique for each device???
TelephonyManger.getDeviceId() Returns the unique device ID, for example, the IMEI for GSM and the MEID or ESN for CDMA phones.
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
But i recommend to use:
Settings.Secure.ANDROID_ID that returns the Android ID as an unique 64-bit hex string.
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Sometimes TelephonyManger.getDeviceId() will return null, so to assure an unique id you will use this method:
public String getUniqueID(){
String myAndroidDeviceId = "";
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null){
myAndroidDeviceId = mTelephony.getDeviceId();
}else{
myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
}
return myAndroidDeviceId;
}
This is not a duplicate question. As it turns out, Google's CTS require that getPhoneType of TelephonyManager needs to be none and getDeviceId of TelephonyManager needs to be null for non-phone devices.
So to get IMEI, please try to use:
String imei = SystemProperties.get("ro.gsm.imei")
Unfortunately, SystemProperties is a non-public class in the Android OS, which means it isn't publicly available to regular applications. Try looking at this post for help accessing it: Where is android.os.SystemProperties
Since Android 8 everything's changed. You should use Build.getSerial(), to get the serial number of the device and add the permission READ_PHONE_STATE.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
serial = Build.getSerial(); // Requires permission READ_PHONE_STATE
} else {
serial = Build.SERIAL; // Will return 'unknown' for device >= Build.VERSION_CODES.O
}
And get the IMEI or MEID this way:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String imei = tm.getImei(); // Requires permission READ_PHONE_STATE
serial = imei == null ? tm.getMeid() : imei; // Requires permission READ_PHONE_STATE
} else {
serial = tm.getDeviceId(); // Requires permission READ_PHONE_STATE
}

Categories

Resources