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

如何在Flutter中获取通讯录权限?附permission_handler代码示例

正确获取通讯录权限的实现方案

要顺利使用contact_services操作通讯录,你需要完成平台权限配置并完善权限请求逻辑,具体步骤如下:

1. 平台权限配置

Android

在android/app/src/main/AndroidManifest.xml中添加通讯录权限声明(按需选择读/写权限):

<!-- 读取通讯录权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- 写入通讯录权限(如需修改通讯录) -->
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

iOS

在ios/Runner/Info.plist中添加权限用途描述,系统请求权限时会展示这段文字:

<key>NSContactsUsageDescription</key>
<string>需要访问您的通讯录来管理联系人信息</string>

2. 完善权限请求逻辑

你的现有代码实现了基础权限请求,但缺少对不同权限状态的后续处理(比如用户永久拒绝时的引导),且需确保权限通过后再调用contact_services。修改后的完整代码如下:

import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'calendar.dart';
import 'info.dart';
// 导入contact_services插件
import 'package:contact_services/contact_services.dart';

void main() => runApp(const PageScaffoldApp());

class PageScaffoldApp extends StatelessWidget {
  const PageScaffoldApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      theme: CupertinoThemeData(brightness: Brightness.light),
      home: HomeScreen(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<Widget> data = [CalendarScreen(), const InfoScreen()];
  bool _contactsPermissionGranted = false;

  @override
  void initState() {
    super.initState();
    _askPermissions();
  }

  Future<void> _askPermissions() async {
    PermissionStatus permissionStatus = await _getContactPermission();
    setState(() {
      _contactsPermissionGranted = permissionStatus == PermissionStatus.granted;
    });

    if (_contactsPermissionGranted) {
      // 权限通过后初始化通讯录服务
      _initContactServices();
    } else if (permissionStatus == PermissionStatus.permanentlyDenied) {
      // 用户永久拒绝,引导去设置开启
      _showOpenSettingsDialog();
    }
  }

  Future<PermissionStatus> _getContactPermission() async {
    PermissionStatus permission = await Permission.contacts.status;
    if (permission != PermissionStatus.granted &&
        permission != PermissionStatus.permanentlyDenied) {
      PermissionStatus permissionStatus = await Permission.contacts.request();
      return permissionStatus;
    } else {
      return permission;
    }
  }

  void _initContactServices() async {
    // 示例:获取通讯录联系人
    try {
      List<Contact> contacts = await ContactsService.getContacts();
      print("获取到${contacts.length}个联系人");
      // 这里可以处理联系人数据
    } catch (e) {
      print("获取联系人失败: $e");
    }
  }

  void _showOpenSettingsDialog() {
    showCupertinoDialog(
      context: context,
      builder: (context) => CupertinoAlertDialog(
        title: const Text("通讯录权限被拒绝"),
        content: const Text("请前往应用设置开启通讯录权限,否则无法使用相关功能"),
        actions: [
          CupertinoDialogAction(
            child: const Text("取消"),
            onPressed: () => Navigator.pop(context),
          ),
          CupertinoDialogAction(
            child: const Text("去设置"),
            onPressed: () {
              Navigator.pop(context);
              openAppSettings();
            },
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
      tabBar: CupertinoTabBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.calendar_circle),
            activeIcon: Icon(CupertinoIcons.calendar_circle_fill),
            label: 'Calendar',
          ),
          BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.info_circle),
            activeIcon: Icon(CupertinoIcons.info_circle_fill),
            label: 'Info',
          ),
        ],
      ),
      tabBuilder: (BuildContext context, int index) {
        return CupertinoTabView(
          builder: (BuildContext context) {
            return data[index];
          },
        );
      },
    );
  }
}

关键说明

  • 权限状态处理:新增permanentlyDenied状态的处理逻辑,引导用户前往设置开启权限,避免用户误操作后无法再次触发权限请求。
  • 权限验证时机:仅在权限通过后初始化contact_services,避免无权限时调用相关功能抛出异常。
  • 平台配置:必须在Android和iOS的配置文件中添加对应权限声明和描述,否则权限请求会直接失败。

内容的提问来源于stack exchange,提问作者M.K. Mandawar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 20:30:35