联系人备份工具应用


欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

适配的第三方库地址:

  • flutter_contacts: https://pub.dev/packages/flutter_contacts
  • share_plus: https://pub.dev/packages/share_plus
  • sqflite: https://pub.dev/packages/sqflite
  • permission_handler: https://pub.dev/packages/permission_handler

一、项目概述

运行效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1 应用简介

联系人备份工具是一款专注于通讯录管理的实用工具应用,旨在帮助用户安全、便捷地管理手机联系人。应用支持多种备份方式、智能重复检测、灵活分组管理,让用户的通讯录始终保持整洁有序。

应用以清新青绿为主色调,象征安全与可靠。涵盖联系人管理、备份恢复、重复检测、分组管理四大核心模块。用户可以轻松备份联系人、导入导出数据、合并重复项、按组分类管理,实现通讯录的高效管理。

1.2 核心功能

功能模块功能描述实现方式
联系人管理查看、编辑、删除联系人通讯录API
本地备份备份联系人到本地存储文件存储
云端备份同步联系人到云端服务网络同步
导入导出导出VCF/CSV格式文件文件处理
重复检测智能识别重复联系人算法匹配
合并功能一键合并重复联系人数据合并
分组管理按类别分组管理联系人分类管理
搜索功能快速搜索联系人信息模糊搜索

1.3 联系人分组定义

序号分组名称图标颜色描述
1家人👨‍👩‍👧‍👦红色家庭成员
2朋友👥蓝色社交好友
3工作💼绿色工作伙伴
4同学🎓橙色学校同学
5其他灰色其他联系人

1.4 备份类型定义

序号备份类型图标描述特点
1本地备份📱备份到手机存储无需网络
2云端备份☁️同步到云端服务跨设备同步
3导出文件📥导出VCF/CSV文件便于分享

1.5 重复检测规则

序号匹配字段优先级描述
1电话号码完全匹配电话号码
2姓名完全匹配联系人姓名
3邮箱完全匹配邮箱地址
4姓名+电话组合匹配

1.6 导出格式定义

序号格式名称扩展名描述兼容性
1VCF.vcfvCard标准格式通用
2CSV.csv表格数据格式Excel兼容
3JSON.json结构化数据格式开发友好

1.7 技术栈

技术领域技术选型版本要求
开发框架Flutter>= 3.0.0
编程语言Dart>= 2.17.0
设计规范Material Design 3-
状态管理StatefulWidget-
通讯录管理Flutter Contacts>= 1.0.0
文件分享Share Plus>= 7.0.0
数据存储Sqflite>= 2.0.0
权限管理Permission Handler>= 11.0.0
目标平台鸿蒙OS / WebAPI 21+

1.8 项目结构

lib/
└── main_contact_backup.dart
    ├── ContactBackupApp               # 应用入口
    ├── ContactGroup                   # 联系人分组枚举
    ├── BackupType                     # 备份类型枚举
    ├── Contact                        # 联系人模型
    ├── BackupRecord                   # 备份记录模型
    ├── DuplicateContact               # 重复联系人模型
    ├── ContactBackupHomePage          # 主页面(底部导航)
    ├── _buildContactsPage             # 联系人页
    ├── _buildBackupPage               # 备份页
    ├── _buildDuplicatesPage           # 重复检测页
    └── _buildGroupsPage               # 分组页

二、系统架构

2.1 整体架构图

Data Layer

Business Layer

Presentation Layer

主页面
ContactBackupHomePage

联系人页

备份页

重复检测页

分组页

联系人列表

联系人详情

搜索功能

备份选项

备份记录

恢复功能

重复列表

合并功能

分组列表

分组详情

联系人管理器
ContactManager

备份管理器
BackupManager

重复检测器
DuplicateDetector

导入导出器
ImportExporter

Contact
联系人

BackupRecord
备份记录

ContactGroup
分组

SQLite
本地数据库

2.2 类图设计

belongs to

has

contains

ContactBackupApp

+Widget build()

«enumeration»

ContactGroup

