https://developer.android.com/training/permissions/requesting#java 를 보시면 자세한 설명이 나와 있구요, 저도 매일 쓰는 부분이 아니라서 해당 문서를 참조했어요. AndroidX Result API를 사용하도록 문서가 업데이트 된 것 같네요. 하시다가 막히는게 생기시면 저 사이트로 가셔서 디테일한 내용을 확인하시길 바래요.
대충 아랫처럼 퍼미션을 핸들링하는 클래스를 하나 만들어 봤습니다. 여러군데서 사용할 수 있는 기능이므로 Generlaization하면 훨씬 더 좋겠죠.
public class PermissionResolver {
private final int PERMISSION_REQUEST_CODE = 1004;
private final Activity activity;
private String[] wantedPermissions;
private int minSdkVersion = Build.VERSION_CODES.M;
private PermissionResolverCallback callback;
private PermissionResolver(Activity activity) {
this.activity = activity;
}
public static PermissionResolver with(Activity activity) {
return new PermissionResolver(activity);
}
public PermissionResolver want(String[] wantedPermissions) {
this.wantedPermissions = wantedPermissions;
return this;
}
public PermissionResolver minSdk(int minSdkVersion) {
this.minSdkVersion = minSdkVersion;
return this;
}
public PermissionResolver callback(PermissionResolverCallback callback) {
this.callback = callback;
return this;
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void requestPermission() {
TelephonyManager telephonyManager = OSUtil.getTelephonyManager(activity.getApplicationContext());
if (telephonyManager == null) {
callback.onError(new SystemServiceNotFoundException("Cannot find TelephonyManager"));
return;
}
if (!isSdkSupported()) {
callback.onSdkNotSupported();
return;
}
if (allPermissionsGranted()) {
callback.onPermissionsResolved();
return;
}
ActivityCompat.requestPermissions(activity, getUnresolvedPermissions(), PERMISSION_REQUEST_CODE);
}
private boolean allPermissionsGranted() {
return getUnresolvedPermissions().length == 0;
}
private boolean isSdkSupported() {
return OSUtil.isSdkGreaterEqualThan(minSdkVersion);
}
@NotNull
private String[] getUnresolvedPermissions() {
List<String> result = new ArrayList<>();
for (String permission : wantedPermissions) {
boolean granted = ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED;
if (!granted) {
result.add(permission);
}
}
return result.toArray(new String[]{});
}
public void onRequestPermissionsResult(int requestCode, String[] requestedPermissions) {
if (requestCode != PERMISSION_REQUEST_CODE) return;
if (requestedPermissions.length == 0) {
callback.onPermissionsCancelled();
return;
}
;
if (allPermissionsGranted()) {
callback.onPermissionsResolved();
return;
}
callback.onPermissionsDenied(unresolvedPermissions);
}
}
public interface PermissionResolverCallback {
void onError(Exception e);
void onSdkNotSupported();
void onPermissionsCancelled();
void onPermissionsResolved();
void onPermissionsDenied(String[] unresolvedPermissions);
}
public class OSUtil {
public static TelephonyManager getTelephonyManager(Context context) {
return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
public static boolean isSdkGreaterEqualThan(int apiLevel) {
return Build.VERSION.SDK_INT >= apiLevel;
}
}
public class PermissionUtil {
private final static String[] PHONE_NUMBER_PERMISSION_OREO = new String[]{
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.READ_PHONE_STATE};
private final static String[] PHONE_NUMBER_PERMISSION = new String[]{
Manifest.permission.READ_PHONE_STATE};
@NonNull
public static String[] getReadPhoneNumberPermissions() {
return OSUtil.isSdkGreaterEqualThan(Build.VERSION_CODES.O) ?
PHONE_NUMBER_PERMISSION_OREO : PHONE_NUMBER_PERMISSION;
}
}
PermissionResolver는 activity, callback 등등이 초기화가 필요하기 때문에 requestPermission하시기 전에 validation을 해주는 것도 좋을 것 같구요. 현재 수락이 안된 퍼미션을 구하는 부분은 Java8 stream API를 온전히 쓰실 수 있다면 그걸 사용하는 게 더 깔끔할 것 같습니다.
사용은 이런 식으로 하면 됩니다.
private PermissionResolver permissionResolver;
permissionResolver = PermissionResolver.with(this)
.minSdk(Build.VERSION_CODES.M)
.want(PermissionUtil.getReadPhoneNumberPermissions())
.callback(new PermissionResolverCallback() {
@Override
public void onError(Exception e) {
// 필요한 처리
}
@Override
public void onSdkNotSupported() {
// 필요한 처리
}
@Override
public void onPermissionsCancelled() {
// 필요한 처리
}
@Override
public void onPermissionsResolved() {
// 필요한 처리
}
@Override
public void onPermissionsDenied(String[] unresolvedPermissions) {
// 필요한 처리
}
});
permissionResolver.requestPermission();
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
permissionResolver.onRequestPermissionsResult(requestCode, permissions);
}
테스트를 안해 본 온전한 코드가 아니므로, 그대로 copy & paste 하지 마시고 개념을 이해하신 다음, 필요한 부분은 보완해 가시길 바랍니다.
먼저, 아랫처럼 Result API를 사용하기 추가하시면 좀 더 직관적인 코드를 작성하실 수 있습니다. 사용법은 첫라인의 링크에 나와 있습니다.
dependencies {
def activity_version = "1.1.0"
// Java language implementation
implementation "androidx.activity:activity:$activity_version"
// Kotlin
implementation "androidx.activity:activity-ktx:$activity_version"
}