티스토리 뷰

안드로이드에서 지정한 위험 권한은 사용자로 부터 직접 승인받아야만 사용할 수 있습니다.

이 포스트에서는 Flutter에서 permission_handler라는 패키지를 사용하여 사용자에게 권한을 요청받는 방법에 대해 다룹니다.

 

[1] pubspec.yaml 에 패키지 추가하기

먼저 permission_handler에 새로운 패키지를 추가하기 위해 pubspec에 다음과 같이 입력합니다.

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  
  # Permission checking
  permission_handler: ^3.1.0

 

그리고 레이아웃은 아래 사진과 같이 간단하게 Text를 놓고, 누르면 권한 요청을 하도록 하겠습니다.

,

[2-1] AndroidManifest에 권한 등록하기

안드로이드 매니패스트 파일에 아래와 같이 사용할 권한을 등록합니다.

android/app/src/main/AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

[2-2] iOS info.plist에 권한 등록하기

iOS개발을 안해봐서 모르지만 아래와 같이 추가합니다.

ios/Runner/Info.plist

<key>NSContactsUsageDescription</key>
<string>This app requires contacts access to function.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app requires access to your location when in use to show relevan information.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app requires always on access to to your location to notifiy you when are near a store.</string>

 

[3] 간단한 예제 만들어보기

아래와 같이 PermissionService 클래스를 만듭니다. 이때, 코드의 정리를 위해

새롭게 permissions_service.dart 파일을 만들고 그 안에 작성하였습니다.

 

이 클래스 안에는 각종 권한 요청 코드가 들어갑니다.

import 'package:permission_handler/permission_handler.dart';

class PermissionsService {
  final PermissionHandler _permissionHandler = PermissionHandler();
}

 

아래 코드는 연락처 읽기 권한 요청을 합니다.

/// Requests the users permission to read their contacts.
  Future<bool> requestContactsPermission() async {
    return _requestPermission(PermissionGroup.contacts);
  }

아래 사진에 보이는 것과 같이 다양한 권한 요청이 가능합니다.

 

좀더 응용하여 아래 코드같이 매개변수에 직접 권한을 넣어서 요청할 수도 있습니다.

  Future<bool> _requestPermission(PermissionGroup permission) async {
    var result = await _permissionHandler.requestPermissions([permission]);
    if (result[permission] == PermissionStatus.granted) {
      return true;
    }

    return false;
  }

 

 

그리고 아래 코드에서 권한을 요청합니다.

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: InkWell(
          child: Text("권한 요청하기"),
          onTap: () {
            PermissionsService().requestLocationPermission();
          },
        ),
      ),
    );
  }
}

 

 

정상적으로 권한요청이 되는 것을 확인할 수 있습니다.

 

[4] 더 나아가기

 

좀더 응용하여 아래 코드같이 매개변수에 직접 권한을 넣어서 요청할 수도 있습니다.

  Future<bool> _requestPermission(PermissionGroup permission) async {
    var result = await _permissionHandler.requestPermissions([permission]);
    if (result[permission] == PermissionStatus.granted) {
      return true;
    }

    return false;
  }

 

 

이번에는 권한을 요청하고 사용자가 거부했을 때 Dialog를 띄워보도록 하겠습니다. 

 

먼저 아래 코드와 같이 거부했을 때 Dialog를 띄워줄 함수를 선언합니다.

void _showDialog(BuildContext context) {
  showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: new Text("권한필요"),
          content: new Text("이 앱을 정상적으로 실행하기 위해 권한이 필요합니다."),
          actions: <Widget>[
            // usually buttons at the bottom of the dialog
            new FlatButton(
              child: new Text("닫기"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      });
}

 

그리고 PermissionService 클래스 안에 아래 코드를 작성합니다.

이 Future는 요청할 권한과 사용자가 거절했을 때 실행할 메소드를 파라메터로 받습니다.

Future<bool> requestPermission({PermissionGroup permission,Function onPermissionDenied}) async {
    var granted = await _requestPermission(permission);
    if (!granted) {
      onPermissionDenied();
    }
    return granted;
  }

 

그리고 호출은 아래와 같이 합니다.

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: InkWell(
          child: Text("권한 요청하기"),
          onTap: () {
            PermissionsService().requestPermission(
                permission: PermissionGroup.contacts,
                onPermissionDenied: () {
                  _showDialog(context);
                });
          },
        ),
      ),
    );
  }
}

 

전체 코드

permission_service.dart

import 'package:permission_handler/permission_handler.dart';

class PermissionsService {
  final PermissionHandler _permissionHandler = PermissionHandler();

  Future<bool> _requestPermission(PermissionGroup permission) async {
    var result = await _permissionHandler.requestPermissions([permission]);
    if (result[permission] == PermissionStatus.granted) {
      return true;
    }

    return false;
  }

  /// 연락처 권한 요청
  Future<bool> requestContactsPermission() async {
    return _requestPermission(PermissionGroup.contacts);
  }

  /// 위치 권한 사용 요청
  Future<bool> requestLocationPermission() async {
    return _requestPermission(PermissionGroup.locationAlways);
  }

  /// (권한, 거절시 실행할 메소드)
  Future<bool> requestPermission({PermissionGroup permission,Function onPermissionDenied}) async {
    var granted = await _requestPermission(permission);
    if (!granted) {
      onPermissionDenied();
    }
    return granted;
  }
}

main.dart

import 'package:flutter/material.dart';
import 'permission_service.dart';
import 'package:permission_handler/permission_handler.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: InkWell(
          child: Text("연락처 권한 요청하기"),
          onTap: () {
            PermissionsService().requestPermission(
                permission: PermissionGroup.contacts,
                onPermissionDenied: () {
                  _showDialog(context);
                });
          },
        ),
      ),
    );
  }
}

void _showDialog(BuildContext context) {
  showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: new Text("권한필요"),
          content: new Text("이 앱을 정상적으로 실행하기 위해 권한이 필요합니다."),
          actions: <Widget>[
            // usually buttons at the bottom of the dialog
            new FlatButton(
              child: new Text("닫기"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      });
}
댓글
댓글쓰기 폼