Android R(API 30) 이상 버전부터는 WRITE_EXTERNAL_STORAGE 권한을 받을 수 없게되었다.
이에 따라 기존의 파일 저장 방식이나 삭제 방식을 사용할 수 없게 되었는데
이번 포스트에서는 그 해결법을 공유하고자 한다.
https://codechacha.com/ko/android11-storage-updates/
이제는 MediaStore 를 통해 DeleteRequest를 보내는 방식으로 사용자에게 삭제 허가를 받도록 바뀌었다.
[주의] 이 방법은 Android R 이상에서만 사용한다. 버전 검사를 필수로 하자.
먼저 File Path를 Uri로 변환해주는 작업이 필요하다.
private Uri getImageUri(String path) {
File file = new File(path);
if (file.exists()) {
long id = 0;
ContentResolver CR = activity.getContentResolver();
String selection = MediaStore.Images.Media.DATA;
String[] args = new String[]{file.getAbsolutePath()};
String[] projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA};
String sortOrder = MediaStore.Images.Media.TITLE + " ASC";
Cursor cursor = CR.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection + "=?", args, null);
if (cursor != null) {
while (cursor.moveToNext()) {
int idIndex = cursor.getColumnIndex(MediaStore.Images.Media._ID);
id = Long.parseLong(cursor.getString(idIndex));
try {
return ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
} catch (Exception e) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
((RecoverableSecurityException)e).getUserAction().getActionIntent().getIntentSender();
}
}
}
cursor.close();
}
}
return null;
}
이어서 변환된 Uri들을 List에 담아준다.
List<Uri> uris = new ArrayList<>();
for (String path : paths) {
Uri uriFromFile = getImageUri(path);
if (uriFromFile != null) uris.add(uriFromFile);
}
Uri List를 담은 IntentSenderRequest를 만들어준다
if (uris.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
IntentSender intentSender = MediaStore.createDeleteRequest(activity.getContentResolver(), uris).getIntentSender();
if (intentSender != null) return new IntentSenderRequest.Builder(intentSender).build();
}
}
만들어진 Request를 요청할 ActivityResultLauncher 를 선언한다
launcher = registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(), result -> {
if (result.getResultCode() == RESULT_OK) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Toast.makeText(this, "삭제 성공", Toast.LENGTH_SHORT).show();
DeleteFinish();
}
}
});
이제 분기처리를 통해 Android R 이상일 때 실행하도록 해주면 끝이다
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
launcher.launch(GFA.DeleteAfterAndroid11(deleteList));
} else {
GFA.DeleteFileList(deleteList);
}
실행해보면 다이얼로그를 통해 사용자에게 앱에서 사진을 지우는것을 허가하시겠습니까? 라며 요청한다
참... 이래저래 힘들게 한다 안드로이드
'Android(Java)' 카테고리의 다른 글
안드로이드 커스텀 진동 (0) | 2022.04.27 |
---|---|
안드로이드 날짜간의 차이 계산 알고리즘 (0) | 2022.04.08 |
안드로이드 버전 별 이미지 저장 (0) | 2022.03.16 |
자주 까먹는 문법 정리 (0) | 2022.02.23 |
RecyclerView & ViewPager2 끝에서 스크롤 감지 (0) | 2021.12.31 |