본문 바로가기
[ Developer ]/Android

[Android] 안드로이드 마쉬멜로우 권한 얻기

by 김현섭. 2016. 7. 16.
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
Android 권한 얻기
마시멜로에서 ACTION_CALL을 하려면 권한이 필요하다면서 에러가 발생하는데 
CALL을 시키기 위한 권한을 얻어보는 방식을 알아본다

Android의 권한 획득 방식
  1. Android OS 마쉬멜로 이전 버전 방식
    • Android Menifest.xml에서 <user-permission />을 사용해서 권한을 획득
    • ex)
  2. 마쉬멜로 이후 버전일 때
    • 마쉬멜로 이후의 버전에도 1번의 방식을 포함한다
    • 실시간 권한 허가 작업이 필요하다
    • ex)
    • 위처럼 권한에 대해 사용자에게 문의하고 권한을 얻어오는 작업이 필요하다
    • 허용시에만 사용이 가능하다
    • 작업 순서
      1. OS Check
        • OS가 마시멜로인지
        • 마쉬멜로라면 다음 단계로 넘어간다
      2. 마쉬멜로 라면 권한 허가 여부 묻는다
        • 이전에 앱에서 허가를 했나
        • 권한이 있다면 작업 수행 
        • 아니라면 다음 단계
      3. 거부 이력 여부 존재 하는지 확인
        • 사용자가 이전에 거부한 이력이 있는지
        • 있다면 허용을 할 것인지에 대해 문의
          • 이전에 거절을 했기 때문에 면밀히 물어보는 과정
        • 없다면 권한 요청
      4. 사용할 것인지에 대해 물어봄

@ 권한 획득 실습
우선 Android Studio에서 새로운 프로젝트를 생성한다
Call App 

그런 후 간단하게 버튼을 하나 생성 한다


그리고 나서 MainActivity에서 버튼과 버튼에 인텐트를 통해서 ACTION_CALL을 수행하는 과정을 정의한다


startActivity가 권한을 가져오는 로직이 없어서 빨간줄이 뜨는 것을 볼 수 있다
우선은 manifests에서 uses-permission을 추가해준다


위의 권한을 허가하는 구문이 있다면 사용이 된다
그러나 마쉬멜로에서는 구문만으로는 해결을 할 수 없다

권한을 획득하는 작업 순서에 따라서 로직을 작성한다


우선 마시멜로 버전인 것을 먼저 걸러주기 위해서 Build.VERSION_CODES를 보면 버전들이 나오는데 M이 마쉬멜로이다
위와 같은 방식으로 마쉬멜로보다 큰 버전인 지를 걸러낸다


권한을 우선 가져오는데 Manifest는 android를 import 시켜 가져오고 int값으로 가져오면 된다


안드로이드에서는 boolean대신 int와 상수를 비교한다 
why? 논리값은 결과값을 다양하게 가져오기 못하고 안드로이드가 C 기반이기 때문이다

위와 같이 권한을 가져온 후 상수와 비교를 해주면 된다


그리고 큰 틀에서 마쉬멜로 이전 버전일 때 기존 로직을 실행하게 하면 에러가 발생하지 않는다


그런 후 권한이 존재할 때도 인텐트를 실행하도록 만들면 된다


이제는 권한이 없을 때의 로직을 작성해준다


우선 권한을 거부한 이력이 있는지에 대해 검사를 해준다
이력이 있다면 true를 리턴하고 없다면 false를 리턴할 것이다


권한을 거부한 적 없을 때 즉 최초로 권한을 요청할 때 requestPermissions를 이용하면 된다
2개의 파라미터가 들어가는데 권한이 배열인 이유는 여러가지 권한을 요청할 수 있기 때문이다
또한 요청 코드를 보낼 수 있다



위와 같이 적어주면 String 배열에 CALL_PHONE 권한을 requestCode = 1000으로 요청하는 것이다


AlertDialog를 이용해서 사용자에게 보여준다
그런 후 네와 아니요 각각의 버튼에 필요한 로직을 작성해준다


그러나 PositiveButton일 때 requestPermissions가 에러가 발생하는 것을 볼 수 있다


