如何用Flutter+Node.js+MongoDB实现类WhatsApp通讯录好友检测
实现通讯录联系人检测功能的方案
整体流程
Flutter端获取并标准化通讯录手机号 → 发送至Node.js后端 → 后端查询MongoDB匹配已注册用户 → 返回结果给Flutter端展示
1. Flutter端处理
1.1 权限申请
- Android:在
AndroidManifest.xml中添加权限<uses-permission android:name="android.permission.READ_CONTACTS"/> - iOS:在
Info.plist中添加权限描述<key>NSContactsUsageDescription</key> <string>需要访问通讯录来检测已注册的联系人</string>
1.2 获取并标准化通讯录手机号
使用flutter_contacts获取通讯录后,必须统一手机号格式(比如去除非数字字符、添加国家码),避免因格式不一致导致查询失败:
import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; // 获取并处理通讯录手机号(去重+标准化) Future<List<String>> getStandardizedContactNumbers() async { if (!await FlutterContacts.requestPermission()) { return []; } final contacts = await FlutterContacts.getContacts(withProperties: true); final Set<String> uniqueNumbers = {}; for (final contact in contacts) { for (final phone in contact.phones) { // 移除所有非数字字符 final cleanNumber = phone.number.replaceAll(RegExp(r'\D'), ''); // 标准化为带国家码的格式(示例为+86,可根据用户地区动态调整) final standardized = '+86$cleanNumber'; uniqueNumbers.add(standardized); } } return uniqueNumbers.toList(); } // 发送至后端查询已注册用户 Future<List<Map<String, dynamic>>> queryRegisteredUsers(List<String> numbers) async { final response = await http.post( Uri.parse('http://你的后端域名/api/check-contacts'), headers: {'Content-Type': 'application/json'}, body: json.encode({'phoneNumbers': numbers}), ); if (response.statusCode == 200) { return List<Map<String, dynamic>>.from(json.decode(response.body)); } else { throw Exception('查询联系人失败'); } }
2. Node.js后端实现
2.1 接口编写(基于Express+Mongoose)
接收前端传来的手机号列表,查询MongoDB中匹配的已注册用户:
const express = require('express'); const router = express.Router(); const User = require('../models/User'); router.post('/check-contacts', async (req, res) => { try { const { phoneNumbers } = req.body; // 仅查询手机号在列表中的用户,返回必要字段(避免泄露敏感信息) const registeredUsers = await User.find( { phone: { $in: phoneNumbers } }, { phone: 1, username: 1, avatar: 1, _id: 0 } ); res.json(registeredUsers); } catch (err) { console.error(err); res.status(500).json({ error: '服务器内部错误' }); } }); module.exports = router;
3. MongoDB优化
为了提升$in查询的速度,必须给用户集合的phone字段添加索引:
const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ phone: { type: String, required: true, unique: true }, username: { type: String, required: true }, avatar: String, // 其他字段... }); // 添加单字段索引,加速手机号查询 userSchema.index({ phone: 1 }); module.exports = mongoose.model('User', userSchema);
4. 隐私优化(可选)
如果担心通讯录隐私泄露,可以对手机号进行哈希处理后再传输:
- Flutter端哈希手机号:
import 'dart:convert'; import 'package:crypto/crypto.dart'; String hashPhone(String number) { return sha256.convert(utf8.encode(number)).toString(); } - 后端存储哈希后的手机号,查询时用哈希后的列表匹配,避免明文传输和存储用户通讯录信息。
内容的提问来源于stack exchange,提问作者Vivek Shah
相关产品推荐
相关产品推荐

