웹사이트 검색

Android 런타임 권한 예


Android 런타임 권한 예제에 오신 것을 환영합니다. Android 6.0 Marshmallow가 도입되면서 Google은 앱에서 권한을 처리하는 방식을 변경했습니다. 이 튜토리얼에서는 소개된 새로운 Android 런타임 권한과 이를 처리하는 방법을 살펴보겠습니다. 제대로 처리되지 않으면 응용 프로그램 충돌이 발생할 수 있습니다.

Android 런타임 권한이란 무엇입니까?

Android 6.0(SDK 23)이 도입되면서 사용자는 런타임 시 사용이 필요할 때 특정 권한을 요구하는 메시지를 받게 됩니다. 그래서 가장 먼저 떠오르는 질문은 - 이전 앱이 Android Marshmallow에서 실행될 것인가? targetSdkVersion이 22 이하이면 대답은 예입니다. 따라서 Android 런타임 권한은 이전 버전과의 호환성을 지원합니다. 이제 이것은 sdk 버전을 22로 설정하여 이전 권한 모델로 작업할 수 있다는 의미는 아닙니다. Marshmallow를 사용하는 사용자는 설정->앱에서 위험한 권한(나중에 위험하고 정상적인 권한에 대해 논의할 것임)을 취소할 수 있습니다. -> 권한. 사용자가 아직 부여하지 않은 권한이 필요한 일부 함수를 호출하려는 경우 해당 함수는 갑자기 응용 프로그램 충돌로 이어지는 Exception(java.lang.SecurityException)을 발생시킵니다. 따라서 애플리케이션에서 이 새로운 Android 권한 모델을 구현해야 합니다.

위험하고 정상적인 안드로이드 권한

Android는 일부 권한을 위험하고 일부는 정상으로 정의합니다. 두 형식의 공통점은 매니페스트 파일에서 정의해야 한다는 것입니다. Android 6.0부터는 런타임에 위험한 권한만 확인하고 일반 권한은 확인하지 않습니다. 일반 권한의 예는 android.permission.INTERNET입니다. 위험한 권한은 사용자가 응용 프로그램에서 허용하는 작업을 쉽게 이해할 수 있도록 범주로 그룹화됩니다. 사용자가 그룹/범주에서 하나의 권한을 수락하면 전체 그룹을 수락합니다. 위험한 권한의 예는 android.permission.FINE_LOCATIONandroid.permission.COARSE_LOCATION입니다. 모든 위치 권한을 활성화하면 모두 활성화됩니다.

Android 런타임 권한 요청

메서드 requestPermissions(String[] permission, int requestCode);는 위험한 권한을 요청하는 데 사용되는 공개 메서드입니다. 권한의 문자열 배열을 전달하여 여러 위험한 권한을 요청할 수 있습니다. 참고: 두 개의 서로 다른 그룹에 속하는 Android 권한은 사용자에게 각 그룹에 대한 개별 대화 상자를 표시합니다. 동일한 그룹에 속하는 경우 하나의 대화 프롬프트만 표시됩니다. 요청 결과는 onRequestPermissionResult 메서드로 전달됩니다. 예: 앱에서 카메라와 위치에 액세스하고 싶다고 가정해 보겠습니다. 둘 다 위험한 권한입니다. 애플리케이션이 시작될 때 이러한 권한에 대한 액세스를 요청하는 메시지가 표시됩니다. 권한을 문자열 배열에 추가하고 아래와 같이 requestPermissions를 호출해 보겠습니다.

String[] perms = {"android.permission.FINE_LOCATION", "android.permission.CAMERA"};

int permsRequestCode = 200; 
requestPermissions(perms, permsRequestCode);

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){

    switch(permsRequestCode){

        case 200:

            boolean locationAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
            boolean cameraAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;

            break;

    }

}

이제 우리는 사용자가 이미 수락한 권한을 계속 수락하는 것을 원하지 않습니다. 이전에 권한이 부여된 경우에도 사용자가 나중에 해당 권한을 취소하지 않았는지 다시 확인해야 합니다. 이를 위해 모든 권한에 대해 다음 메서드를 호출해야 합니다.

