Android                
            API-23 +의 런타임 권한
        
        
            
    수색…
소개
Android Marshmallow는 Runtime Permission 모델을 선보였습니다. 권한은 보통 및 위험 권한의 두 가지 범주로 분류됩니다. 현재 사용자가 런타임에 위험한 권한 을 부여합니다.
비고
sdk 23에서 Android는 위험한 권한 그룹으로 분류 된 범위 내에서 Android 6.0 이상을 실행하는 기기의 권한에 대한 런타임 권한을 필요로합니다. 위험한 권한 그룹은 사용자의 개인 정보 및 / 또는 보안을 손상시키는 것으로 간주됩니다.
다음은 위험한 사용 권한 그룹 목록입니다.
위험한 사용 권한 그룹
 허가 그룹 
 달력 
 카메라 
 콘택트 렌즈 
 위치 
 마이크로폰 
 전화 
 센서 
 SMS 
 저장 
이 그룹의 모든 권한을 사용하려면 대상 SDK가 23 이상인 Android 6.0 이상의 장치에 대한 런타임 사용 권한을 관리해야합니다.
일반 사용 권한
다음은 일반적인 사용 권한 목록입니다. 이것들은 사용자의 프라이버시 나 보안에 위험한 것으로 간주되지 않으므로 sdk 23 이상의 런타임 권한을 요구하지 않습니다.
 ACCESS_LOCATION_EXTRA_COMMANDS 
 ACCESS_NETWORK_STATE 
 ACCESS_NOTIFICATION_POLICY 
 ACCESS_WIFI_STATE 
 블루투스 
 블루투스 _ADMIN 
 BROADCAST_STICKY 
 CHANGE_NETWORK_STATE 
 CHANGE_WIFI_MULTICAST_STATE 
 CHANGE_WIFI_STATE 
 DISABLE_KEYGUARD 
 EXPAND_STATUS_BAR 
 GET_PACKAGE_SIZE 
 INSTALL_SHORTCUT 
 인터넷 
 KILL_BACKGROUND_PROCESSES 
 MODIFY_AUDIO_SETTINGS 
 NFC 
 READ_SYNC_SETTINGS 
 READ_SYNC_STATS 
 RECEIVE_BOOT_COMPLETED 
 REORDER_TASKS 
 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 
 REQUEST_INSTALL_PACKAGES 
 알람을 설정하다 
 SET_TIME_ZONE 
 SET_WALLPAPER 
 SET_WALLPAPER_HINTS 
 TRANSMIT_IR 
 UNINSTALL_SHORTCUT 
 USE_FINGERPRINT 
 떨리다 
 깨어남 
 WRITE_SYNC_SETTINGS 
Android 6.0 다중 사용 권한
이 예제는 Android 6 이상에서 런타임에 권한을 확인하는 방법을 보여줍니다.
public static final int MULTIPLE_PERMISSIONS = 10; // code you want.
String[] permissions = new String[] {
    Manifest.permission.WRITE_EXTERNAL_STORAGE,
    Manifest.permission.CAMERA,
    Manifest.permission.ACCESS_COARSE_LOCATION,
    Manifest.permission.ACCESS_FINE_LOCATION
};
@Override
void onStart() {
    if (checkPermissions()){
        // permissions granted.    
    } else {
        // show dialog informing them that we lack certain permissions
    }
}
private boolean checkPermissions() {
    int result;
    List<String> listPermissionsNeeded = new ArrayList<>();
    for (String p:permissions) {
        result = ContextCompat.checkSelfPermission(getActivity(),p);
        if (result != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(p);
        }
    }
    if (!listPermissionsNeeded.isEmpty()) {
        ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MULTIPLE_PERMISSIONS);
        return false;
    }
    return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MULTIPLE_PERMISSIONS:{
            if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                // permissions granted.
            } else {
                // no permissions granted.
            }
            return;
        }
    }
}
        브로드 캐스트, URI에서 권한 실행
인 텐트를 등록 된 브로드 캐스트 리시버로 보낼 때 권한 검사를 할 수 있습니다. 보내는 권한은 태그 아래 등록 된 권한과 교차 확인됩니다. 연결된 수신자에게 브로드 캐스트를 보낼 수있는 사용자를 제한합니다.
 권한을 가진 방송 요청을 보내려면, 상기의 문자열로 권한 지정 Context.sendBroadcast(Intent intent, String permission) 전화를하지만, 수신기의 앱이 브로드 캐스트를 수신하기 위해 그 권한이 있어야합니다 명심하십시오. 수신자는 발신자보다 먼저 설치해야합니다. 
