FlutterPlugin获取手机通讯录

用Android Studio创建flutter plugin项目:


FlutterPlugin获取手机通讯录_第1张图片
image.png

创建完成目录长这样:


FlutterPlugin获取手机通讯录_第2张图片
image.png

主要文件就三个,addressbook_plugin.dart里写flutter代码,AddressbookPlugin.m写iOS代码,安卓代码则是AddressbookPlugin.java

先看flutter代码
addressbook_plugin.dart:

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

class AddressBookPlugin {
  static const MethodChannel _channel =
      const MethodChannel('addressbook_plugin');

  static Future get addressBook async {
    final String contacts = await _channel.invokeMethod('getAddressBook');
    return contacts;
  }
}

addressbook_plugin是自定义的channel名,用来和原生进行通信的管道名,而getAddressBook则是自定义的方法名,原生根据方法名执行相应操作

接着看iOS代码(OC)
AddressbookPlugin:

#import "AddressbookPlugin.h"
#import 

@implementation AddressbookPlugin

+ (void)registerWithRegistrar:(NSObject*)registrar {
    FlutterMethodChannel* channel = [FlutterMethodChannel
                                     methodChannelWithName:@"addressbook_plugin"
                                     binaryMessenger:[registrar messenger]];
    AddressbookPlugin* instance = [[AddressbookPlugin alloc] init];
    [registrar addMethodCallDelegate:instance channel:channel];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    if ([@"getAddressBook" isEqualToString:call.method]) {
        // 通讯录
        [self getAddressBook:result];
    } else {
        result(FlutterMethodNotImplemented);
    }
}

- (void)getAddressBook:(FlutterResult)result {
    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    if (status == CNAuthorizationStatusNotDetermined) {
        CNContactStore *store = [[CNContactStore alloc] init];
        [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError*  _Nullable error) {
            if (error) {
                NSLog(@"授权失败");
                result(@"没有权限");
            } else {
                NSLog(@"成功授权");
                [self openContact:result];
            }
        }];
    } else if(status == CNAuthorizationStatusRestricted) {
        NSLog(@"用户拒绝");
        result(@"没有权限");
    } else if (status == CNAuthorizationStatusDenied) {
        NSLog(@"用户拒绝");
        result(@"没有权限");
    } else if (status == CNAuthorizationStatusAuthorized) { // 已经授权
        // 有通讯录权限 -- 进行下一步操作
        [self openContact:result];
    }
}

// 有通讯录权限 -- 进行下一步操作
- (void)openContact:(FlutterResult)result {
    NSMutableArray *contactsArr = [NSMutableArray array];
    // 获取指定的字段,并不是要获取所有字段,需要指定具体的字段
    NSArray *keysToFetch = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
    CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
    CNContactStore *contactStore = [[CNContactStore alloc] init];
    
    [contactStore enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
//        NSString *givenName = contact.givenName;
//        NSString *familyName = contact.familyName;
//        NSLog(@"givenName=%@, familyName=%@", givenName, familyName);
        // 拼接姓名
        NSString *nameStr = [NSString stringWithFormat:@"%@%@", contact.familyName, contact.givenName];
        
        NSArray *phoneNumbers = contact.phoneNumbers;
   
        for (CNLabeledValue *labelValue in phoneNumbers) {
            // 遍历一个人名下的多个电话号码
            CNPhoneNumber *phoneNumber = labelValue.value;
            NSString *string = phoneNumber.stringValue;
            
            // 去掉电话中的特殊字符
            string = [string stringByReplacingOccurrencesOfString:@"+86" withString:@""];
            string = [string stringByReplacingOccurrencesOfString:@"-" withString:@""];
            string = [string stringByReplacingOccurrencesOfString:@"(" withString:@""];
            string = [string stringByReplacingOccurrencesOfString:@")" withString:@""];
            string = [string stringByReplacingOccurrencesOfString:@" " withString:@""];
            string = [string stringByReplacingOccurrencesOfString:@" " withString:@""];
            
            NSLog(@"姓名=%@, 电话号码是=%@", nameStr, string);
            
            [contactsArr addObject:@{@"name": nameStr, @"phone": string}];
        }
    }];
    
    NSLog(@"共计%ld个号码", contactsArr.count);
    
    NSError *error = nil;
    NSData *contactsJsonData = [NSJSONSerialization dataWithJSONObject:contactsArr
                                                               options:kNilOptions
                                                                 error:&error];
    NSString *contactsJsonString = [[NSString alloc] initWithData:contactsJsonData
                                                         encoding:NSUTF8StringEncoding];
    NSLog(@"通讯录Json %@", contactsJsonString);
    
    result(contactsJsonString);
}

@end

在registerWithRegistrar方法中注册通道,在handleMethodCall代理方法中监听方法

上面代码在监听到getAddressBook方法时执行了获取通讯录的操作

获取通讯录使用了下面的系统库

#import 

到这里插件包就写完了,把整个插件包项目文件提交到github上就可以在其他项目中使用这个插件了

现在试试在其他项目中导入这个插件,新建一个项目,打开pubspec.yaml

在dependencies:下导入插件,需要以git路径形式导入,比如

addressbook_plugin:
    git: https://github.com/neechen/address_book_plugin.git
FlutterPlugin获取手机通讯录_第3张图片
image.png

点右上角Pub get导入插件

写一个获取通讯录的方法:

void _getAddressBook() async {
    try {
      contacts = await AddressBookPlugin.addressBook;
    } catch (e) {
      print(e);
    }

    if (contacts.length > 0) {
      setState(() {});
    }
  }

与原生通信的方法都是异步的,这里要用async/await

ios项目中info.plist文件需要加入通讯录权限,否则会失败:


image.png

main.dart代码:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '通讯录插件测试',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: '通讯录插件测试'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  String contacts = '';

  void _getAddressBook() async {
    try {
      contacts = await AddressBookPlugin.addressBook;
    } catch (e) {
      print(e);
    }

    if (contacts.length > 0) {
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Text(
          '$contacts',
          style: TextStyle(
            fontSize: 15,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _getAddressBook,
        child: Icon(Icons.contacts),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

效果:


FlutterPlugin获取手机通讯录_第4张图片
image.png

你可能感兴趣的:(FlutterPlugin获取手机通讯录)