Flutter 插件实现从通讯录选取单个联系人信息

43 阅读1分钟

不需要READ_CONTACT权限

原生插件代码

依赖

implementation 'com.google.code.gson:gson:2.10.1'
implementation 'androidx.activity:activity-ktx:1.5.0'

插件代码实现

package com.phone.flutter_contact_picker_plugin

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import android.app.Activity
import android.content.pm.PackageManager
import android.net.Uri
import com.google.gson.Gson
import androidx.core.content.ContextCompat
import androidx.core.app.ActivityCompat
import io.flutter.plugin.common.MethodChannel.Result
import android.provider.ContactsContract
import android.content.Intent
import io.flutter.plugin.common.PluginRegistry

/** FlutterContactPickerPlugin */
class FlutterContactPickerPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
    PluginRegistry.ActivityResultListener {

    private val requestPickContactInfo = 1002

    private lateinit var channel: MethodChannel
    private lateinit var activity: Activity
    private var pendingResult: Result? = null

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_contact_picker_plugin")
        channel.setMethodCallHandler(this)
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        if (call.method == "pickContactInfo") {
            pendingResult = result
            val intent = Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI)
            activity?.startActivityForResult(intent, requestPickContactInfo)
        } else {
            result.notImplemented()
        }
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
        binding.addActivityResultListener(this)
    }

    override fun onDetachedFromActivityForConfigChanges() {
        onDetachedFromActivity()
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        onAttachedToActivity(binding)
    }
    override fun onDetachedFromActivity() {
    }


    override  fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?): Boolean {
        if (requestCode==requestPickContactInfo){
            var contactInfo : ContactInfo?= null
            if (intent!=null&&resultCode == Activity.RESULT_OK){
                val contactUri: Uri? = intent?.data
                if (contactUri!=null){
                    val projection = arrayOf(
                        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                        ContactsContract.CommonDataKinds.Phone.NUMBER
                    )
                    val contactCursor= activity.contentResolver.query(contactUri!!, projection, null, null, null)
                    if (contactCursor != null){
                        contactCursor?.moveToFirst()?.let {
                            // 获取联系人姓名
                            val displayName =
                                contactCursor.getString(contactCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))    ?: ""
                            // 获取联系人电话号码
                            val phoneNumber =
                             contactCursor.getString(contactCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER))    ?: ""
                            contactInfo=  ContactInfo(name = displayName, phone = phoneNumber)
                        }
                        contactCursor.close()
                    }
                }
            }

            val gson = Gson()
            if (contactInfo==null){
                contactInfo=ContactInfo(name = "", phone = "")
            }
            pendingResult?.success(gson.toJson(contactInfo!!))
            pendingResult = null
        }
        return true
    }
}

flutter 调用

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class FlutterContactPickerPlugin {
  static const MethodChannel methodChannel =
      MethodChannel('flutter_contact_picker_plugin');

  ///从通讯录选取单个联系人信息
  static Future<Map<String, dynamic>> pickContactInfo() async {
    try {
        String jsonString = await methodChannel.invokeMethod('pickContactInfo');
        Map<String, dynamic> map = parseMap(jsonString);
        return map;
    } on PlatformException catch (e) {
      debugPrint(e.message);
    }
    return Future.value({});
  }

  ///解析JSON字符串 "{"name":"hhh","phone":"1234567"}"成String, dynamic>
  static Map<String, dynamic> parseMap(String jsonString)  {
    try {
      // 使用 jsonDecode 函数将 JSON 字符串转换为 Map<String, dynamic>
      Map<String, dynamic> map = jsonDecode(jsonString);
      return map;
    } catch (e) {
      // 如果 JSON 字符串无效或转换过程中发生错误,打印错误信息
      debugPrint("Failed to parse app parseMap: $e");
      return {};
    }
  }

  ///列表JSON字符串
  static List<Map<String, dynamic>> parseList(String jsonString) {
    try {
      // 使用 jsonDecode 函数将 JSON 字符串转换为 List<Map<String, dynamic>>
      List<Map<String, dynamic>> appList =
          jsonDecode(jsonString).cast<Map<String, dynamic>>();
      return appList;
    } catch (e) {
      // 如果 JSON 字符串无效或转换过程中发生错误,打印错误信息
      print("Failed to parse  list: $e");
      return [];
    }
  }
}