Android 6.0 런타임 사용 권한 상세 정보

17931 단어
실행할 때 권한은 안드로이드 6.0 버전에서 시작합니다. 프로젝트에서 targetSdkVersion이 23보다 크면 동적 권한을 고려해야 합니다.권한은 또 일반 권한과 위험 권한으로 나뉜다.일반 권한은 다음과 같습니다.
android.permission.ACCESS LOCATIONEXTRA_COMMANDS 
android.permission.ACCESS NETWORKSTATE 
android.permission.ACCESS NOTIFICATIONPOLICY 
android.permission.ACCESS WIFISTATE 
android.permission.ACCESS WIMAXSTATE 
android.permission.BLUETOOTH 
android.permission.BLUETOOTH_ADMIN 
android.permission.BROADCAST_STICKY 
android.permission.CHANGE NETWORKSTATE 
android.permission.CHANGE WIFIMULTICAST_STATE 
android.permission.CHANGE WIFISTATE 
android.permission.CHANGE WIMAXSTATE 
android.permission.DISABLE_KEYGUARD 
android.permission.EXPAND STATUSBAR 
android.permission.FLASHLIGHT 
android.permission.GET_ACCOUNTS 
android.permission.GET PACKAGESIZE 
android.permission.INTERNET 
android.permission.KILL BACKGROUNDPROCESSES 
android.permission.MODIFY AUDIOSETTINGS 
android.permission.NFC 
android.permission.READ SYNCSETTINGS 
android.permission.READ SYNCSTATS 
android.permission.RECEIVE BOOTCOMPLETED 
android.permission.REORDER_TASKS 
android.permission.REQUEST INSTALLPACKAGES 
android.permission.SET TIMEZONE 
android.permission.SET_WALLPAPER 
android.permission.SET WALLPAPERHINTS 
android.permission.SUBSCRIBED FEEDSREAD 
android.permission.TRANSMIT_IR 
android.permission.USE_FINGERPRINT 
android.permission.VIBRATE 
android.permission.WAKE_LOCK 
android.permission.WRITE SYNCSETTINGS 
com.android.alarm.permission.SET_ALARM 
com.android.launcher.permission.INSTALL_SHORTCUT 
com.android.launcher.permission.UNINSTALL_SHORTCUT

일반 권한은 필요할 때 명세서 파일에 설명하기만 하면 됩니다.위험 권한은 명세서 파일에 명시해야 하는 것 외에 코드에서 동태적으로 판단 신청을 해야 한다.위험 권한은 다음과 같습니다.
android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR

android.permission-group.CAMERA 
android.permission.CAMERA

android.permission-group.CONTACTS   
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS

android.permission-group.LOCATION   
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION

android.permission-group.MICROPHONE 
android.permission.RECORD_AUDIO

android.permission-group.PHONE  
android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
com.android.voicemail.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS

android.permission-group.SENSORS    
android.permission.BODY_SENSORS

android.permission-group.SMS    
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
android.permission.READ_CELL_BROADCASTS

android.permission-group.STORAGE    
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE

위험 권한은 그룹별로 나뉘는데 각 그룹에서 특정한 권한이 허용되거나 거부되면 같은 그룹의 다른 권한도 상응하는 자동으로 허용되거나 거부된다.targetSdkVersion이 23보다 크면 우리가 위험 권한을 사용할 때 이러한 논리에 따라 처리해야 한다.
먼저 현재 응용 프로그램이 권한이 있는지 판단하고 없으면 신청한다. 사용자가 허락하거나 거절한 후에 해당하는 방법을 리셋하고 우리는 리셋에서 자신의 논리를 처리한다.
단일 권한 신청
Activity/Fragment에서 권한이 있는지 판단하는 방법은 checkSelfPermission()이고, 권한을 신청하는 방법은 RequestPermissions()이며, 사용자가 허락하거나 거절하면 리셋 방법인 onRequestPermissionsResult()이다.
Activity/Fragment에서 이러한 방법을 제공했지만 만약에 우리가 이런 방법을 사용한다면 안드로이드 버전이 23보다 큰지 아닌지를 판단하려면 코드는 다음과 같다.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ //        }else{ //        }

