如何在android中以编程方式获取设备的IMEI/ESN ?

为了唯一地识别每个设备,我想使用IMEI(或CDMA设备的ESN号)。如何以编程方式访问它?

574199 次浏览

你想调用android.telephony.TelephonyManager.getDeviceId()

这将返回唯一标识该设备的字符串(GSM上的IMEI, CDMA上的MEID)。

你需要在你的AndroidManifest.xml中获得以下权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

为了做到这一点。

话虽如此,做这件事要小心。用户不仅会想知道为什么您的应用程序要访问他们的电话堆栈,而且如果用户获得了新设备,可能很难迁移数据。

更新:正如下面评论中提到的,这不是一种安全的方式来验证用户,并引起隐私问题。不建议使用。相反,如果你想实现一个无障碍的登录系统,可以查看谷歌+登录API

Android备份API也可用,如果你只是想要一种轻量级的方式来持久化一束字符串,当用户重置他们的手机(或购买新设备)。

除了Trevor Johns的回答外,你还可以这样使用:

TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.getDeviceId();

并且您应该在Manifest.xml文件中添加以下权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

在模拟器中,你可能会得到一个“00000…”的值。如果设备ID不可用,getDeviceId()返回NULL。

或者你可以使用Android.Provider.Settings.System中的ANDROID_ID设置(如这里strazerre.com所述)。

这样做的好处是,它不需要特殊的权限,但如果另一个应用程序具有写访问权限并更改它,则可以更改它(这显然不常见,但并非不可能)。

仅供参考,这里是来自博客的代码:

import android.provider.Settings;
import android.provider.Settings.System;


String androidID = System.getString(this.getContentResolver(),Secure.ANDROID_ID);

实现注意: 如果ID对系统架构至关重要,你需要知道,在实践中,一些非常低端的Android手机&平板电脑已经发现重用相同的ANDROID_ID (9774d56d682e549c是在我们的日志中显示的值)

来自:http://mytechead.wordpress.com/2011/08/28/how-to-get-imei-number-of-android-device/:

下面的代码可以帮助获取android设备的IMEI号码:

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String device_id = tm.getDeviceId();

Android Manifest中需要的权限:

android.permission.READ_PHONE_STATE
注意:在平板电脑或不能作为移动电话的设备的情况下

. IMEI将为空

我使用以下代码获取IMEI或使用Secure。ANDROID_ID作为替代,当设备没有电话功能时:

/**
* 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;
}

API等级11或以上:

case TelephonyManager.PHONE_TYPE_SIP:
return "SIP";


TelephonyManager tm= (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
textDeviceID.setText(getDeviceID(tm));

TelephonyManager的getDeviceId()方法返回唯一的设备ID,例如GSM电话的IMEI, CDMA电话的MEID或ESN。如果设备ID不可用,则返回null。

Java代码

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>

< >强许可要求

. READ_PHONE_STATE

使用下面的代码给你IMEI号码:

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
System.out.println("IMEI::" + telephonyManager.getDeviceId());

获取IMEI(国际移动设备标识符)

public String getIMEI(Activity activity) {
TelephonyManager telephonyManager = (TelephonyManager) activity
.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getDeviceId();
}

来获得设备唯一id

public String getDeviceUniqueID(Activity activity){
String device_unique_id = Secure.getString(activity.getContentResolver(),
Secure.ANDROID_ID);
return device_unique_id;
}

对于Android 6.0+游戏已经改变,所以我建议你使用这个;

最好的方法是在运行时执行,否则会出现权限错误。

   /**
* 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);
}
}

希望这能帮助到你或其他人。

新更新:< em > < / em >

对于Android版本6及以上,WLAN MAC地址已弃用,请遵循Trevor Johns的回答

< em >更新:< / em >

对于设备的唯一标识,可以使用安全。ANDROID_ID

< em >老答:< / em >

使用IMEI作为唯一设备ID的缺点:

  • IMEI依赖于设备的Simcard插槽,所以不是 对于不使用Simcard的设备,可以获得IMEI。 在双sim卡设备中,我们为同一个设备获得2个不同的imei,因为它有2个simcard插槽

您可以使用WLAN MAC地址字符串(不推荐用于Marshmallow和Marshmallow+,因为WLAN MAC地址已在Marshmallow转发上被弃用。所以你会得到一个伪值)

我们也可以使用WLAN MAC地址获得android手机的唯一ID。MAC地址对于所有设备都是唯一的,它适用于所有类型的设备。

使用WLAN MAC地址作为设备ID的优点:

  • 是所有类型设备的唯一标识符(智能手机和 李平板电脑). < / p > < / >

  • 如果重新安装应用程序,它将保持唯一

使用WLAN MAC地址作为设备ID的缺点:

  • 给你一个虚假的价值从棉花糖和以上。

  • 如果设备没有wifi硬件,则MAC地址为空, 但通常可以看到大多数Android设备都有wifi 硬件和市场上几乎没有没有wifi的设备 李硬件。< / p > < / >

来源:technetexperts.com

正如在API 26中,getDeviceId()是贬值的,所以你可以使用以下代码来满足API 26和更早的版本

TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String imei="";
if (android.os.Build.VERSION.SDK_INT >= 26) {
imei=telephonyManager.getImei();
}
else
{
imei=telephonyManager.getDeviceId();
}

不要忘记为READ_PHONE_STATE添加使用上述代码的权限请求。

< p >更新: 从Android 10开始,用户应用程序被限制获得不可重置的硬件标识符,如IMEI
你可以使用这个TelephonyManager TELEPHONY_SERVICE函数来获取唯一设备ID, 需要的权限:READ_PHONE_STATE

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

例如,GSM IMEICDMA的MEID或ESN电话。

/**
* 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();
}

如果设备ID不可用. 返回null

getDeviceId()方法已弃用。 有一个新方法getImei(int)

在这里检查

对于那些寻找Kotlin版本的人,您可以使用这样的东西;

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")
}

注意:你必须使用checkSelfPermission或任何你使用的方法将上面的telephonyService()与权限检查结合起来。

还可以在清单文件中添加此权限;

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

Kotlin获取DeviceId (IMEI)的代码,有处理权限所有android版本的可比性检查:

 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


}

将此权限添加到AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- IMEI-->

试试这个(总是需要第一个IMEI)

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();
}

你需要在AndroidManifest.xml中设置以下权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

要获得IMEI(国际移动设备标识符),如果它高于API级别26,那么我们将telephonyManager.getImei()作为null,因此,我们使用ANDROID_ID作为唯一标识符。

 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;
}

使用以下代码:

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();
}
}

并调用onRequestPermissionsResult方法如下代码:

@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();
}
}
}

在你的AndroidManifest.xml中添加以下权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

以下代码是为我工作。

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
}
}
}


你无法从andorid10 +或29+手机中获得imei号码,这里是用于为设备创建imei号码的替代功能。

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;
}

对不可重置设备标识符的限制

从Android 10开始,应用程序必须拥有READ_PRIVILEGED_PHONE_STATE特权权限才能访问设备的不可重置标识符,包括IMEI和序列号。