에러의 내용은 이 문구는 마쉬멜로우에서 생긴 키워드이기 때문에 버전 체크를 통해서 마쉬멜로우인지를 체크해줘야한다
그러나 위에서 마쉬멜로인지를 체크해줬는데도 에러가 발생하는 이유는 onClick내에서는 new DialogInterface로 이전의 상황을 모르기 때문에 버전을 체크해줘야 한다


RequestCode를 보냈다는 건 즉 응답을 받는다는 얘기기 때문에 응답을 받아주는 과정이 필요하다
onRequestPermissionsResult를 통해서 응답을 받는 처리를 해준다


startActivity에서 다시 한번 권한 체크를 해야 하는데 Alt + Enter를 통해서 Permission Check를 해주면 된다



자동완성을 해주면 된다
이제 결과를 통해서 확인해본다


위와 같이 허용을 할 것 인지에 대해 뜨는 것이 나왔다
우선 거부를 해본다

거부 이력이 있기 때문에 다시 한번 버튼을 누른다면 권한이 필요하다는 로그가 뜬다


다시 한번 요청을 승락하고 누르면 전화가 걸리는 것을 볼 수 있다


*Source - Android 권한 요청
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public class MainActivity extends AppCompatActivity {
 
    private Button button;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        button = (Button) findViewById(R.id.btnCall);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
 
                /**
                 * 사용자의 OS Version이 마쉬멜로우 이상인지
                 */
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    // 사용자 단말기의 권한 중 "전화걸기" 권한이 허용 되어 있는지 체크
                    int permissionResult = checkSelfPermission(Manifest.permission.CALL_PHONE);
 
                    if (permissionResult == PackageManager.PERMISSION_DENIED) {
                        // 권한 없음
                        if (shouldShowRequestPermissionRationale(Manifest.permission.CALL_PHONE)) {
                            // 권한을 한번이라도 거부한 적 있는지 검사
                            // 있다면 true 리턴 || 없다면 false 리턴
                            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
                            dialog.setTitle("권한 필요")
                                    .setMessage("기능을 사용하기 위해 단말기의 '전화걸기' 권한이 필요합니다")
                                    .setPositiveButton("네"new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                requestPermissions(new String[]{Manifest.permission.CALL_PHONE}, 1000);
                                            }
                                        }
                                    })
                                    .setNegativeButton("아니요"new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Toast.makeText(MainActivity.this"기능 취소", Toast.LENGTH_SHORT).show();
                                        }
                                    }).create().show();
                        } else {
                            // 권한 거부한 적 없음 CALL_PHONE 권한을 요청
                            requestPermissions(new String[]{Manifest.permission.CALL_PHONE}, 1000);
                        }
                    } else {
                        // 권한 존재
                        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-222"));
                        startActivity(intent);
                    }
                } else {
                    // 마쉬멜로 이전 버전이라면
                    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-222"));
                    startActivity(intent);
                }
            }
        });
    }
 
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 1000) {
            if (grantResults.length > 0 && grantResults[0== PackageManager.PERMISSION_GRANTED) {
                // 요청한 권한 허용 시
                Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-222"));
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    // TODO: Consider calling
                    //    ActivityCompat#requestPermissions
                    // here to request the missing permissions, and then overriding
                    //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                    //                                          int[] grantResults)
                    // to handle the case where the user grants the permission. See the documentation
                    // for ActivityCompat#requestPermissions for more details.
                    return;
                }
                startActivity(intent);
            }
            else {
                Toast.makeText(MainActivity.this"권한 요청 거부", Toast.LENGTH_SHORT).show();
            }
        }
    }
}
cs

권한 요청을 하기 위해서 로직이 복잡하다
그런한 것을 간단하게 해주기 위해서 다음의 블로그를 참조해서 간단하게 사용하기를 권장한다


위의 방식을 이용하기 위해서는 MainActivity의 패키지 내에 클래스를 생성해서 첫 번째 내용을 붙여넣는다


그러고 난 후 Main에서 위의 방식 코드를 임시로 주석 처리 한 후 블로그에 있는 사용 방법 내용으로 대체를 해본다


그리고 나서 응답을 처리하는 메소드도 가져다가 쓰면 된다


그러면 조금 더 간단하게 사용을 할 수 있게 된다

실행을 시켜보면 이미 권한이 요청되었기 때문에 콘솔창에 권한이 존재 한다는 내용이 뜨게된다