+String label

+IconData icon

+Color color

+family()

+friends()

+work()

+school()

+other()

«enumeration»

BackupType

+String label

+IconData icon

+local()

+cloud()

+export()

Contact

+String id

+String name

+String phone

+String email

+String company

+String notes

+ContactGroup group

+bool isFavorite

+DateTime createdAt

+DateTime updatedAt

+get initials

+get displayName

+copyWith()

BackupRecord

+String id

+String name

+BackupType type

+int contactCount

+int fileSize

+DateTime createdAt

+String filePath

+get fileSizeFormatted

DuplicateContact

+Contact original

+List<Contact> duplicates

+String matchField

2.3 页面导航流程

联系人

备份

重复

分组

应用启动

联系人页

底部导航

查看联系人列表

点击联系人

查看详情

编辑/删除

备份页

选择备份类型

执行备份

重复检测页

查看重复列表

合并重复

分组页

查看分组列表

点击分组

查看分组联系人

2.4 备份恢复流程

存储服务备份管理器备份页用户存储服务备份管理器备份页用户alt[本地备份][云端备份][导出文件]选择备份类型请求备份写入本地文件返回文件路径上传到云端返回同步结果生成VCF/CSV返回文件保存备份记录返回备份结果显示成功提示

三、核心模块设计

3.1 数据模型设计

3.1.1 联系人分组枚举 (ContactGroup)
enum ContactGroup {
  family('家人', Icons.family_restroom, Colors.red),
  friends('朋友', Icons.people, Colors.blue),
  work('工作', Icons.work, Colors.green),
  school('同学', Icons.school, Colors.orange),
  other('其他', Icons.more_horiz, Colors.grey);

  final String label;
  final IconData icon;
  final Color color;
  const ContactGroup(this.label, this.icon, this.color);
}
3.1.2 备份类型枚举 (BackupType)
enum BackupType {
  local('本地备份', Icons.phone_android),
  cloud('云端备份', Icons.cloud_upload),
  export('导出文件', Icons.file_download);

  final String label;
  final IconData icon;
  const BackupType(this.label, this.icon);
}
3.1.3 联系人模型 (Contact)
class Contact {
  final String id;
  final String name;
  final String? phone;
  final String? email;
  final String? company;
  final String? notes;
  final ContactGroup group;
  final bool isFavorite;
  final DateTime createdAt;
  final DateTime? updatedAt;

  const Contact({
    required this.id,
    required this.name,
    this.phone,
    this.email,
    this.company,
    this.notes,
    required this.group,
    required this.isFavorite,
    required this.createdAt,
    this.updatedAt,
  });

  Contact copyWith({
    String? name,
    String? phone,
    String? email,
    String? company,
    String? notes,
    ContactGroup? group,
    bool? isFavorite,
    DateTime? updatedAt,
  }) {
    return Contact(
      id: id,
      name: name ?? this.name,
      phone: phone ?? this.phone,
      email: email ?? this.email,
      company: company ?? this.company,
      notes: notes ?? this.notes,
      group: group ?? this.group,
      isFavorite: isFavorite ?? this.isFavorite,
      createdAt: createdAt,
      updatedAt: updatedAt ?? this.updatedAt,
    );
  }

  String get initials {
    if (name.isEmpty) return '?';
    final parts = name.split(' ');
    if (parts.length >= 2) {
      return '${parts[0][0]}${parts[1][0]}'.toUpperCase();
    }
    return name[0].toUpperCase();
  }
}
3.1.4 联系人分组分布
40%27%17%10%7%联系人分组分布示例家人朋友工作同学其他

3.2 页面结构设计

3.2.1 主页面布局

ContactBackupHomePage

IndexedStack

联系人页

备份页

重复检测页

分组页

NavigationBar

联系人 Tab

备份 Tab

重复 Tab

分组 Tab

3.2.2 联系人页结构

联系人页

SliverAppBar

统计卡片

联系人列表

联系人详情

联系人总数

收藏数量

收藏统计

电话统计

邮箱统计