메소드 서명은 다음과 같습니다.
 void sendBroadcast (Intent intent, String receiverPermission)
 //for example to send a broadcast to Bcastreceiver receiver
 Intent broadcast = new Intent(this, Bcastreceiver.class);
 sendBroadcast(broadcast, "org.quadcore.mypermission");
 브로드 캐스트 보낸 사람이 sendBroadcast를 통해 보낸 요청한 권한을 포함해야한다는 것을 매니페스트에 지정할 수 있습니다.
 <!--  Your special permission -->
 <permission android:name="org.quadcore.mypermission" 
    android:label="my_permission" 
    android:protectionLevel="dangerous"></permission>
 또한이 브로드 캐스트를 수신해야하는 응용 프로그램의 매니페스트에서 사용 권한을 선언하십시오.
 <!--  I use the permission ! -->
 <uses-permission android:name="org.quadcore.mypermission"/>
 <!-- along with the receiver -->
 <receiver android:name="Bcastreceiver" android:exported="true" />
 참고 : 수신자와 방송사 모두 허가를 요구할 수 있으며,이 경우 관련 권한이 부여 된 대상에게 전달되도록 인 력 확인을 통과해야합니다. 권한을 정의하는 앱을 먼저 설치해야합니다.
동일한 사용 권한 그룹의 여러 런타임 사용 권한
매니페스트에는 두 그룹의 네 가지 위험한 런타임 권한이 있습니다.
<!-- Required to read and write to shredPref file. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- Required to get location of device. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
 사용 권한이 필요한 활동. 앱이 백그라운드에있는 동안 권한이 취소되어 앱이 다운 될 수 있기 때문에 권한이 필요한 모든 활동에서 권한을 확인하는 것이 중요합니다.
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.act_layout);
    
    // A simple check of whether runtime permissions need to be managed 
    if (Build.VERSION.SDK_INT >= 23) {
        checkMultiplePermissions();
    }
 우리는 각 그룹에서 이들 중 하나에 대한 권한을 요청하기 만하면되며이 그룹의 다른 모든 권한은 사용자가 권한을 취소하지 않는 한 부여됩니다.