구글 엔지니어는 당연히 이런 것들을 고려하여 개발자에게 호환 패키지를 제공하고Activity/Fragment에서ContextCompat을 사용한다.checkSelfPermission()이 권한이 있는지 여부를 판단합니다.Activity에서 Activity Compat을 사용합니다.requestPermissions() 요청 권한Fragment에서 직접 RequestPermissions()로 권한을 요청하고 앞에ActivityCompat을 붙이지 마십시오. 그렇지 않으면 Fragment가 있는Activity의 리셋 방법을 리셋합니다.Activity/Fragment에서 사용자가 권한을 허용하거나 거부한 후에 onRequestPermissionsResult () 방법을 되돌려줍니다.다음은 일반적인 시스템 카메라 사진 기능을 호출하는 코드입니다.
       private void takePhoto() {
           Intent photoIn = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

          startActivityForResult(photoIn, TAKE_PHOTO_REQUEST); 
      }

프로젝트 targetSdkVersion이 23보다 크면 동적 요청 권한이 필요합니다.
if (ContextCompat.checkSelfPermission(MySetupActivity.this,  Manifest.permission.CAMERA)!=  PackageManager.PERMISSION_GRANTED) {
  ActivityCompat.requestPermissions(MySetupActivity.this,new String[]{Manifest.permission.CAMERA}, 100);
} else {
    takePhoto();
}

권한이 있는지 아닌지를 먼저 판단하고 관련 코드를 직접 집행하는 것이 있으면 권한을 신청한다.사용자가 허용 또는 거부 권한을 클릭하면 onRequestPermissionsResult 메서드가 리콜되고 이 메서드에서 처리됩니다.
  @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

if (requestCode == 100) {//  
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        takePhoto();
    } else {
        // Permission Denied
        AlertDialog mDialog = new AlertDialog.Builder(MySetupActivity.this)
                .setTitle("    ")
                .setMessage("      ,     !")
                .setPositiveButton("  ", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                        ShowAppSetDetails.showInstalledAppDetails(MySetupActivity.this, "user.zhuku.com");
                        LogPrint.logILsj(TAG, "      ");
                    }
                })
                .setCancelable(true)
                .create();
        mDialog.show();
    }
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

사용자가 권한을 허락한 후에 우리는 관련 코드를 직접 실행하고 거부하면 사용자에게 탄창 알림이 권한을 열어야 하는지 여부를 알립니다.그중의
ShowAppSetDetails.showInstalledAppDetails(MySetupActivity.this, "user.zhuku.com");

현재 app 정보 설정 인터페이스를 여는 코드입니다.구체적인 코드는 다음과 같습니다.
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;

/**
 *    :     “      ”
 *    :Li Shengjie
 *     :2016/11/25 1:40
 *    :Li Shengjie
 *     :2016/11/25 1:40
 *     :
 */

public class ShowAppSetDetails {
private static final String SCHEME = "package";
/**
 *     InstalledAppDetails     Extra  (  Android 2.1     )
 */
private static final String APP_PKG_NAME_21 = "com.android.settings.ApplicationPkgName";
/**
 *     InstalledAppDetails     Extra  (  Android 2.2)
 */
private static final String APP_PKG_NAME_22 = "pkg";
/**
 * InstalledAppDetails    
 */
private static final String APP_DETAILS_PACKAGE_NAME = "com.android.settings";
/**
 * InstalledAppDetails  
 */
private static final String APP_DETAILS_CLASS_NAME = "com.android.settings.InstalledAppDetails";

/**
 *     InstalledAppDetails                。   Android 2.3(Api Level
 * 9)  ,  SDK     ; 2.3  ,        (  InstalledAppDetails  )。
 *
 * @param context
 * @param packageName        
 */
public static void showInstalledAppDetails(Context context, String packageName) {
    Intent intent = new Intent();
    final int apiLevel = Build.VERSION.SDK_INT;
    if (apiLevel >= 9) { // 2.3(ApiLevel 9)  ,  SDK     
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts(SCHEME, packageName, null);
        intent.setData(uri);
    } else { // 2.3  ,        (  InstalledAppDetails  )
        // 2.2 2.1 ,InstalledAppDetails   APP_PKG_NAME  。
        final String appPkgName = (apiLevel == 8 ? APP_PKG_NAME_22
                : APP_PKG_NAME_21);
        intent.setAction(Intent.ACTION_VIEW);
        intent.setClassName(APP_DETAILS_PACKAGE_NAME,
                APP_DETAILS_CLASS_NAME);
        intent.putExtra(appPkgName, packageName);
    }
    context.startActivity(intent);
}
}