重复统计

联系人卡片

分组标签

收藏标记

3.2.3 备份页结构

备份页

备份选项

备份记录列表

恢复功能

本地备份

云端备份

导出文件

备份名称

联系人数量

文件大小

创建时间

3.2.4 重复检测页结构

重复检测页

检测结果

重复列表

合并操作

重复组数

可合并数

原始联系人

重复联系人

匹配字段

合并按钮

查看详情

3.3 重复检测逻辑

开始检测

获取所有联系人

按电话号码分组

有重复?

记录电话重复

按姓名分组

有重复?

记录姓名重复

按邮箱分组

有重复?

记录邮箱重复

返回结果

3.4 备份管理逻辑

本地

云端

导出

选择备份类型

备份类型?

生成备份文件

连接云端服务

选择导出格式

写入本地存储

上传联系人数据

生成VCF/CSV

保存备份记录

分享文件

显示成功提示


四、UI设计规范

4.1 配色方案

应用以清新青绿为主色调,象征安全与可靠:

颜色类型色值用途
主色#009688 (Teal)导航、主题元素
辅助色#4DB6AC卡片背景
第三色#80CBC4进度条背景
强调色#B2DFDB分组页面
背景色#FAFAFA页面背景
卡片背景#FFFFFF信息卡片
家人色#F44336家人分组
朋友色#2196F3朋友分组

4.2 分组配色

分组色值视觉效果
家人#F44336红色
朋友#2196F3蓝色
工作#4CAF50绿色
同学#FF9800橙色
其他#9E9E9E灰色

4.3 字体规范

元素字号字重颜色
页面标题24pxBold主色
联系人名称16pxMedium#000000
联系方式13pxRegular#666666
分组标签11pxMedium分组色
备份名称15pxMedium#000000
提示文字14pxRegular#999999

4.4 组件规范

4.4.1 联系人卡片
┌─────────────────────────────────────┐
│  ⭕ 张三              [朋友]        │
│     138****1234                     │
│                                  ⭐ │
└─────────────────────────────────────┘
4.4.2 备份选项卡片
┌─────────────────────────────────────┐
│  备份选项                             │
│                                     │
│  ┌────────┐ ┌────────┐ ┌────────┐  │
│  │  📱   │ │  ☁️   │ │  📥   │  │
│  │ 本地   │ │ 云端   │ │ 导出   │  │
│  │ 备份   │ │ 备份   │ │ 文件   │  │
│  └────────┘ └────────┘ └────────┘  │
└─────────────────────────────────────┘
4.4.3 备份记录卡片
┌─────────────────────────────────────┐
│  📱 自动备份_20240115         ⋮     │
│     28 个联系人 · 45.7 KB           │
│     2024-01-15 10:30               │
└─────────────────────────────────────┘
4.4.4 重复联系人卡片
┌─────────────────────────────────────┐
│  ⚠️ 重复: 电话号码相同               │
│  ─────────────────────────────────  │
│  ⭕ 张三  [保留]                    │
│     138****1234                     │
│  ⭕ 张三                            │
│     138****1234                     │
│  ─────────────────────────────────  │
│  [合并]              [查看详情]     │
└─────────────────────────────────────┘
4.4.5 分组卡片
┌─────────────────────────────────────┐
│  👥                          12    │
│                                     │
│  朋友                               │
│  12 位联系人                        │
└─────────────────────────────────────┘

五、核心功能实现

5.1 联系人管理器实现

class ContactManager {
  List<Contact> _contacts = [];

  Future<void> loadContacts() async {
    if (await Permission.contacts.request().isGranted) {
      final contacts = await FlutterContacts.getContacts(
        withProperties: true,
        withPhoto: true,
      );
      _contacts = contacts.map(_convertToContact).toList();
    }
  }

  Future<void> addContact(Contact contact) async {
    final newContact = Contact(
      id: 'contact_${DateTime.now().millisecondsSinceEpoch}',
      name: contact.name,
      phone: contact.phone,
      email: contact.email,
      company: contact.company,
      notes: contact.notes,
      group: contact.group,
      isFavorite: false,
      createdAt: DateTime.now(),
    );
    _contacts.add(newContact);
    await _saveToSystemContacts(newContact);
  }

