> 技术文档 > Flutter插件鸿蒙化,flutter_native_contact_picker_plus联系人选择器的跨平台适配实践【下篇】

Flutter插件鸿蒙化,flutter_native_contact_picker_plus联系人选择器的跨平台适配实践【下篇】

接上篇:Flutter插件鸿蒙化,flutter_native_contact_picker_plus联系人选择器的跨平台适配实践【上篇】

4.ios侧处理

类似ios侧处理这边的Contact,并返回

 var data = Dictionary() data[\"fullName\"] = CNContactFormatter.string(from: contact, style: CNContactFormatterStyle.fullName) let numbers: Array = contact.phoneNumbers.compactMap { $0.value.stringValue as String } data[\"phoneNumbers\"] = numbers result(data)

5.ArkTS处理单选联系人

 contact.selectContacts({ isMultiSelect: false }, (err: BusinessError, data) => { if (err) { console.error(`Failed to select Contacts. Code: ${err.code}, message: ${err.message}`); return; } const contactInfo = new Map<string, string | string[]>(); if (data && data.length > 0) { const contact: contact.Contact = data[0]; contactInfo.set(\"fullName\", contact.name?.fullName || \"\"); const phoneNumbers: string[] = contact.phoneNumbers?.map(item => item.phoneNumber) || []; contactInfo.set(\"phoneNumbers\", phoneNumbers); if (contact.emails && contact.emails.length > 0) { const emails: string[] = contact.emails.map(item => item.email); contactInfo.set(\"emails\", emails); } } let jsonObject: Record<string, Object> = {}; contactInfo.forEach((value, key) => { if (key !== undefined && value !== undefined) { jsonObject[key] = value; } }) console.info(`Succeeded in selecting Contacts. data->${JSON.stringify(jsonObject)}`); result.success(jsonObject) });

6.ArkTS处理多选联系人

多选的处理方式

7.完整的代码

import { FlutterPlugin, FlutterPluginBinding, MethodCall, MethodCallHandler, MethodChannel, MethodResult,} from \'@ohos/flutter_ohos\';import { contact } from \'@kit.ContactsKit\';import { BusinessError } from \'@kit.BasicServicesKit\';/** FlutterNativeContactPickerPlusPlugin **/export default class FlutterNativeContactPickerPlusPlugin implements FlutterPlugin, MethodCallHandler { private channel: MethodChannel | null = null; constructor() { } getUniqueClassName(): string { return \"FlutterNativeContactPickerPlusPlugin\" } onAttachedToEngine(binding: FlutterPluginBinding): void { this.channel = new MethodChannel(binding.getBinaryMessenger(), \"flutter_native_contact_picker_plus\"); this.channel.setMethodCallHandler(this) } onDetachedFromEngine(binding: FlutterPluginBinding): void { if (this.channel != null) { this.channel.setMethodCallHandler(null) } } onMethodCall(call: MethodCall, result: MethodResult): void { console.info(\" call.method 被调用\" + JSON.stringify(call.method)); if (call.method == \"getPlatformVersion\") { result.success(\"OpenHarmony ^ ^ \") } else if (call.method == \"selectContact\") { contact.selectContacts({ isMultiSelect: false }, (err: BusinessError, data) => { if (err) { console.error(`Failed to select Contacts. Code: ${err.code}, message: ${err.message}`); return; } const contactInfo = new Map<string, string | string[]>(); if (data && data.length > 0) { const contact: contact.Contact = data[0]; contactInfo.set(\"fullName\", contact.name?.fullName || \"\"); const phoneNumbers: string[] = contact.phoneNumbers?.map(item => item.phoneNumber) || []; contactInfo.set(\"phoneNumbers\", phoneNumbers); if (contact.emails && contact.emails.length > 0) { const emails: string[] = contact.emails.map(item => item.email); contactInfo.set(\"emails\", emails); } } let jsonObject: Record<string, Object> = {}; contactInfo.forEach((value, key) => { if (key !== undefined && value !== undefined) { jsonObject[key] = value; } }) console.info(`Succeeded in selecting Contacts. data->${JSON.stringify(jsonObject)}`); result.success(jsonObject) }); } else if (call.method == \"selectContacts\") { console.info(\" selectContacts 被调用\"); contact.selectContacts({ isMultiSelect: true }, (err: BusinessError, data) => { if (err) { console.error(`Failed to select Contacts. Code: ${err.code}, message: ${err.message}`); result.error(err.code.toString(), err.message, null); return; } console.info(`Succeeded in selecting Contacts. data->${JSON.stringify(data)}`); const selectedContacts: contact.Contact[] = []; if (data && data.length > 0) { for (const contact of data) { const contactInfo = new Map<string, string | string[]>(); contactInfo.set(\"fullName\", contact.name?.fullName || \"\"); const phoneNumbers: string[] = contact.phoneNumbers?.map(item => item.phoneNumber) || []; contactInfo.set(\"phoneNumbers\", phoneNumbers); if (contact.emails && contact.emails.length > 0) {  const emails: string[] = contact.emails.map(item => item.email);  contactInfo.set(\"emails\", emails); } let jsonObject: Record<string, Object> = {}; contactInfo.forEach((value, key) => {  if (key !== undefined && value !== undefined) { jsonObject[key] = value;  } }); selectedContacts.push(jsonObject); } } console.info(`Succeeded in selecting Contacts. data->${JSON.stringify(selectedContacts)}`); result.success(selectedContacts); }); } else { result.notImplemented(); } }}

参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-inner-application-uiabilitycontext#uiabilitycontextterminateself-1和https://gitcode.com/openharmony-sig/flutter_contacts/tree/master/ohos/src/main/ets/components

四、编写 Example

1. 创建 Example 应用

在插件根目录下创建一个名为 example 的文件夹,用于存放示例应用。在 example 文件夹中,创建一个鸿蒙平台的 Flutter 应用,用于验证插件功能。

2. 签名与运行

使用 Deveco Studio 打开 example > ohos 目录,单击 File > Project Structure > Project > Signing Configs,勾选 Automatically generate signature,等待自动签名完成。然后运行以下命令:

flutter pub get flutter build hap --debug

如果应用正常启动,说明插件适配成功。如果没有,欢迎大家联系坚果派一起支持。

五、总结

通过以上步骤,我们成功地将 flutter_native_contact_picker 三方库适配到了鸿蒙平台。这个过程涉及到了解插件的基本信息、配置开发环境、创建鸿蒙模块、编写原生代码以及测试验证等多个环节。希望这篇博客能够帮助到需要进行 flutter_native_contact_picker 鸿蒙适配的开发者们,让大家在鸿蒙生态的开发中更加得心应手。

六、参考

  • [如何使用Flutter与OpenHarmony通信 FlutterChannel](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/如何使用Flutter与OpenHarmony通信 FlutterChannel.md)
  • [开发module](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/如何使用混合开发 module.md)
  • 开发package
  • 开发plugin
  • [开发FFI plugin](https://gitcode.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/04_development/开发FFI plugin.md)
  • developing-packages
  • 适配仓库地址

七、FAQ

如何将Map转换为JSON字符串

可以将Map转成Record后,再通过JSON.stringify()转为JSON字符串。示例如下

 const contactInfo = new Map<string, string | string[]>(); if (data && data.length > 0) { const contact: contact.Contact = data[0]; contactInfo.set(\"fullName\", contact.name?.fullName || \"\"); const phoneNumbers: string[] = contact.phoneNumbers?.map(item => item.phoneNumber) || []; contactInfo.set(\"phoneNumbers\", phoneNumbers); if (contact.emails && contact.emails.length > 0) { const emails: string[] = contact.emails.map(item => item.email); contactInfo.set(\"emails\", emails); } } let jsonObject: Record<string, Object> = {}; contactInfo.forEach((value, key) => { if (key !== undefined && value !== undefined) { jsonObject[key] = value; } }) console.info(`Succeeded in selecting Contacts. data->${JSON.stringify(jsonObject)}`);

如何判断是鸿蒙平台

import \'dart:io\'; Platform.operatingSystem == \'ohos\';

八、使用示例

import \'package:flutter/material.dart\';import \'package:flutter_native_contact_picker_plus/flutter_native_contact_picker_plus.dart\';void main() { runApp(const MyApp());}class MyApp extends StatefulWidget { const MyApp({super.key}); @override MyAppState createState() => MyAppState();}class MyAppState extends State<MyApp> { final FlutterContactPickerPlus _contactPicker = FlutterContactPickerPlus(); List<Contact>? _contacts; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text(\'Contact Picker Example App\'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[  MaterialButton( color: Colors.blue, child: const Text(\"Single\"), onPressed: () async {  Contact? contact = await _contactPicker.selectContact();  setState(() {  _contacts = contact == null ? null : [contact];  }); },  ),  MaterialButton( color: Colors.blue, child: const Text(\"Multiple\"), onPressed: () async {  final contacts = await _contactPicker.selectContacts();  setState(() {  _contacts = contacts;  }); },  ),  if (_contacts != null) ..._contacts!.map(  (e) => Text(e.toString()), ) ], ), ), ), ); }}

九、坚果派

坚果派由坚果等人创建,团队拥有若干华为HDE,以及若干其他领域的三十余位万粉博主运营。专注于分享的技术包括HarmonyOS/OpenHarmony,ArkUI-X,元服务,服务卡片,华为自研语言,BlueOS操作系统、团队成员聚集在北京、上海、广州、深圳、南京、杭州、苏州、宁夏等地。 聚焦“鸿蒙原生应用”、“智能物联”和“AI赋能”、“人工智能”四大技术领域,依托华为开发者专家等强大的技术团队,以及涵盖需求、开发、测试、运维于一体的综合服务体系,赋能文旅、媒体、社交、家居、消费电子等行业客户,帮助开发者实现价值提升。 目前上架鸿蒙原生应用18款,三方库80个。

地址:https://atomgit.com/nutpi

https://gitcode.com/nutpi

官网:https://www.nutpi.net/