앱이 권한을 신청할 때 사용자가'더 이상 알리지 않음'을 클릭하면 거부 권한을 직접 리셋해 구글 엔지니어에게 shouldshow Request Permission Rationale() 방법을 제공한다.
호환성 패키지의 방법은 Activity Compat입니다.shouldshow RequestPermissionRationale (), Fragment에서 사용하려면 shouldshow RequestPermissionRationale () 를 직접 사용하십시오.
ActivityCompat.shouldshow RequestPermissionRationale () 방법의 반환값은boolean 형식입니다. 첫 번째 권한을 신청할 때false로 되돌아갑니다. 사용자가 '알림 안 하기' 를 누르면true로 되돌아갑니다.세부 코드는 다음과 같습니다.
if (ContextCompat.checkSelfPermission(MySetupActivity.this, Manifest.permission.CAMERA)
                        != PackageManager.PERMISSION_GRANTED) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(MySetupActivity.this, Manifest.permission.CAMERA)) {
                        //       
                        mDialog = new AlertDialog.Builder(MySetupActivity.this)
                                .setTitle("    ")
                                .setMessage("        ,       ,    ?")
                                .setPositiveButton(" ", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.cancel();
                                        ActivityCompat.requestPermissions(MySetupActivity.this,
                                                new String[]{Manifest.permission.CAMERA},
                                                100);
                                    }
                                })
                                .setNegativeButton(" ", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.cancel();
                                    }
                                })
                                .setCancelable(true)
                                .create();
                        mDialog.show();
                    } else {
                        ActivityCompat.requestPermissions(MySetupActivity.this,
                                new String[]{Manifest.permission.CAMERA},
                                100);
                    }

                } else {
                    takePhoto();
}

Fragment의 경우 코드는 다음과 같습니다.
 if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {
                if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
                    //       
                    mDialog = new AlertDialog.Builder(getContext())
                            .setTitle("    ")
                            .setMessage("        ,       ,    ?")
                            .setPositiveButton(" ", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                    requestPermissions(new String[]{Manifest.permission.CAMERA},
                                            PERMISSIONS_CAMERA);
                                }
                            })
                            .setNegativeButton(" ", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.cancel();
                                }
                            })
                            .setCancelable(true)
                            .create();
                    mDialog.show();
                } else {
                    requestPermissions(new String[]{Manifest.permission.CAMERA},
                            PERMISSIONS_CAMERA);
                }

            } else {
                selectPicFromCamera();
            }

특히 Fragment에서 권한을 요청하면Activity에서도 onRequestPermissionsResult () 를 다시 썼다면 onRequestPermissionsResult () 방법에는 반드시 슈퍼를 써야 합니다.onRequestPermissionsResult(requestCode, permissions, grantResults);이 코드는 쓰지 않으면 Activity에서 Fragment를 실행하는 권한 리셋 방법을 나누어 주지 않습니다.
Fragment에서 RequestPermissions() 소스는 다음과 같습니다.
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHost == null) {
    throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
mHost.onRequestPermissionsFromFragment(this, permissions, requestCode);
}

사실 Fragment 요청 권한도 Activity에서 요청한 것이고, 리셋 결과를 Fragment에 전달했을 뿐이다.
한 번에 여러 권한 신청
예를 들어 요청할 권한은 다음과 같습니다.
 /**
 *            
 */
