[Flutter] 연락처 가져오기

soonmuu·2023년 2월 22일
0

flutter

목록 보기
9/11

구현할 기능

  • 연락처 리스트에서 원하는 연락처 클릭시 해당 정보 가져오기

전체적인 흐름

  1. 연락처 접근 권한 얻기
  2. 권한 얻고난 후 연락처 데이터 가져오기
  3. 데이터 리스트로 출력 및 필요한 기능 구현

사용 패키지

사용권한 permission_handler
https://pub.dev/packages/permission_handler/install

연락처 접근 contacts_service
https://pub.dev/packages/contacts_service/install

android 세팅

android\app\src\main\AndroidManifest.xml
아래 허용 추가
연락처 수정을 할 것이 아니라면 WRITE_CONTACTS는 빼도된다

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
  	<!--추가-->
    <uses-permission android:name="android.permission.READ_CONTACTS" />  
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />  
  
  ...

ios 세팅

ios/Podfile
target 'Runner' do블럭 아래 post_install 블럭에 접근 권한을 추가해준다

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

## 수정부분
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',
        
         ## 연락처 접근권한
         ## dart: PermissionGroup.contacts
        'PERMISSION_CONTACTS=1',
         
         ## dart: PermissionGroup.camera
         # 'PERMISSION_CAMERA=1',
      ]
    end
  end
 end 

아래 permission_handler readme를 보면 다양한 접근 권한 예시가 있다
https://pub.dev/packages/permission_handler

ios\Runner\Info.plist
연락처 권한을 얻을때 표시할 메시지를 같이 작성한다

<key>NSContactsUsageDescription</key>  
<string>연락처 권한이 필요합니다.</string>  

flutter에서 사용하기

연락처 가져오기

  • _contacts변수를 선언할때 List<Contact>? 를 사용해서 사실 null로 초기화를 안해줘도 되는데 ios에서 사용할때는 null safety오류가 떠서 초기화를 해줬다
 List<Contact>? _contacts = null; // ios 오류때문에 초기화 해야함

  // 연락처 가져오기 기능
  Future<void> getContacts() async {
    if (await Permission.contacts.request().isGranted) {
      // 접근권한을 얻을 시 실행되는 기능
      var contacts = await ContactsService.getContacts(
        withThumbnails: false,
      );

      // 가져온 연락처 목록 변수에 할당
      setState(() {
        _contacts = contacts;
      });

      // 연락처 목록 모달 열기
      showModal();

      // Iterate over the contacts and look for the phone number
    } else {
      // Permission denied, handle the error
      // 연락처 접근권한을 얻지 못하면 상황에따라 알림 처리가 필요
    }
  }

연락처 리스트 모달 생성

앞서 가져온 연락처 데이터를 ListView를 사용해 리스트로 출력한다

** 주의할점 - 번호는 배열형태로 들어온다

  • 연락처 1개당 여러개의 전화번호를 등록할 수 있기 때문에 불러올때 순서를 지정해 불러와 줘야한다.
  • 또한 연락처가 없을 경우 오류가 날 수 있음으로 연락처가 없는 경우도 조건을 만들어줘야한다.
	List<Contact> list = {연락처 데이터} // 전체데이터
    
    list.phones // 출력시 아래와 같이 출력
    /*
    	[
        	Item(
            	label: 'phone',
                value: '123456789',
            ),
            Item(
            	label: 'phone',
                value: '123456789',
            ),
        ]
    */
  • 나같은 경우는 첫번째 연락처를 기본으로 불러오도록 하였다
	var phoneNumber = list.phones!.isNotEmpty
                            ? c.phones![0].value.toString()
                            : '연락처가 없습니다';

전체코드

 // 연락처 모달 오픈
  Future<void> showModal() async {
    showDialog(
      context: context,
      builder: (context) {
        return Dialog(
        // 목록 생성
          child: ListView.builder(
            itemCount: _contacts?.length,
            itemBuilder: (BuildContext context, int index) {
              Contact c = _contacts!.elementAt(index); // 연락처 element
              var userName = c.displayName; // 연락처 이름
              // 연락처 번호
             	var phoneNumber = c.phones!.isNotEmpty
                            ? c.phones![0].value.toString()
                            : '연락처가 없습니다';
              
              // 버튼으로 렌더링
              return TextButton(
                onPressed: () {
                  // 연락처 누를시 실행할 함수
                  _phoneNumberController.text = phoneNumber.toString();
                  // 모달 닫기
                  Navigator.of(context).pop();
                },
                child: Text(userName ?? ""),
              );
            },
          ),
        );
      },
    );
  }

결과적으로 '연락처 가져오기' 버튼을 누를 때 아래와 같이 실행할 수 있다

  if (_contacts == null) {
     getContacts(); // 최초로 가져오기
  } else {
     showModal(); // 한번 가져온 후 실행
  }

전체코드

import 'package:permission_handler/permission_handler.dart';
import 'package:contacts_service/contacts_service.dart';

class MyWidget extends StatefulWidget {
  const MyWidget({super.key});

  
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  List<Contact>? _contacts = null; // ios 오류때문에 초기화 해야함

  // 연락처 가져오기 기능
  Future<void> getContacts() async {
    if (await Permission.contacts.request().isGranted) {
      var contacts = await ContactsService.getContacts(
        withThumbnails: false,
      );

      // 가져온 연락처 목록 변수에 할당
      setState(() {
        _contacts = contacts;
      });

      // 연락처 목록 모달 열기
      showModal();

      // Iterate over the contacts and look for the phone number
    } else {
      // Permission denied, handle the error
    }
  }
  
   // 연락처 모달 오픈
  Future<void> showModal() async {
    showDialog(
      context: context,
      builder: (context) {
        return Dialog(
          child: ListView.builder(
            itemCount: _contacts?.length,
            itemBuilder: (BuildContext context, int index) {
              Contact c = _contacts!.elementAt(index);
              var userName = c.displayName;
              var phoneNumber = c.phones?.first.value;
              return TextButton(
                onPressed: () {
                  _phoneNumberController.text = phoneNumber.toString();
                  Navigator.of(context).pop();
                },
                child: Text(userName ?? ""),
              );
            },
          ),
        );
      },
    );
  }
  
  
  Widget build(BuildContext context) {
    return Container(
    	child: ElevatedButton(
          onPressed: () {
            if (_contacts == null) {
              getContacts(); // 최초로 가져오기
            } else {
              showModal(); // 한번 가져온 후 실행
            }
          },
          child: Text(
            '연락처에서 선택',
            style: TextStyle(
                fontSize: 13,
               color: Theme.of(context).primaryColorDark,
            ),
          ),
       ),
    );
  }
}
profile
프론트엔드

0개의 댓글

관련 채용 정보