checkSelfPermission(String perm);

PERMISSION_GRANTED 또는 PERMISSION_DENIED의 정수 값을 반환합니다. 참고: 사용자가 앱에서 중요한 권한을 거부하면 shouldShowRequestPermissionRationale(String permission)이 사용자에게 권한이 필요함을 설명하는 데 사용됩니다. 권한이 이미 존재하는지 확인하는 애플리케이션을 개발해 봅시다. 그렇지 않은 경우 런타임에 요청됩니다.

Android 런타임 권한 프로젝트 구조

Android 런타임 권한 코드

content_main.xml에는 권한을 확인하고 요청하는 두 개의 버튼이 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.journaldev.runtimepermissions.MainActivity"
    tools:showIn="@layout/activity_main">
    <Button
        android:id="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:text="Check Permission"/>
    <Button
        android:id="@+id/request_permission"
        android:layout_below="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Request Permission"/>
</RelativeLayout>

MainActivity.java는 아래와 같이 정의됩니다.

package com.journaldev.runtimepermissions;

import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.view.View;
import android.widget.Button;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.CAMERA;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int PERMISSION_REQUEST_CODE = 200;
    private View view;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Button check_permission = (Button) findViewById(R.id.check_permission);
        Button request_permission = (Button) findViewById(R.id.request_permission);
        check_permission.setOnClickListener(this);
        request_permission.setOnClickListener(this);


    }


    @Override
    public void onClick(View v) {

        view = v;

        int id = v.getId();
        switch (id) {
            case R.id.check_permission:
                if (checkPermission()) {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                } else {

                    Snackbar.make(view, "Please request permission.", Snackbar.LENGTH_LONG).show();
                }
                break;
            case R.id.request_permission:
                if (!checkPermission()) {

                    requestPermission();

                } else {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                }
                break;
        }

    }

    private boolean checkPermission() {
        int result = ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION);
        int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);

        return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
    }

    private void requestPermission() {

        ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0) {

                    boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                    boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;

                    if (locationAccepted && cameraAccepted)
                        Snackbar.make(view, "Permission Granted, Now you can access location data and camera.", Snackbar.LENGTH_LONG).show();
                    else {

                        Snackbar.make(view, "Permission Denied, You cannot access location data and camera.", Snackbar.LENGTH_LONG).show();

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
                                showMessageOKCancel("You need to allow access to both the permissions",
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                    requestPermissions(new String[]{ACCESS_FINE_LOCATION, CAMERA},
                                                            PERMISSION_REQUEST_CODE);
                                                }
                                            }
                                        });
                                return;
                            }
                        }

                    }
                }


                break;
        }
    }


    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(MainActivity.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

}

참고: 응용 프로그램 태그 위의 Manifest 파일에서 런타임 시 확인할 권한을 다음과 같이 추가하십시오.

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

위의 코드에서 확인되고 요청되는 두 가지 권한은 CAMERA와 LOCATION입니다. 정적 권한 전체 클래스 이름을 가져오면 정규화된 경로 대신 PERMISSION 개체만 작성할 수 있습니다. checkPermission()은 각 권한에 대해 checkSelfPermission을 호출합니다. requestPermission()ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);를 호출합니다. onRequestPermissionsResult는 권한이 부여되었는지 여부를 확인합니다. 코드에서 두 권한이 모두 부여되지 않으면 권한을 요청해야 하는 필수 필요성을 보여주는 경고 대화 상자가 나타납니다. 이를 위해 shouldShowRequestPermissionRationale(String permission)가 호출되어 권한의 필요성을 보여주는 경고 대화 상자를 호출합니다. 설정->앱->권한에서 수동으로 권한을 철회할 수 있습니다. 참고: 런타임 권한별 메서드는 API 23 이후에만 사용할 수 있습니다. 따라서 각 메서드에서 다음 조건이 확인됩니다.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)

Android 런타임 권한 예제 프로젝트 다운로드

참조: https://developer.android.com/training/permissions/requesting.html