接上篇:Flutter插件鸿蒙化,flutter_native_contact_picker_plus联系人选择器的跨平台适配实践【上篇】
4.ios侧处理
类似ios侧处理这边的Contact,并返回
var data = Dictionary<String, Any>()
data["fullName"] = CNContactFormatter.string(from: contact, style: CNContactFormatterStyle.fullName)
let numbers: Array<String> = 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();
}
}
}
参考:developer.huawei.com/consumer/cn…
四、编写 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](gitcode.com/openharmony… FlutterChannel.md)
- [开发module](gitcode.com/openharmony… module.md)
- 开发package
- 开发plugin
- [开发FFI plugin](gitcode.com/openharmony… 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个。