ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 안드로이드 마시멜로우(Android 6.0) 권한요청 - Custom Dialog( 2/2 )
    Android 2019. 4. 11. 15:16

    이번 글에서는 System Dialog에서 거부를 한 이후에 다시한번 사용자에게 권한허용을 요청하는 Custum Dialog를 생성을 해보겠다.

    목표는 아래와 같은 다이얼로그를 만드는것이다. 이전글에서 만든 java파일에 몇몇 메소드를 추가하고 Dialog를 커스텀할 파일들을 몇개 만들것이다.

     

     

     

     

     

    1. PermissionUtil.java

     

    - checkPermissions_list()

     

    Custum Dialog를 보면 리스트뷰 형식으로 허용이 필요한 권한들이 나열되어있다. 요청한 권한들중에 계속해서 거부된 권한들을 리스트로 리턴한다. Custom Dialog를 생성할때 사용된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    //배열로 들어온 권한중에 계속 거부상태인 권한들을 리스트로 리턴

    public static List<String> checkPermissions_list(Activity activity, String[] array_permission) {
     
         List<String> list_permission = new ArrayList<String>();
         try{
              for (String permission : array_permission) {
                  if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                    list_permission.add(permission);
                  }
              }
         }catch(Exception e){
         }
         
         return list_permission;
    }
     
    Colored by Color Scripter

     

     

     

    - showRequestAgainDialog()

     

    System Dialog를 생성하는 메소드. 문장만 쓰려면 따로 리스트뷰를 추가할 필요는 없다. 해당 권한에 대한 이름과 이미지를 추가하기 위해서 좀더 내용을 추가하였다.

     

    그리고 저장공간에 대한 Read,Write하는 권한을 허용하는 테스트를 하다보니 버그같은 내용이 보였다.

    읽고,쓰기 권한 2개를 요청하면 System Dialog에는 저장공간이라는 타이틀로 한개의 권한 허용을 물어본다. 하지만 Custom Dialog에는 권한 허용 리스트를 모두 보여주기때문에 WRITE_EXTERNAL_STORAGE ,  READ_EXTERNAL_STORAGE  두줄로 보이게 되기 때문에  WRITE_EXTERNAL_STORAGE가 있을때는 리스트뷰에 추가할때 add하지 않게끔해서 구현을 하였다. Write, Read 구분해서 보여주고싶다면 조건문을 제거하고 사용하면된다.

    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
     
    /**
     * 권한 받는 팝업 이후 다시한번 권유하는 Custom Dialog
     * 설정시 setting 권한 on/off 하도록
     * 취소시 팝업창만 Dismiss하거나 앱을 종료하거나 기획대로 수정
     */
     public void showRequestAgainDialog(String[] array_permission) {
     
          AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
          LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          View convertView = (View) inflater.inflate(R.layout.permission_listview, null);
          ListView lv = (ListView) convertView.findViewById(R.id.listview);
     
          try {
                //true일경우 모든 권한 수락 받음
                //false일 경우 거부된 권한이 있음
                if (checkPermissions((MainActivity)mContext, array_permission)) {
     
                    //모든권한 허용받음
                    //원하는 기능 구현
                } else {
     
                    //거부된 권한이 있음
                    //해당 권한 허용 요청을 위한 Custum Dialog생성
     
                    Permission permission;
                    List<Permission> mList = new ArrayList<Permission>();
                    List<String> list = new ArrayList<>();
                    list = checkPermissions_list((MainActivity)mContext, array_permission);
     
                    if (list.size() > 0) {
     
                        for (String stPermission : list) {
                            permission = new Permission();
                            permission.setPermission(stPermission);
     
                            //write,read 권한 모두 스토리지 권한이 필요한데.
                            //필요권한 재요청 Custum Dialog에서 같은 스토리지 권한요청이 2줄 나오는거 방지.
                            if!("WRITE_EXTERNAL_STORAGE".equals(stPermission.replace("android.permission.",""))) ) {
                                mList.add(permission);
                            }
                        }
                    }
     
                    PermissionAdapter permissionAdapter = new PermissionAdapter(mContext, R.layout.permission_list_item, mList);
                    lv.setAdapter(permissionAdapter);
     
                    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                    convertView.setLayoutParams(params);
     
                    builder.setCancelable(false);
                    builder.setView(convertView);
                    builder.setMessage("해당 기능 사용을 위해 다음 권한 허용이 필요합니다.");
     
                    builder.setPositiveButton("설정"new DialogInterface.OnClickListener() {
     
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
     
                            try {
                                ((MainActivity) mContext).isReturnedFromSettings = true;
     
                                // TODO Auto-generated method stub
                                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                                        .setData(Uri.parse("package:" + mContext.getPackageName()));
                                mContext.startActivity(intent);
     
                            } catch (ActivityNotFoundException e) {
                                ((MainActivity) mContext).isReturnedFromSettings = true;
     
                                Intent intent = new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
                                mContext.startActivity(intent);
                            }
                        }
                    });
     
                    builder.setNegativeButton("취소"new DialogInterface.OnClickListener() {
     
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // TODO Auto-generated method stub
                        }
                    });
                    builder.create();
                    builder.show();
                }
     
          }catch (Exception e){
          }
     
    }
     
    Colored by Color Scripter

     

     

     

     

     

    2. permission_listview.xml

    - Custom Dialog의 텍스트 아래에 권한 리스트들이 나올수 있도록 listview를 추가해준다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
     
        <ListView
            android:id="@+id/listview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_marginLeft="25dp"
            android:layout_marginRight="25dp"
            android:layout_marginTop="10dp"
            android:dividerHeight="3dp">
        </ListView>
     
    </LinearLayout>
     
    Colored by Color Scripter

     

     

     

     

    3. permission_list_item.xml

    Custom Dialog에 추가한 리스트뷰 내부 각각의 리스트의 UI를 잡아준다. 권한 이미지와 권한이름을 넣어줄 UI를 만든다.

    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
     
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
     
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="5dp">
     
                <ImageView
                    android:id="@+id/iv_permission"
                    android:layout_width="25dp"
                    android:layout_height="25dp"
                    android:layout_centerInParent="true"/>
     
                <TextView
                    android:id="@+id/tv_permission"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:text=""
                    android:layout_marginLeft="10dp"
                    android:gravity="left|center"/>
     
        </LinearLayout>
    </LinearLayout>
     
    Colored by Color Scripter

     

     

     

     

    4. Permission.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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    public class Permission implements Parcelable{
     
        private String permission;
     
        public Permission(){
        }
     
        public Permission(String permission){
            this.permission = permission;
        }
     
        public String getPermission() {
            return permission;
        }
     
        public void setPermission(String permission) {
            this.permission = permission;
        }
        
        @Override
        public int describeContents() {
            return 0;
        }
        
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(this.permission);
        }
     
        public Permission(Parcel in) {
            this.permission=in.readString();
        }
     
        public static final Creator<Permission> CREATOR = new Creator<Permission>() {
     
            public Permission createFromParcel(Parcel in) {
                return new Permission(in);
            }
     
            public Permission[] newArray(int size) {
                return new Permission[size];
            }
        };
     
    }
     
    Colored by Color Scripter

     

     

     

     

    5. PermissionAdapter.java

    리스트뷰 UI을 세팅해주게된다. 필요한 권한을 리스트로 받아서 파싱해서 텍스트로 세팅하고

    해당 권한 이미지를 PackageManager.getResourcesForApplication("android").getDrawable(groupInfo.icon)를 통해  Drawable로 리턴받아 설정해준다.

     

    케이스 별로 작성하기 위해서 WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE 모두 케이스 문에 넣어줬지만 실제로는 WRITE의 경우에는 list에 add하지 않기 때문에 READ인 경우는 안생길것이다.

    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
     
    public class PermissionAdapter extends ArrayAdapter<Permission> {
     
        private Context context;
        private List<Permission> items;
        private LayoutInflater inflater;
        ViewHolderPermission holder;
        private PackageManager mPackageManager;
     
        public PermissionAdapter(Context context, int textViewResourceId, List<Permission> items) {
     
            super(context, textViewResourceId, items);
            this.context = context;
            this.items = items;
            this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     
        }
     
        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {
     
            try {
     
                if (view == null) {
                    LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    view = vi.inflate(R.layout.permission_list_item, null);
                    holder = new ViewHolderPermission();
                    holder.img_Permission = (ImageView)view.findViewById(R.id.iv_permission);
                    holder.tv_Permission = (TextView)view.findViewById(R.id.tv_permission);
                    view.setTag(holder);
                }
     
                //현재 position 의 내용을 View 로 작성하여 리턴
                Permission item = (Permission)items.get(position);
     
                if (item != null) {
     
                    String permission_name = "";
                    ViewHolderPermission holder = (ViewHolderPermission) view.getTag();
     
                    //권한에 맞춰 설정에 있는 언어로 변환후 Set
                    switch(item.getPermission().replace("android.permission.","")){
     
                         case "READ_PHONE_STATE":
     
                            permission_name = "Phone";
                            break;
     
                         case "WRITE_EXTERNAL_STORAGE":
     
                            permission_name = "Storage"
                            break;
     
                         case "READ_EXTERNAL_STORAGE":
                            
                            permission_name = "Storage"
                            break;
                    }
     
                    holder.tv_Permission.setText(permission_name);
                    holder.img_Permission.setImageDrawable(getPermissionDrawable(item.getPermission()));
     
                }
     
            }catch(Exception e){
                LogUtil.LogString("PermissionAdapter Exception");
     
                }
     
            return view;
     
        }
     
        private Drawable getPermissionDrawable(String permission) {
            Drawable drawable = null;
            try {
                mPackageManager = this.context.getPackageManager();
                PermissionInfo permissionInfo = mPackageManager.getPermissionInfo(permission, 0);
                PermissionGroupInfo groupInfo = mPackageManager.getPermissionGroupInfo(permissionInfo.group, 0);
                drawable = mPackageManager.getResourcesForApplication("android").getDrawable(groupInfo.icon);
                drawable.setColorFilter(context.getResources().getColor(R.color.accent_material_light), PorterDuff.Mode.SRC_ATOP);
            } catch (PackageManager.NameNotFoundException|Resources.NotFoundException e) {
            }
            return drawable;
        }
     
        static class ViewHolderPermission {
            ImageView img_Permission;
            TextView tv_Permission;
        }
    }
     
    Colored by Color Scripter

     

     

     

     

    5. MainActivity.java

     

    Custom Dialog를 호출할때 사용하면된다.

    이전글에서 onRequestPermissionsResult() 메소드 안에 권한이 없을때 Custom Dialog를 호출하게끔 적어둔 라인이다.

    1
    2
     
    PermissionUtil permissionUtil = new PermissionUtil(MainActivity.this);
    permissionUtil.showRequestAgainDialog(array_permissions);
     

     

     

     

     

     

    안드로이드 마시멜로우(Android 6.0) 권한요청 - System Dialog( 1/2 )

    https://justbobby.tistory.com/16

     

    안드로이드 마시멜로우(Android 6.0) 권한요청 - System Dialog( 1/2 )

    이전에는 앱설치 할때AndroidManifest.xml에 등록해둔 필요권한을 보여주고 설치와 동시에 권한을 얻었지만 안드로이드 targetSDK23이상을 빌드하게되면서 앱에서 해당 권한이 필요할때 마다 사용자로부터 권한을..

    justbobby.tistory.com

     

     

    댓글

Designed by Tistory.