  Future<void> updateContact(Contact contact) async {
    final index = _contacts.indexWhere((c) => c.id == contact.id);
    if (index != -1) {
      _contacts[index] = contact.copyWith(updatedAt: DateTime.now());
      await _updateSystemContacts(contact);
    }
  }

  Future<void> deleteContact(String contactId) async {
    _contacts.removeWhere((c) => c.id == contactId);
    await _deleteFromSystemContacts(contactId);
  }

  List<Contact> searchContacts(String query) {
    final lowerQuery = query.toLowerCase();
    return _contacts.where((c) {
      return c.name.toLowerCase().contains(lowerQuery) ||
          (c.phone?.contains(query) ?? false) ||
          (c.email?.toLowerCase().contains(lowerQuery) ?? false);
    }).toList();
  }
}

5.2 备份管理器实现

class BackupManager {
  final DatabaseHelper _dbHelper = DatabaseHelper();

  Future<BackupRecord> createLocalBackup(List<Contact> contacts) async {
    final fileName = 'backup_${DateTime.now().millisecondsSinceEpoch}.json';
    final data = jsonEncode(contacts.map((c) => c.toJson()).toList());
    final file = await _saveToFile(fileName, data);

    final record = BackupRecord(
      id: 'backup_${DateTime.now().millisecondsSinceEpoch}',
      name: '本地备份_${DateTime.now().toString().substring(0, 10)}',
      type: BackupType.local,
      contactCount: contacts.length,
      fileSize: data.length,
      createdAt: DateTime.now(),
      filePath: file.path,
    );

    await _dbHelper.insertBackupRecord(record);
    return record;
  }

  Future<BackupRecord> createCloudBackup(List<Contact> contacts) async {
    final response = await _cloudService.uploadContacts(contacts);

    final record = BackupRecord(
      id: 'backup_${DateTime.now().millisecondsSinceEpoch}',
      name: '云端备份_${DateTime.now().toString().substring(0, 10)}',
      type: BackupType.cloud,
      contactCount: contacts.length,
      fileSize: response.size,
      createdAt: DateTime.now(),
    );

    await _dbHelper.insertBackupRecord(record);
    return record;
  }

  Future<void> restoreFromBackup(BackupRecord record) async {
    final data = await _loadBackupData(record);
    final contacts = (jsonDecode(data) as List)
        .map((json) => Contact.fromJson(json))
        .toList();

    for (final contact in contacts) {
      await _contactManager.addContact(contact);
    }
  }

  Future<String> exportToVCF(List<Contact> contacts) async {
    final buffer = StringBuffer();
    for (final contact in contacts) {
      buffer.writeln('BEGIN:VCARD');
      buffer.writeln('VERSION:3.0');
      buffer.writeln('FN:${contact.name}');
      if (contact.phone != null) {
        buffer.writeln('TEL:${contact.phone}');
      }
      if (contact.email != null) {
        buffer.writeln('EMAIL:${contact.email}');
      }
      if (contact.company != null) {
        buffer.writeln('ORG:${contact.company}');
      }
      buffer.writeln('END:VCARD');
    }
    return buffer.toString();
  }
}

5.3 重复检测器实现

