폰에 저장된 연락처 몰래 가져오는 법 & 타입시스템
- 연락처를 꺼내는 방법으로는
- 패키지를 하나 설치해야 함
- pubspec.yaml에서 contacts_service를 설치하기!
- 물론 버전은 다를 수 있지만 contacts_service: ^0.6.3 작성 후 전구에서 pub get을 해주기
dependencies:
flutter:
sdk: flutter
permission_handler: ^8.3.0
contacts_service: ^0.6.3
import 'package:contacts_service/contacts_service.dart';
- 설치를 한 다음엔 무조건 실행되고 있는 프로그램을 중지하고 재실행을 시켜야함!!
- 이후 ContactsService.getContacts() 로 연락처 리스트를 가져올 수 있다.
- 여기서 await을 추가해준 이유는 print()를 실행 시까지 해당 함수가 완료되지 못하면 에러가 발생하기 때문!
- 배열로 값이 들어 오기에 배열만 잘 다루면 원하는 값을 가져올 수 있다.
- getPermission() async{ var status = await Permission.contacts.status; // 연락처 권한을 주었는지 대한 여부 if (status.isGranted) { print('허락됨'); var contacts = await ContactsService.getContacts(); print(contacts[0].givenName); }
- 또한 해당 함수 실행시 연락처에 값을 추가하고자 한다면
- 클래스로 부터 객체를 생성 후 추가할 수 있는데
- 여기서 원래 클래스로부터 인스턴스를 생성할 때 new를 붙여줘야 하지만
- flutter에서는 붙이지 않아도 된다고 한다.
getPermission() async{
var status = await Permission.contacts.status; // 연락처 권한을 주었는지 대한 여부
if (status.isGranted) {
print('허락됨');
var contacts = await ContactsService.getContacts();
print(contacts[0].givenName);
var newPerson = Contact();
newPerson.givenName = '간주';
newPerson.familyName = '중';
await ContactsService.addContact(newPerson);
}
- 이후 현재 반복문으로 보여지고 있는 목록을 연락처에 있는 사람들로 대체하기
- 여기서 문제는 Dart는 타입을 꼭 지켜줘야하는 TypeScript 와 유사하기에
- 타입을 꼭 지켜줘야 한다.
- 그래서 해결책으로는 아래와 같다.
- 타입 캐스팅(좋지 못한 방법이라고 한다)
- Union Type ( 변수 하나에 타입 여러 개 설정 가능, 설치 후 사용하면 된다고 함)
- 기존 배열을 빈 리스트로 만들어 type을 List<dynamic>으로 만들어주기
- dynamic은 어떠한 타입도 가능하다는 것을 의미
- 배열 생성 시 미리 타입을 명시할 수 도 있음
- List<int> number = [1,2,3,4,5]
- 우선 강의에서는 List<dynamic>으로 빈 리스트만 가지고 있는 리스트를 생성 후 연락처에 있는 데이터를 list에 setState로 담아주기
- 아래 코드는 현재 버튼을 클릭하게 되면 연락처에 있는 유저의 이름을 보여주도록 하는 코드
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({super.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();
setState(() {
person = contacts;
});
} else if (status.isDenied) {
print('거절됨');
Permission.contacts.request(); // 허락해달라고 팝업띄우는 코드
}
}
var a = 1;
var total = 3;
var person = [];
// var cnt = [0, 0, 0];
var title = 'Contact';
changeNumber(){
setState(() {
total++;
});
}
changeState(value){
setState(() {
person.add(value);
});
}
deleteState(idx){
setState(() {
person.removeAt(idx);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: (){
showDialog(context: context, builder: (context){
return Dialog(
child: Modal(state: title, changeNumber: changeNumber, changeState:changeState)
);
});
},
),
appBar: AppBar(title: Text(person.length.toString()),actions: [
IconButton(onPressed: (){
getPermission();
}, icon: Icon(Icons.contacts))
],),
body: ListView.builder(
itemCount: person.length,
itemBuilder: (c,i){
return ListTile(
leading: Icon(Icons.person),
title: Text(person[i].givenName)
);
}
),
);
}
}
숙제
- 모달창에서 완료를 누르면 입력한 이름이 연락처에 추가되도록 하기!
- 해결 방법으로는 우선 모달창으로 getPermission 메서드를 전달해서 연락처에 추가 후 바로 person 리스트가 연락처에 있는 목록을 다시 갱신되도록 만들기!
- 그리고 모달창에서는 Contact 인스턴스를 생성 후
현재 입력된 input 데이터 값을 해당 인스턴스의 givenName 에 넣고 연락처에 담아주기!
- 이때 로직의 순서대로 흘러갈 수 있도록 하기 위해 async, awiat을 사용함
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({super.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();
setState(() {
person = contacts;
});
} else if (status.isDenied) {
print('거절됨');
Permission.contacts.request(); // 허락해달라고 팝업띄우는 코드
}
}
var a = 1;
var total = 3;
var person = [];
// var cnt = [0, 0, 0];
var title = 'Contact';
changeNumber(){
setState(() {
total++;
});
}
changeState(value){
setState(() {
person.add(value);
});
}
deleteState(idx){
setState(() {
person.removeAt(idx);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: (){
showDialog(context: context, builder: (context){
return Dialog(
child: Modal(state: title, changeNumber: changeNumber, changeState:changeState, getPermission:getPermission)
);
});
},
),
appBar: AppBar(title: Text(person.length.toString()),actions: [
IconButton(onPressed: (){
getPermission();
}, icon: Icon(Icons.contacts))
],),
body: ListView.builder(
itemCount: person.length,
itemBuilder: (c,i){
return ListTile(
leading: Icon(Icons.person),
title: Text(person[i].givenName)
);
}
),
);
}
}
class Modal extends StatelessWidget {
Modal({super.key, this.state, this.changeNumber, this.changeState, this.getPermission});
final state;
final changeNumber;
final getPermission;
var changeState;
var inputData = TextEditingController();
@override
Widget build(BuildContext context) {
return Container(
height: 400,
margin: EdgeInsets.fromLTRB(5, 0, 5, 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.all(5),
child: Text(state, style: TextStyle(fontSize: 40, fontWeight: FontWeight.w900)),
),
Container(
margin: EdgeInsets.all(5),
child: TextField( controller: inputData, style: TextStyle(fontSize: 30),),
),
Container(
margin: EdgeInsets.all(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
margin: EdgeInsets.fromLTRB(5, 0, 5, 0),
child: TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Cencel', style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),)),
),
Container(
margin: EdgeInsets.fromLTRB(5, 0, 5, 0),
child: TextButton(onPressed: () async{
if (inputData.text != ''){
var newPerson = Contact();
newPerson.givenName = inputData.text.toString();
await ContactsService.addContact(newPerson);
await getPermission();
Navigator.pop(context);
}
}, child: Text('OK', style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),)),
),
],
),
)
],
),
);
}
}