显示READ_PHONE_STATE权限对话框时触发PackageManager$NameNotFoundException异常
从你贴的异常栈来看,关键错误是No package: null——这说明系统的GrantPermissionsActivity找不到发起权限请求的应用包名,结合你是迁移代码后才出现问题的情况,大概率是权限请求时传递的Activity上下文无效导致的。
我给你几个针对性的解决建议:
先检查传递的Activity实例是否有效
你写的requestPermission方法第一个参数是Activity activity,迁移代码后很可能不小心传了null,或者错误地传了Application Context(比如getApplicationContext())。权限请求必须绑定到一个存活的Activity实例上,系统才能通过它获取到你的应用包名。调用这个方法时,一定要传当前的Activity对象:比如在Activity里用this,在Fragment里用getActivity()(注意要确保Fragment已关联Activity,避免null)。修复权限请求方法的逻辑漏洞
你的代码里不管shouldShowRequestPermissionRationale返回true还是false,都直接调用requestPermissions,其实这个判断的意义是用来显示权限说明弹窗的,而且你应该先加非空判断避免传入null的Activity:public void requestPermission(Activity activity, String[] permissions, int permissionRequestCode) { // 先校验Activity实例是否有效 if (activity == null) { throw new IllegalArgumentException("Activity instance can't be null for permission request!"); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permissions[0])) { // 这里显示权限说明弹窗,告知用户为什么需要该权限 new AlertDialog.Builder(activity) .setTitle("需要读取手机状态权限") .setMessage("为了完成相关功能,我们需要获取您的手机状态信息,请允许此权限。") .setPositiveButton("确定", (dialog, which) -> { ActivityCompat.requestPermissions(activity, permissions, permissionRequestCode); }) .setNegativeButton("取消", null) .show(); } else { ActivityCompat.requestPermissions(activity, permissions, permissionRequestCode); } } }确保调用时机在Activity生命周期内
不要在Activity已销毁、或未完成初始化的状态下调用权限请求(比如在子线程直接调用,或者在onDestroy之后),必须保证Activity处于活跃状态(比如onCreate、onResume等生命周期方法内,或者用户交互事件触发时)。顺带确认Manifest权限声明
虽然你说已经声明,但还是再核对一下,READ_PHONE_STATE的声明是否正确放在Manifest根节点下(不要放在application标签里):<uses-permission android:name="android.permission.READ_PHONE_STATE" />如果你适配Android 12+,还需要额外声明
READ_PHONE_NUMBERS权限,但这不是导致当前异常的原因,只是顺便提醒。
总结一下:这个异常的核心是系统拿不到你的应用包名,根源就是传递的Activity上下文无效,先把这个环节排查清楚,应该就能解决问题了。
内容的提问来源于stack exchange,提问作者Ezio