class DuplicateDetector {
  List<DuplicateContact> findDuplicates(List<Contact> contacts) {
    final duplicates = <DuplicateContact>[];
    final phoneMap = <String, List<Contact>>{};
    final nameMap = <String, List<Contact>>{};
    final emailMap = <String, List<Contact>>{};

    for (final contact in contacts) {
      if (contact.phone != null) {
        phoneMap.putIfAbsent(contact.phone!, () => []).add(contact);
      }
      nameMap.putIfAbsent(contact.name, () => []).add(contact);
      if (contact.email != null) {
        emailMap.putIfAbsent(contact.email!, () => []).add(contact);
      }
    }

    for (final entry in phoneMap.entries) {
      if (entry.value.length > 1) {
        duplicates.add(DuplicateContact(
          original: entry.value.first,
          duplicates: entry.value.skip(1).toList(),
          matchField: '电话号码',
        ));
      }
    }

    for (final entry in nameMap.entries) {
      if (entry.value.length > 1) {
        final existingIds = duplicates
            .expand((d) => [d.original.id, ...d.duplicates.map((c) => c.id)])
            .toSet();
        if (!existingIds.contains(entry.value.first.id)) {
          duplicates.add(DuplicateContact(
            original: entry.value.first,
            duplicates: entry.value.skip(1).toList(),
            matchField: '姓名',
          ));
        }
      }
    }

    return duplicates;
  }

  Contact mergeContacts(Contact original, List<Contact> duplicates) {
    String? phone = original.phone;
    String? email = original.email;
    String? company = original.company;
    String? notes = original.notes;

    for (final dup in duplicates) {
      phone ??= dup.phone;
      email ??= dup.email;
      company ??= dup.company;
      notes ??= dup.notes;
    }

    return original.copyWith(
      phone: phone,
      email: email,
      company: company,
      notes: notes,
      updatedAt: DateTime.now(),
    );
  }
}

5.4 权限管理实现

class PermissionManager {
  Future<bool> requestContactsPermission() async {
    final status = await Permission.contacts.status;
    if (status.isGranted) return true;

    final result = await Permission.contacts.request();
    if (result.isGranted) return true;

    if (result.isPermanentlyDenied) {
      await openAppSettings();
    }
    return false;
  }

  Future<bool> requestStoragePermission() async {
    if (await Permission.storage.request().isGranted) {
      return true;
    }
    return false;
  }

  Future<bool> checkAllPermissions() async {
    final contactsGranted = await requestContactsPermission();
    final storageGranted = await requestStoragePermission();
    return contactsGranted && storageGranted;
  }
}

5.5 数据库存储实现

class DatabaseHelper {
  static Database? _database;

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  Future<Database> _initDatabase() async {
    final path = join(await getDatabasesPath(), 'contact_backup.db');
    return await openDatabase(
      path,
      version: 1,
      onCreate: (db, version) async {
        await db.execute('''
          CREATE TABLE backup_records (
            id TEXT PRIMARY KEY,
            name TEXT NOT NULL,
            type TEXT NOT NULL,
            contact_count INTEGER NOT NULL,
            file_size INTEGER NOT NULL,
            created_at TEXT NOT NULL,
            file_path TEXT
          )
        ''');
      },
    );
  }

  Future<void> insertBackupRecord(BackupRecord record) async {
    final db = await database;
    await db.insert('backup_records', {
      'id': record.id,
      'name': record.name,
      'type': record.type.name,
      'contact_count': record.contactCount,
      'file_size': record.fileSize,
      'created_at': record.createdAt.toIso8601String(),
      'file_path': record.filePath,
    });
  }

  Future<List<BackupRecord>> getBackupRecords() async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query(
      'backup_records',
      orderBy: 'created_at DESC',
    );
    return maps.map((map) => BackupRecord(
      id: map['id'],
      name: map['name'],
      type: BackupType.values.firstWhere((t) => t.name == map['type']),
      contactCount: map['contact_count'],
      fileSize: map['file_size'],
      createdAt: DateTime.parse(map['created_at']),
      filePath: map['file_path'],
    )).toList();
  }
}

六、交互设计

6.1 联系人管理流程

系统通讯录联系人管理器联系人页用户系统通讯录联系人管理器联系人页用户打开应用加载联系人读取通讯录返回联系人列表显示联系人点击联系人显示详情面板编辑联系人更新联系人同步更新更新成功刷新列表

6.2 备份恢复流程

本地

云端

导出

选择备份类型

备份类型?

生成JSON文件

上传到服务器

选择格式

保存到本地

等待响应

生成VCF/CSV

保存记录

分享文件

显示成功