private void checkMultiplePermissions() {
    if (Build.VERSION.SDK_INT >= 23) {
        List<String> permissionsNeeded = new ArrayList<String>();
        List<String> permissionsList = new ArrayList<String>();
        
        if (!addPermission(permissionsList, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
            permissionsNeeded.add("GPS");
        }
        if (!addPermission(permissionsList, android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
            permissionsNeeded.add("Read Storage");
        }
        
        if (permissionsList.size() > 0) {
            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                    REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
            return;
        }
    }
}
private boolean addPermission(List<String> permissionsList, String permission) {
    if (Build.VERSION.SDK_INT >= 23)
        if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
            permissionsList.add(permission);
            // Check for Rationale Option
            if (!shouldShowRequestPermissionRationale(permission))
                return false;
        }
    return true;
}
 사용자가 권한을 허용하거나 허용하지 않은 결과를 처리합니다. 이 예에서 권한이 허용되지 않으면 앱이 종료됩니다.
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
        
            Map<String, Integer> perms = new HashMap<String, Integer>();
            // Initial
            perms.put(android.Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
            perms.put(android.Manifest.permission.READ_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
            
            // Fill with results
            for (int i = 0; i < permissions.length; i++)
                perms.put(permissions[i], grantResults[i]);
            if (perms.get(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                    && perms.get(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                // All Permissions Granted
                return;
            } else {
                // Permission Denied
                if (Build.VERSION.SDK_INT >= 23) {
                    Toast.makeText(
                            getApplicationContext(),
                            "My App cannot run without Location and Storage " +
                                    "Permissions.\nRelaunch My App or allow permissions" +
                                    " in Applications Settings",
                            Toast.LENGTH_LONG).show();
                    finish();
                }
            }
        }
        break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}
         PermissionUtil 사용
 PermissionUtil 은 컨텍스트에서 사용 권한을 요청하는 간단하고 편리한 방법입니다. 요청 된 모든 권한 ( onAllGranted() ), 요청이 거부 ( onAnyDenied() )되거나 합리적인 것이 필요한 경우 ( onRational() ) 필요한 경우 쉽게 수행 할 수 있습니다. 
귀하의 AppCompatActivity 또는 Fragment에서 사용자의 허가를 요청하고 싶은 곳
mRequestObject = PermissionUtil.with(this).request(Manifest.permission.WRITE_EXTERNAL_STORAGE).onAllGranted(
                new Func() {
                    @Override protected void call() {
                        //Happy Path
                    }
                }).onAnyDenied(
                new Func() {
                    @Override protected void call() {
                        //Sad Path
                    }
                }).ask(REQUEST_CODE_STORAGE);
  그리고 이것을 onRequestPermissionsResult 추가하십시오. 
if(mRequestObject!=null){
    mRequestObject.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
 AndroidManifest.xml에도 요청 된 권한을 추가하십시오.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        추상 기본 클래스에 모든 권한 관련 코드를 포함시키고이 기본 클래스의 활동을 확장하여보다 깨끗하고 재사용 가능한 코드를 얻으십시오.
public abstract class BaseActivity extends AppCompatActivity {
    private Map<Integer, PermissionCallback> permissionCallbackMap = new HashMap<>();
    @Override
    protected void onStart() {
        super.onStart();
        ...
    }
    @Override
    public void setContentView(int layoutResId) {
        super.setContentView(layoutResId);
        bindViews();
    }
    ...
    @Override
    public void onRequestPermissionsResult(
            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionCallback callback = permissionCallbackMap.get(requestCode);
        if (callback == null) return;
        // Check whether the permission request was rejected.
        if (grantResults.length < 0 && permissions.length > 0) {
            callback.onPermissionDenied(permissions);
            return;
        }
        List<String> grantedPermissions = new ArrayList<>();
        List<String> blockedPermissions = new ArrayList<>();
        List<String> deniedPermissions = new ArrayList<>();
        int index = 0;
        for (String permission : permissions) {
            List<String> permissionList = grantResults[index] == PackageManager.PERMISSION_GRANTED
                    ? grantedPermissions
                    : ! ActivityCompat.shouldShowRequestPermissionRationale(this, permission)
                        ? blockedPermissions
                        : deniedPermissions;
            permissionList.add(permission);
            index ++;
        }
        if (grantedPermissions.size() > 0) {
            callback.onPermissionGranted(
                    grantedPermissions.toArray(new String[grantedPermissions.size()]));
        }
        if (deniedPermissions.size() > 0) {
            callback.onPermissionDenied(
                    deniedPermissions.toArray(new String[deniedPermissions.size()]));
        }
        if (blockedPermissions.size() > 0) {
            callback.onPermissionBlocked(
                    blockedPermissions.toArray(new String[blockedPermissions.size()]));
        }
        permissionCallbackMap.remove(requestCode);
    }
    /**
     * Check whether a permission is granted or not.
     *
     * @param permission
     * @return
     */
    public boolean hasPermission(String permission) {
        return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
    }
    /**
     * Request permissions and get the result on callback.
     *
     * @param permissions
     * @param callback
     */
    public void requestPermission(String [] permissions, @NonNull PermissionCallback callback) {
        int requestCode = permissionCallbackMap.size() + 1;
        permissionCallbackMap.put(requestCode, callback);
        ActivityCompat.requestPermissions(this, permissions, requestCode);
    }
    /**
     * Request permission and get the result on callback.
     *
     * @param permission
     * @param callback
     */
    public void requestPermission(String permission, @NonNull PermissionCallback callback) {
        int requestCode = permissionCallbackMap.size() + 1;
        permissionCallbackMap.put(requestCode, callback);
        ActivityCompat.requestPermissions(this, new String[] { permission }, requestCode);
    }
}
 액티비티의 사용 예제
액티비티는 위에서 정의 된 추상 기본 클래스를 다음과 같이 확장해야합니다.
private void requestLocationAfterPermissionCheck() {
    if (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
        requestLocation();
        return;
    }
    // Call the base class method.
    requestPermission(Manifest.permission.ACCESS_FINE_LOCATION, new PermissionCallback() {
        @Override
        public void onPermissionGranted(String[] grantedPermissions) {
            requestLocation();
        }
        @Override
        public void onPermissionDenied(String[] deniedPermissions) {
            // Do something.
        }
        @Override
        public void onPermissionBlocked(String[] blockedPermissions) {
            // Do something.
        }
    });
}