SMS receving이 안되어 원인을 찾다보니
아래 내용을 깜박 잊고 있었음.. ㅎㅎ
하긴 2015년 7월에 들은 내용이니....
개인 앱 개발이라 뭐.. 게을러도 너무 게으르다는 생각을 ㅎㅎ
http://charlie0301.blogspot.kr/2015/07/google-io-extended-2015-android-track.html
[런타임 앱 권한]
- 기존에 설치 시 권한을 요청하고 일괄 승인 했던 것을
M target app에서는 이전처럼 manifest에 권한을 명시하더라도
권한을 사용할 때 사용자에게 다시 물어보도록 함.
또한 환경설정에서 앱별 권한을 설정할 수 도 있음.
- Runtime 시 개별적으로 권한을 요청 할 때 시스템 프로세스 상에서 권한 요청이 실행 됨.
- 액티비티 뿐만 아니라 서비스에서 Runtime시 permission 요청을 해야 할 수 있음.
- 콜백으로 사용자 응답 받게 되므로 기존 권한을 사용하던 부분을 callback trigger를 전후로 나눠 처리 해야 함.
- M 이전 Android 버전들 타겟 앱은 이전 방식 처럼 권한을 수락하게 됨.
- M 버전 기반 앱의 권한이 거부되면 안드로이드에서는 가짜 데이터를 제공할 예정이고 앱의 동작은 가늠할 수 없으므로 앱이 권한 거부 상황을 잘 처리하도록 만들어야 함.
- 권한이 변경되더라도 자동으로 업데이트 가능함. (설치 시 권한 수락이 필요 없으니)
Android 6.0 버전 이상을 대상으로 하는 App의 Manifest에 명시된 앱 권한이 사용자로 부터 허락되지 않을 경우 아래와 같은 에러 메세지가 log로 표시된다.
Permission Denial: receiving Intent { act=android.provider.Telephony.SMS_RECEIVED flg=0x18000010 (has extras) } to com.blogspot.charlie0301/kr.blogspot.charlie0301.wimple.SMSReceiver requires android.permission.RECEIVE_SMS due to sender com.android.phone (uid 1001)
동일 case : http://stackoverflow.com/questions/32537156/basic-error-in-androidmanifest-xml-for-sms-receiving-permission
그래서 App에서 해당 권한이 필요한 기능을 사용할 때 사용자에게 팝업을 띄워 권한을 요청해야 한다. 자세한 설명은 아래에 잘 번역 되어 있음.
: https://developer.android.com/training/permissions/declaring.html
그래서 대충 copy & paste로 다음과 같이 붙임.
권한 요청 시점
: 설정에서 SMS read 하는 기능을 on/off 하는 부분이 있어 on 될 때 권한을 요청하도록 함.
: https://github.com/hallower/wimple/blob/master/app/src/main/java/kr/blogspot/charlie0301/wimple/SettingsFragment.java#L121
권한 요청 팝업 표시
: ContextCompat.checkSelfPermission()로 권한이 수락되지 않았는지 확인하여 ActivityCompat.shouldShowRequestPermissionRationale()로 권한 수락에 대한 설명이 필요한 지 확인함.
[구글 가이드내 코드]
// 권한이 필요한 시점에 if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { // 사용자가 이미 Deny를 했는지 확인하는 절차 if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) { // Deny를 했다면 적절한 설명을 보여주고 사용자의 반응에 따라 다시 요청 해야 함. } else { // 권한 요청을 하지 않았었으면 권한을 요청함. ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS); // MY_PERMISSIONS_REQUEST_READ_CONTACTS 은 // callback에서 권한 처리 결과를 받기 위한 상수값 } }
실제 구현은 귀찮아서 그냥 deny하면 설명만 보여주게 하였음.
: https://github.com/hallower/wimple/blob/master/app/src/main/java/kr/blogspot/charlie0301/wimple/WimpleActivity.java#L168
사용자의 권한 수락/거절 이후 처리
: 이후 사용자의 수락/거절에 따라 callback method가 호출되어 결과를 알 수 있음.
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // 요청이 취소되었을 경우 result가 null일 수 있어 에러 처리 필요 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 권한이 수락되었음 } else { // 권한이 거절됨... } return; } // 다른 권한에 대해서 case 추가 처리 하면 됨. } }
일단 구현에서는 그냥 메세지만 보여주는 것으로 간단하게 대충 구현함.
: https://github.com/hallower/wimple/blob/master/app/src/main/java/kr/blogspot/charlie0301/wimple/WimpleActivity.java#L181
안드로이드 사이트에서 설명하고 있지만 특히나 고려해야할 사항이
- 권한 요청 시점을 필요한 시점으로 선택해야 한다.
: 일부 앱에서는 시작 시 무조건 권한을 확인하게 하던데 별로 좋지 않은 방법인 듯 하다.
: 특히나 위 예제를 시작 시점에 붙여 넣게 되면 Deny 되었을 경우 앱 실행 시 마다 권한 설명을 표시 되거나 권한을 재요청을 하게 하는 loop이 생길 수 있음.
: 권한을 사용하는 시점에 요청 하는 것이 가장 바람직한 듯 함.
- 사용자가 거절 했을 경우 이후 처리를 잘해야 겠음.
: 제한된 메세지 내용을 통해 안드로이드 설정의 앱 목록에서 선택하여 권한을 설정하라는 가이드하는 것은 어려울 것 같음.
: 그래서 간단한 권한 설명과 사용자가 메세지를 읽고 적절한 시점에 권한을 요청해야 할 것 같음.
: 그냥 무조건 선택하라는 안내는 더 도움이 안될 것 같고
댓글 없음:
댓글 쓰기