6.3 重复合并流程

发现重复

无重复

检测重复

显示列表

显示空状态

选择合并

确认合并

更新数据


七、扩展功能规划

7.1 后续版本规划

2024-01-072024-01-142024-01-212024-01-282024-02-042024-02-112024-02-182024-02-252024-03-032024-03-102024-03-172024-03-242024-03-312024-04-07基础UI框架 联系人管理 备份功能实现 重复检测开发 导入导出功能 分组管理完善 云端同步 多设备同步 智能整理 V1.0 基础版本V1.1 增强版本V1.2 进阶版本联系人备份工具开发计划

7.2 功能扩展建议

7.2.1 云端同步

同步功能:

  • 多设备实时同步
  • 版本历史管理
  • 冲突自动解决
  • 增量同步优化
7.2.2 智能整理

整理功能:

  • 自动识别重复
  • 智能分组建议
  • 信息补全提示
  • 批量编辑操作
7.2.3 隐私保护

保护功能:

  • 敏感信息加密
  • 访问密码保护
  • 隐私联系人隐藏
  • 安全删除擦除

八、注意事项

8.1 开发注意事项

  1. 权限申请:正确申请通讯录、存储等敏感权限

  2. 数据安全:联系人数据属于隐私信息,需妥善处理

  3. 性能优化:大量联系人时需优化加载和搜索性能

  4. 兼容性:适配不同Android/iOS版本的通讯录API

  5. 数据同步:确保本地数据与系统通讯录保持同步

8.2 常见问题

问题原因解决方案
权限被拒绝用户拒绝授权引导用户到设置开启
联系人加载慢数据量大实现分页加载
备份失败存储空间不足检查存储空间
导入失败文件格式错误验证文件格式
同步冲突多设备修改提供冲突解决选项

8.3 使用技巧

📱 联系人备份工具使用技巧 📱

备份管理

  • 定期备份联系人数据
  • 保留多个备份版本
  • 备份前检查存储空间
  • 重要联系人单独导出

重复整理

  • 定期检测重复联系人
  • 合并前仔细核对信息
  • 保留最完整的记录
  • 及时清理无效联系人

分组管理

  • 合理设置联系人分组
  • 重要联系人设为收藏
  • 定期整理分组归属
  • 使用搜索快速定位

九、运行说明

9.1 环境要求

环境版本要求
Flutter SDK>= 3.0.0
Dart SDK>= 2.17.0
鸿蒙OSAPI 21+
AndroidAPI 21+
iOS12.0+
Web浏览器Chrome 90+

9.2 依赖配置

pubspec.yaml 中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_contacts: ^1.0.0
  share_plus: ^7.0.0
  sqflite: ^2.0.0
  permission_handler: ^11.0.0
  path_provider: ^2.0.0
  path: ^1.8.0

9.3 权限配置

Android (android/app/src/main/AndroidManifest.xml):

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />

iOS (ios/Runner/Info.plist):

<key>NSContactsUsageDescription</key>
<string>需要访问通讯录以备份和管理联系人</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问存储以保存备份文件</string>

9.4 运行命令

# 查看可用设备
flutter devices

# 运行到Web服务器
flutter run -d web-server -t lib/main_contact_backup.dart --web-port 8147

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 -t lib/main_contact_backup.dart

# 运行到Android设备
flutter run -d android -t lib/main_contact_backup.dart

# 代码分析
flutter analyze lib/main_contact_backup.dart

十、总结

联系人备份工具应用通过多种备份方式、智能重复检测、灵活分组管理,帮助用户安全、便捷地管理手机联系人。应用支持本地备份、云端备份、导出文件三种备份方式,智能识别电话号码、姓名、邮箱重复的联系人,按家人、朋友、工作、同学、其他五类分组管理。

应用采用 Material Design 3 设计规范,以清新青绿为主色调,象征安全与可靠。通过本应用,希望能够帮助用户轻松管理通讯录,让联系人数据始终保持整洁有序。

联系人备份工具——守护您的通讯录安全


Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