To obtain the International Mobile Equipment Identity (IMEI) on modern Android vertions, developers must configure manifest declarations and handle runtime permissions carefully due to increased privacy restrictions.
Menifest Configuration
First, declare the necessary privilege in the project configuration file. Without this permission, the system will block any attempts to read telephony status.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Runtime Permission Verification
Starting with API levell 29 (Android 10), accessing device identifiers requires explicit user consent at runtime. Code logic must differentiate between older environments where implicit access was possible and newer ones requiring checks.
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.os.Build;
public class ImeiUtils {
public static void checkAccessRequirement(Activity context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
boolean isGranted = context.checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED;
if (!isGranted) {
context.requestPermissions(
new String[]{ Manifest.permission.READ_PHONE_STATE },
1002
);
} else {
resolveDeviceId(context);
}
} else {
resolveDeviceId(context);
}
}
}
Execution of Retrieval Logic
Once authorization is confirmed, instantiate the system service to query the hardware serial number. Modern APIs often return null if the application lacks specific carrier privileges or if privacy policies restrict access to resettable identifiers. Therefore, null safety is essential.
private void resolveDeviceId(Context appContext) {
TelephonyManager tm = (TelephonyManager) appContext.getSystemService(TelephonyManager.TELEPHONY_SERVICE);
if (tm != null &&
appContext.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
String targetSerial = tm.getImei();
Log.i("HardwareID", targetSerial != null ? targetSerial : "No identifier available");
}
}