Skip to content
coooldoggy.dev

Android PermissionUtil

Android1 min read

어플리케이션을 만들때마다 권한에 대한 부분은 항상 헷갈린다

Ted Permssion 이라는 좋은 라이브러리를 사용하면 간단히 해결할 수도 있지만 고전적인 방법으로 권한을 체크하는 법에 대해 정리해보고자 한다.

안드로이드에서 권한을 받는 순서는 대부분 아래와 같이 흘러간다.

  1. 권한이 필요한 행동을 한다
  2. 권한이 있는지 없는지 체크한다

2-1. 권한이 있으면 바로 동작 실행

2-2. 권한이 없다면 runtime 권한 팝업창 호출

*허용시: 동작 실행

*거부시: 설정 으로 보내거나 앱 종료

권한이 있는지 없는지 체크하는 것은 OS버전을 체크하여 진행해야하는데 이는 OS버전마다 디바이스 접근 권한이 강화되기 때문이다.

1public class PermissionUtils {
2 private static String TAG = PermissionUtils.class.getSimpleName();
3
4 public static boolean permissionCheck(Context context, int permission) {
5 boolean result = true;
6
7 try {
8 switch (permission) {
9 case Define.CHECK_ACCESS_FINE_LOCATION:
10 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
11 int nAccessFinePermission = context.getApplicationContext().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
12 if (nAccessFinePermission == PackageManager.PERMISSION_GRANTED) {
13 result = true;
14 } else {
15 result = false;
16 }
17 } else {
18 LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
19 if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
20 result = false;
21 }
22 result = true;
23 }
24 break;
25 case Define.CHECK_ACCESS_COARSE_LOCATION:
26 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
27 int nAccessFinePermission = context.getApplicationContext().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);
28 if (nAccessFinePermission == PackageManager.PERMISSION_GRANTED) {
29 result = true;
30 } else {
31 result = false;
32 }
33 } else {
34 LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
35 if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
36 result = false;
37 }
38 result = true;
39 }
40 break;
41 case Define.CHECK_ACCESS_CAMERA:
42 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
43 int nAccessFinePermission = context.getApplicationContext().checkSelfPermission(Manifest.permission.CAMERA);
44 if (nAccessFinePermission == PackageManager.PERMISSION_GRANTED) {
45 result = true;
46 } else {
47 result = false;
48 }
49 }
50 break;
51 case Define.CHECK_ACCESS_STORAGE:
52 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
53 int nAccessFinePermission1 = context.getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
54 int nAccessFinePermission2 = context.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
55 if (nAccessFinePermission1 == PackageManager.PERMISSION_GRANTED && nAccessFinePermission2 == PackageManager.PERMISSION_GRANTED) {
56 result = true;
57 } else {
58 result = false;
59 }
60 }
61 break;
62 }//end switch
63
64 } catch (Exception e) {
65 e.printStackTrace();
66 }
67 return result;
68 }
69
70}

우선 PermissionUtil.class를 만든다. 이 class는 사용자가 이 앱에 대한 권한을 허용했는지 거부했는지에 대해 체크한다. 그리고 권한을 요청할 액티비티 내에서 권한이 허용여부를 묻는 메소드를 만든다.

1private void checkPermission(int requesttype) {
2 switch (requesttype) {
3 case Define.CHECK_ACCESS_FINE_LOCATION:
4 if (PermissionUtils.permissionCheck(this.getApplicationContext(), Define.CHECK_ACCESS_FINE_LOCATION) == false) {
5 requestPermission(Define.REQUEST_ACCESS_FINE_LOCATION);
6 } else {
7 }
8 break;
9 case Define.CHECK_ACCESS_CAMERA:
10 break;
11 }
12 }

여기서 else 구문이 이미 권한이 존재하는 것이므로 if구문에 런타임권한을 요청하는 함수를 호출한다. 런타임 권한을 호출하는 함수는 다음과 같다.

1private void requestPermission(int requesttype) {
2 switch (requesttype) {
3 case Define.REQUEST_ACCESS_FINE_LOCATION:
4 ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, requesttype);
5 break;
6 case Define.REQUEST_ACCESS_CAMERA:
7 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, requesttype);
8 break;
9 }
10 }

이때 android.Manifest.permission. 다음의 스트링이 권한을 의미하는 것이므로 각각의 권한에 맞게 변경하면 된다.

마지막으로 권한이 승인되거나 거부되었을때 OS에서 resultCode와 결과값을 반환해주는데 이 값을 받기 위해서 method를 Override 해준다.

1@Override
2 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
3 switch (requestCode) {
4 case Define.REQUEST_ACCESS_FINE_LOCATION:
5 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
6 } else {
7 requestLocationAgain();
8 }
9 return;
10 case Define.CHECK_ACCESS_CAMERA:
11 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
12 // 권한 허가
13 } else {
14 // 권한 거부
15 }
16 break;
17 }
18 }
19
20 private void requestLocationAgain(){
21 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
22 intent.addCategory(Intent.CATEGORY_DEFAULT);
23 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
24 startActivity(intent);
25 }

여기서 만약 거부당했을때 설정화면으로 이동하게 하고 싶다면 requestLocationAgain() 함수 안의 intent를 실행해주면 된다.

Define. 어쩌구라고 자꾸나오는데 주로 Define에 constant들을 몰아넣고 공통으로 사용하고 있다. 여기서 쓰였던 것들은

1public static final int CHECK_ACCESS_FINE_LOCATION = 0;
2 public static final int CHECK_ACCESS_COARSE_LOCATION = 1;
3 public static final int CHECK_ACCESS_CAMERA = 2;
4 public static final int CHECK_ACCESS_STORAGE = 3;

이렇게 그냥 int 값을 준것이기 때문에 클래스의 멤버로 선언해도 상관없다.