从手机获取联系人并在对话框显示时出错,附相关代码求助
嘿,看起来你在从系统联系人拉取数据并展示到AlertDialog的过程中踩坑了!我帮你梳理几个最常见的问题和对应的修复方案,应该能解决你的困扰:
常见问题排查与修复方案
1. 联系人权限缺失(最容易忽略的点)
Android 6.0及以上版本对读取联系人这类危险权限要求动态申请,光在Manifest里声明还不够。
首先,在AndroidManifest.xml里添加权限声明:
<uses-permission android:name="android.permission.READ_CONTACTS" />
然后在代码里先检查权限,再执行查询逻辑,避免直接触发权限异常:
btn_add_from_contacts.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 先检查是否已获取读取联系人权限 if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // 未授权,发起权限申请 ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_CONTACTS}, 1001); // 自定义请求码,用于后续判断 return; } // 权限已授予,执行联系人加载和弹窗逻辑 loadContactsAndShowDialog(); } }); // 处理权限申请结果回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1001) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户同意权限,继续加载联系人 loadContactsAndShowDialog(); } else { // 用户拒绝权限,给出提示 Toast.makeText(getActivity(), "需要允许读取联系人权限才能继续操作", Toast.LENGTH_SHORT).show(); } } } // 封装联系人查询与弹窗展示的核心逻辑 private void loadContactsAndShowDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); View dialogView = getLayoutInflater().inflate(R.layout.layout_add_from_contacts, null); builder.setView(dialogView); // 只查询需要的列,提升性能,避免冗余数据 Cursor contactCursor = getActivity().getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[]{ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER }, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC"); // 处理Cursor,避免空指针和内存泄漏 List<String> contactList = new ArrayList<>(); if (contactCursor != null) { while (contactCursor.moveToNext()) { String name = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String phoneNum = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); contactList.add(name + " : " + phoneNum); } contactCursor.close(); // 用完Cursor必须关闭,防止内存泄漏 } // 假设你的弹窗布局里有一个ListView用于展示联系人 ListView lvContacts = dialogView.findViewById(R.id.lv_contacts); ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, contactList); lvContacts.setAdapter(adapter); // 别忘记显示弹窗!很多人会漏掉这一步,导致看起来像出错了 builder.setTitle("选择联系人") .setNegativeButton("取消", (dialog, which) -> dialog.dismiss()) .show(); }
2. Cursor处理不当引发的异常
- 永远要先判断Cursor是否为
null,避免查询失败时触发NullPointerException - 遍历完成后**必须调用
close()**释放资源,否则会造成内存泄漏 - 查询时尽量指定需要的列(不要用
null),减少数据传输量,提升查询效率
3. 弹窗未正确显示
你给出的代码片段里只创建了AlertDialog.Builder并设置了View,但没有调用show()方法,这会导致弹窗根本不会弹出,看起来像是功能失效。一定要记得最后调用builder.show()来触发弹窗展示。
4. 弹窗布局的潜在问题
确保你的layout_add_from_contacts布局里包含了用于展示联系人的控件(比如ListView或RecyclerView),并且控件ID与代码中的查找逻辑匹配。如果布局为空或者没有可展示的控件,也会出现“没效果”的情况。
如果这些方案还没解决你的问题,建议把Logcat里的具体错误日志贴出来,这样能更精准地定位问题哦!
内容的提问来源于stack exchange,提问作者user7633479
相关产品推荐
相关产品推荐

