不需要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
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({});
}
static Map<String, dynamic> parseMap(String jsonString) {
try {
Map<String, dynamic> map = jsonDecode(jsonString);
return map;
} catch (e) {
debugPrint("Failed to parse app parseMap: $e");
return {};
}
}
static List<Map<String, dynamic>> parseList(String jsonString) {
try {
List<Map<String, dynamic>> appList =
jsonDecode(jsonString).cast<Map<String, dynamic>>();
return appList;
} catch (e) {
print("Failed to parse list: $e");
return [];
}
}
}