You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Nougat(API24)下无法获取IMEI的问题求助

解决Android Nougat(API24)无法获取IMEI的问题

我仔细看了你的代码和问题描述,核心问题是动态权限申请的流程处理错误,以及代码逻辑顺序颠倒导致权限未生效时就调用了敏感API,进而抛出SecurityException。下面帮你一步步梳理问题并给出正确实现:

你的代码中存在的核心问题

代码1的问题

  • context变量未初始化,点击事件里用context做权限检查会导致错误,应该使用当前Activity的实例(比如MainActivity.this)
  • 权限申请后没有处理回调:用户授予权限后,你没有在onRequestPermissionsResult中重新执行获取IMEI的逻辑,而是在申请权限的同时直接调用getDeviceId(),这时候权限还未真正授予
  • 点击事件的逻辑顺序错误:在权限未通过的分支里直接调用getDeviceId(),这必然会失败

代码2的问题

  • 逻辑完全颠倒:在权限未授予的分支里去调用tm.getDeviceId(),这直接触发了SecurityException,正确逻辑应该是权限授予后才调用这些敏感API

正确的实现步骤与代码

首先确保AndroidManifest.xml中已经声明权限:

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

然后是Activity的完整实现,包含权限检查、申请、回调处理:

public class MainActivity extends AppCompatActivity {

    private TextView imei_number;
    private Button get_imei;
    private TelephonyManager telephonyManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imei_number = findViewById(R.id.textView1);
        get_imei = findViewById(R.id.button1);
        telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        // 点击按钮触发IMEI获取
        get_imei.setOnClickListener(v -> checkPermissionAndGetImei());
    }

    // 检查权限并获取IMEI
    private void checkPermissionAndGetImei() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            // 权限未授予,申请权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 100);
        } else {
            // 权限已授予,直接获取IMEI
            fetchImei();
        }
    }

    // 获取IMEI并显示
    private void fetchImei() {
        try {
            String imei;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // API26及以上可以获取双卡的IMEI
                imei = telephonyManager.getImei(0);
                // 如果是双卡,可以获取第二个:telephonyManager.getImei(1);
            } else {
                // API26以下用getDeviceId
                imei = telephonyManager.getDeviceId();
            }
            imei_number.setText("IMEI: " + imei);
        } catch (SecurityException e) {
            e.printStackTrace();
            imei_number.setText("获取IMEI失败:权限不足");
        }
    }

    // 处理权限申请的回调
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 100) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授予权限,重新获取IMEI
                fetchImei();
            } else {
                // 用户拒绝权限,提示无法获取
                imei_number.setText("您拒绝了权限,无法获取IMEI");
            }
        }
    }
}

关键注意点

  1. 动态权限的必要性:从Android 6.0(API23)开始,READ_PHONE_STATE属于危险权限,必须通过requestPermissions让用户主动授予,仅在Manifest中声明是不够的
  2. 权限回调的处理:必须在onRequestPermissionsResult中处理用户的权限选择,只有当权限授予后,才能调用getDeviceId()或getImei()
  3. API版本适配:API26及以上推荐使用getImei()代替getDeviceId(),后者在高版本中逐渐被废弃

内容的提问来源于stack exchange,提问作者Imran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:24:03