protected String[] permissionList = {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION,
    Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS,
    Manifest.permission.READ_PHONE_STATE,
    Manifest.permission.CAMERA,
    Manifest.permission.WRITE_EXTERNAL_STORAGE,
    Manifest.permission.READ_EXTERNAL_STORAGE

};
우리는 먼저 모든 권한이 이미 허락되었거나 거부되었는지 판단해야 한다. 어떤 권한이 허락되지 않았을 때, 허락되지 않은 권한을 신청해야 한다.
protected void onStart() {
super.onStart();

if (PermissionUtils.checkSelfPermission(SplashActivity.this, permissionList)) {
    PermissionUtils.checkPermissions(this, 0, permissionList);
} else {
    //      
}

}

여기서 PermissionUtils 클래스의 코드는 다음과 같습니다.
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;

import java.util.ArrayList;
import java.util.List;

public class PermissionUtils {
/**
 *     
 */
public static void checkPermissions(Activity activity, int permissRequestCode, String... permissions) {
    List needRequestPermissonList = findDeniedPermissions(activity, permissions);
    if (null != needRequestPermissonList
            && needRequestPermissonList.size() > 0) {
        ActivityCompat.requestPermissions(activity,
                needRequestPermissonList.toArray(
                        new String[needRequestPermissonList.size()]),
                permissRequestCode);
    }
}

/**
 *               
 */
public static List findDeniedPermissions(Activity activity, String[] permissions) {
    List needRequestPermissonList = new ArrayList();
    for (String perm : permissions) {
        if (ContextCompat.checkSelfPermission(activity,
                perm) != PackageManager.PERMISSION_GRANTED) {
            needRequestPermissonList.add(perm);
        } else {
            if (ActivityCompat.shouldShowRequestPermissionRationale(
                    activity, perm)) {
                needRequestPermissonList.add(perm);
            }
        }
    }
    return needRequestPermissonList;
}

public static boolean checkSelfPermission(Context context, String[] permissions) {
    for (String perm : permissions) {
        if (ContextCompat.checkSelfPermission(context, perm) != PackageManager.PERMISSION_GRANTED) {
            return true;
        }
    }
    return false;
}

public static boolean checkSelfResult(int[] grantResults) {
    for (int grantResult : grantResults) {
        if (grantResult != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}
}

onRequestPermissionsResult 콜백 방법에서는 다음과 같이 처리됩니다.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);

if (requestCode == 0) {
    if (PermissionUtils.checkSelfResult(grantResults)) {
        // Permission Granted
        //      
    } else {
        // Permission Denied

        if (null == mDialog)
            mDialog = new AlertDialog.Builder(SplashActivity.this)
                    .setTitle("    ")
                    .setMessage("            ,     !")
                    .setPositiveButton("  ", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                            ShowAppSetDetails.showInstalledAppDetails(SplashActivity.this, "user.zhuku.com");
                            LogPrint.logILsj(TAG, "      ");
                        }
                    })
                    .setCancelable(false)
                    .create();

        if (!mDialog.isShowing()) {
            mDialog.show();
        }
    }
}
}

만약 프로젝트가 페이지에 보일 때 권한 신청을 해야 한다면, onStart () 방법에 넣고, onResume () 에 쓰지 마십시오.onResume () 에 쓰여 있으면 사용자가 권한에 동의하면 괜찮고, 거부를 클릭하면 권한 거부 방법을 되돌려줍니다. 이 때 시스템이 권한을 신청하는 대화상자가 사라지고, onResume () 요청 권한을 다시 호출해서 대화 상자를 표시합니다. 거부를 하면 onResume () 방법을 다시 호출하여 계속 순환합니다.시스템에서 권한을 요청하는 대화 상자가 한 번에 Activity 를 열었기 때문입니다.부분 소스는 다음과 같습니다.
 public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHasCurrentPermissionsRequest) {
    Log.w(TAG, "Can reqeust only one set of permissions at a time");
    // Dispatch the callback with empty arrays which means a cancellation.
    onRequestPermissionsResult(requestCode, new String[0], new int[0]);
    return;
}
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}

이 블로그는 오리지널로vitamio에서 유래한 것으로 전재는 출처를 밝혀 주십시오.

좋은 웹페이지 즐겨찾기