Jin's Dev Story

[Flutter] 사용자 연락처 불러오기 본문

Web & Android/Flutter

[Flutter] 사용자 연락처 불러오기

woojin._. 2023. 9. 12. 10:51

패키지 설치

1. pubspec.yaml 파일에 dependencies: 를 찾아 contacts_service: ^0.6.3 을 입력

dependencies:
  flutter:
    sdk: flutter
  permission_handler: ^8.3.0
  contacts_service: ^0.6.3

2. 옆에 전구 모양 아이콘 클릭하여 pub get 실행

3. import 'package:contacts_service/contacts_service.dart'; 를 main.dart 파일 가장 상단에 추가

 

연락처 다루는 패키지

  • 외부 패키지로 복붙해서 사용하면 되는 코드들
  • list로 모든 연락처 가져옴
    var contacts = await ContactsService.getContacts();
  • 위의 코드는 연락처에 저장된 썸네일 이미지도 다 가져오기 때문에 느림
  • 아래 코드는 썸네일 제외하고 가져올 수 있는 코드
  • await이 붙어서 오래 걸리면 다음 줄을 실행하라는 코드
    var contacts = await ContactsService.getContacts(withThumbnails: false);
  • 첫 연락처의 이름 부분을 출력해보는 코드
    var contacts = await ContactsService.getContacts(withThumbnails: false);
    print(contacts[0].givenName)
  • 실제 연락처가 폰으로 추가되는 코드
    • new 키워드 생략 가능
    • .givenName → 이름
    • .familyName → 성
var newContact = new Contact();
newContact.givenName = '민수';
await ContactsService.addContact(newContact);

 

실제 연락처를 list로 보여주기

💡 가져온 연락처들을 ListView.builder() 여기에 보여주고 싶으면?

  • name이라는 state 안의 자료 개수만큼 ListView를 생성하고 있기 때문에 name이라는 변수에다가 contacts를 넣으면 됨
    (getPermission 함수 안쪽)
    
    var contacts = await ContactsService.getContacts(withThumbnails: false);
    print(contacts[0].givenName)
    
    setState(() {
      name = contacts;
    });

→ 에러 발생 : A value of type 'List' can't be assigned to a variable of type 'List'

  • 변수를 만들 때 문자만 집어넣었다면 앞으로도 문자만 가능
  • 숫자인 경우 숫자만 가능
  • 방법은 4가지
  1. name 변수를 만들 때 리스트를 비워두어 dynamic 타입이 되도록 하기
var name = ['영희', '횟집', '미용실']; 이거를
var name = []; 이걸로 고쳤습니다
  • ListView.builder 쪽에도 name[i]가 아닌 name[i].givenName으로 변경해야 함
    body: ListView.builder(
                  itemCount: name.length,
                  itemBuilder: (c, i) {
                    return ListTile(
                      leading: Icon(Icons.account_circle_rounded),
                      title: Text(name[i].givenName),
                    );
                  },
                )

2. Contact라는 자료가 들어오는 name 변수로 만들기

List<Contact> name = [];

3. 타입 캐스팅 사용

  • 빠르지만 타입을 사기치는 거라 좋은 관습이 아님

4. Union type 사용

  • 패키지 설치 필요

예제

  • Dialog에 이름 입력하고 완료 누르면 실제 그 이름으로 연락처가 추가되는 기능과 ListView 안의 목록에도 새로운 이름이 보이도록 하기
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:contacts_service/contacts_service.dart';

void main() {
  runApp(
      MaterialApp(
        home: MyApp()
      )
  );
}

class MyApp extends StatefulWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  getPermission() async {
    var status = await Permission.contacts.status;
    if (status.isGranted) {  // 허락된 경우
      print('허락됨');
      var contacts = await ContactsService.getContacts();
      // print(contacts[0].givenName);

      setState(() {
        name = contacts;
      });

    } else if (status.isDenied) {  // 거절된 경우
      print('거절됨');
      Permission.contacts.request();   // 현재 거절된 상태니 팝업창 띄워달라는 코드
      openAppSettings();
    }
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getPermission();
  }

  var total = 3;
  var like = [0, 0, 0];
  var name = [];

  addName(a) {
    setState(() {
      name.add(a);
    });
  }

  addOne() {
    setState(() {
      total++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              showDialog(context: context, builder: (context) {
                return DialogUI(addOne: addOne, addName : addName );
              });
            },
          ),
          appBar: AppBar( title: Text(total.toString()), actions: [
            IconButton(onPressed: () { getPermission();}, icon: Icon(Icons.contacts))
          ],),
          body: ListView.builder(
              itemCount: name.length,
              itemBuilder: (c, i) {
                return ListTile(
                  leading: Icon(Icons.account_circle_rounded),
                  title: Text(name[i].givenName),
                );
              },
            )
        );
  }
}

class DialogUI extends StatelessWidget {
  DialogUI({Key? key, this.addOne, this.addName}) : super(key: key);
  final addOne, addName;
  var inputData = TextEditingController();
  var inputData2 = '';
  @override
  Widget build(BuildContext context) {
    return Dialog(
      child: SizedBox(
        width: 300,
        height: 300,
        child: Column(
          children: [
            TextField(controller: inputData),
            Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                TextButton(child: Text('취소'), onPressed: (){ Navigator.pop(context);}),
                TextButton(
                    child: Text('완료'),
                    onPressed: () {
                      addOne();
                      var newContact = Contact();
                      newContact.givenName = inputData.text;  //새로운 연락처 만들기
                      ContactsService.addContact(newContact);  //실제로 연락처에 집어넣기
                      addName(newContact);
                    })
              ],
            )
          ],
        ),
      )
    );
  }
}