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

4 阅读2分钟

接上篇: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 鸿蒙适配的开发者们,让大家在鸿蒙生态的开发中更加得心应手。

六、参考

七、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个。

地址:atomgit.com/nutpi

gitcode.com/nutpi

官网:www.nutpi.net/