안드로이드 마쉬멜로우 6.0 권한 허용 팝업 기능 추가하기
https://blog.stylingandroid.com/permissions-part-3/
위 블로그 글을 참고 하였고
프로젝트는 작성자의 깃허브 사이트
https://github.com/StylingAndroid/Permissions/tree/Part3
를 참고 하였다.
프로젝트를 실행하면 이러한 모습이다
코드를 참고하면서 내 프로젝트에 필요한 것만 참고함.
먼저
PermissionsActivity.java 와 PermissionsChecker.java를 프로젝트에 붙여넣기 하였다.
추가 설명은 코드 내 주석을 달아놓았다.
PermissionsActivity.java
37라인
setContentView(R.layout.new_custom_full);
이 부분은 팝업을 표시할 액티비티의 xml 파일명으로 변경해준다.
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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; public class PermissionsActivity extends AppCompatActivity { public static final int PERMISSIONS_GRANTED = 0; public static final int PERMISSIONS_DENIED = 1; private static final int PERMISSION_REQUEST_CODE = 0; private static final String EXTRA_PERMISSIONS = "com.stylingandroid.permissions.EXTRA_PERMISSIONS"; private static final String PACKAGE_URL_SCHEME = "package:"; private PermissionsChecker checker; private boolean requiresCheck; public static void startActivityForResult(Activity activity, int requestCode, String... permissions) { Intent intent = new Intent(activity, PermissionsActivity.class); intent.putExtra(EXTRA_PERMISSIONS, permissions); ActivityCompat.startActivityForResult(activity, intent, requestCode, null); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) { throw new RuntimeException("This Activity needs to be launched using the static startActivityForResult() method."); } setContentView(R.layout.new_custom_full); //xml 파일명 변경 필요 checker = new PermissionsChecker(this); requiresCheck = true; } @Override protected void onResume() { super.onResume(); if (requiresCheck) { String[] permissions = getPermissions(); if (checker.lacksPermissions(permissions)) { requestPermissions(permissions); } else { allPermissionsGranted(); } } else { requiresCheck = true; } } private String[] getPermissions() { return getIntent().getStringArrayExtra(EXTRA_PERMISSIONS); } private void requestPermissions(String... permissions) { ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE); } private void allPermissionsGranted() { setResult(PERMISSIONS_GRANTED); finish(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) { requiresCheck = true; allPermissionsGranted(); } else { requiresCheck = false; showMissingPermissionDialog(); } } private boolean hasAllPermissionsGranted(@NonNull int[] grantResults) { for (int grantResult : grantResults) { if (grantResult == PackageManager.PERMISSION_DENIED) { return false; } } return true; } //모두 거부 하였을 때 나타나는 팝업 창 설정입니다. private void showMissingPermissionDialog() { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(PermissionsActivity.this); dialogBuilder.setTitle(R.string.help); //팝업 창 타이틀 //팝업 안내 메시지 부분으로 string.xml에서 설정한 메시지를 노출합니다. dialogBuilder.setMessage(R.string.string_help_text); //팝업 창 버튼 2개를 노출합니다. //확인버튼을 누르면 앱 종료?인데 저는 팝업 창만 사라졌네요 dialogBuilder.setNegativeButton(R.string.quit, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { setResult(PERMISSIONS_DENIED); finish(); } }); //설정 버튼을 누르면 설정 화면으로 이동합니다. dialogBuilder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startAppSettings(); } }); dialogBuilder.show(); } private void startAppSettings() { Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName())); startActivity(intent); } } | cs |
PermissionsChecker.java
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 | import android.content.Context; import android.content.pm.PackageManager; import android.support.v4.content.ContextCompat; class PermissionsChecker { private final Context context; public PermissionsChecker(Context context) { this.context = context; } public boolean lacksPermissions(String... permissions) { for (String permission : permissions) { if (lacksPermission(permission)) { return true; } } return false; } private boolean lacksPermission(String permission) { return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED; } } | cs |
발생하는 에러는 알맞게 처리한 다음
AndroidMenifest.xml 에 PermissionsActivity를 추가해준다.
1 2 3 4 5 6 7 8 9 10 | <!--PermissionsActivity 를 추가해줍니다.--> <!--팝업 적용을 위해 @style:AppTheme 추가해줍니다--> <activity android:name="com.yonoo.my.PermissionsActivity" android:configChanges="orientation|screenSize|screenLayout|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/AppTheme" android:screenOrientation="nosensor" > </activity> | cs |
권한도 추가
1 2 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> | cs |
앱 테마 적용을 위해 style.xml에 다음을 추가해준다.
(다국어 설정이 되어있다면 국가별 style.xml에도 추가해준다.)
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> </style>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <resources> <!-- Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vXX/styles.xml on newer devices. --> <style name="AppBaseTheme" parent="android:Theme.Light"> <!-- Theme customizations available in newer API levels can go in res/values-vXX/styles.xml, while customizations related to backward-compatibility can go here. --> </style> <!--팝업 호출을 위해 아래 스타일이 필요합니다.--> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> </style> </resources> | cs |
그리고 권한 팝업 노출시 권한 설명을 위한 메시지를 string.xml에 추가하여준다. 마찬가지로 다국어 string에도 추가
이 메시지는 PermissonsActivity의 showMissingPermissionDialog에서 사용된다.
1 2 3 4 5 6 | <!--권한 팝업에서 노출될 메시지를 설정합니다.--> <string name="settings">설정</string> <string name="help">Help</string> <string name="string_help_text"> 저장소와 카메라 권한이 필요합니다. </string> <string name="quit">확인</string> | cs |
그리고 권한 팝업을 띄울 액티비티파일에 다음 코드를 추가해준다.
ex) NewCustomFullActivity 에 권한 팝업을 띄울거라면 변수를 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class NewCustomFullActivity implements OnClickListener{ //권한 체크를 위한 값 선언 private static final int REQUEST_CODE = 0; /*요청받은 권한을 설정합니다. 여기선 저장소와 카메라를 설정 * android.Manifest.permission.WRITE_EXTERNAL_STORAGE * android.Manifest.permission.CAMERA * */ private static final String[] PERMISSIONS = new String[]{ android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA }; //PermissionChecker를 사용하기 위해 선언 private PermissionsChecker checker; | cs |
OnCreate에 다음 코드 추가
1 2 | //Oncreate 에서 Checker를 호출 checker = new PermissionsChecker(this); | cs |
그리고 다음 함수를 추가해준다.
1 2 3 | private void startPermissionsActivity() { PermissionsActivity.startActivityForResult(this, REQUEST_CODE, PERMISSIONS); } | cs |
이제 팝업을 어디서 띄울지 결정해야했는데 카메라를 선택했을 때 띄우기로 결정
그래서 startActivityForResult(intent, PICK_FROM_CAMERA); 이 부분이 호출될 때 팝업이 뜨게 하였다.
권한 때문에 SecurtiyException 이 발생할 때
1 2 3 4 | //권한을 체크 if (checker.lacksPermissions(PERMISSIONS)) { startPermissionsActivity(); } | cs |
이 부분을 추가해주어 권한 허용 유무를 체크하여 미허용상태면 팝업을 띄우도록 startPermissionsActivity() 을 요청한다.
추가된 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //카메라를 호출할 때 권한이 없으면 권한요청팝업이 뜨도록 설정 try{ startActivityForResult(intent, PICK_FROM_CAMERA); }catch (SecurityException e) { //권한을 체크 if (checker.lacksPermissions(PERMISSIONS)) { startPermissionsActivity(); } //토스트로 안내메시지도 같이 호출해보았습니다. e.printStackTrace(); if(language.equals("en") || language.equals("th") || language.equals("vi")) Toast.makeText(getApplicationContext(), "check phone settinig > application manager > app permission Camera approve", Toast.LENGTH_LONG).show(); else Toast.makeText(getApplicationContext(), "설정 > 애플리케이션 관리자 >앱권한에서 카메라 권한을 허용해주세요", Toast.LENGTH_LONG).show(); } | cs |
이렇게 해주면 카메라를 킬 때 허용 팝업이 노출된다.
외국인 블로거가 짜놓은 코드를 사용하였기 때문에 자세한 설명보다는 크게 크게 이해해보려고 하였다.
나중을 위해서 적어 놓은건데 빼 먹은 건 없나 모르겠다.
원래는 앱 시작하자마자 팝업 띄우려고 헀는데 뭔가 계속 안된다..
그래서 그냥 해당기능 켤 때 띄우는 걸로..
이런 걸 취미로 포스팅 하는 개발자들은 참 대단하다.
난 아무리 봐도 이해가 안가는데..