requestPermission과 startActivityForResult는 Result API가 추가됨에 따라 deprecated 되었습니다. 따라서 ResultAPI를 이용해 처리하세요.
먼저, 아래와 같이 dependency 를 app 폴더에 있는 build.gradle 에 추가하세요.
androidx.activity:activity:1.3.1
(https://maven.google.com/web/index.html 에서 필요한 구글 라이브러리를 검색하실 수 있습니다.)
Result API를 사용하기 위해서는 두가지를 제공해 주어야 합니다. 첫번째 어떤 Intent 생성과 처리에 대한 부분, 두번째로는 Activity를 띄우기위해 콜백을 등록하는 부분.
첫번째는 아래와 같이 ActivityResultContract 클래스를 구현해 주면 됩니다. 이 부분을 기존의 startActivityForResult 에 넘겨줄Intent를 생성하는 부분과 onActivityResult 콜백 처리부분을 합쳐놓은 것으로 보시면 됩니다.
public abstract class ActivityResultContract<I, O> {
/* Create an intent that can be used for Activity.startActivityForResult */
public abstract @NonNull Intent createIntent(@NonNull Context context,
@SuppressLint("UnknownNullness") I input);
/** Convert result obtained from {@link Activity#onActivityResult} to O */
@SuppressLint("UnknownNullness")
public abstract O parseResult(int resultCode, @Nullable Intent intent);
}
public class GetContent extends ActivityResultContract<String, Uri> {
...
}
두번째는, 기존처럼 onActivityResult콜백을 사용하지 않기 때문에 콜백을 미리 등로해주어야 합니다.
중요한 점은, 아래처럼 등록하는 코드를 사용할 때, 멤버변수등으로 처리해서 액티비티나 프레그먼트가 생성시 바로 등록될 수 있도록 해주어야 합니다.
val getContent = registerForActivityResult(GetContent()) { uri: Uri? ->
// Handle the returned Uri
}
다음에는 startActivityForResult 호출하는 대신,
getContent.launch("image/*")
처럼 호출하면 됩니다.
해당 API에서는 많이 사용하는 Intent들은 미리 만들어서 제공하고 있습니다. ActivityResultContrats 나 아래 링크를 보시면 어떤 Contract이 제공되는지 확인하실 수 있습니다.
https://developer.android.com/reference/androidx/activity/result/contract/package-summary
Permission과 이미지를 고르는 Intent들도 이미 제공되고 있습니다.
아래처럼 처리하시면 되는데, 제가 테스트해 본 코드는 코틀린으로 작성되었기 때문에 자바로 변환하시길 바라고, 테스트는 많이 안되었기 때문에 세부적인 처리는 추가하시기 바랍니다.
fun onCreate(saveInstance: Bundle?) {
super.onCreate(saveinstance)
...
pickImageButon.setOnClickListener {
if(ActivityCompat.checkSelfPermission(requireContext(), android.Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) { //여기는 님의 코드 그대로 사용
permissionActivityForResult.launch(android.Manifest.permission.CAMERA)
} else {
startActivityForImageSelection()
}
}
}
private val permissionActivityForResult = registerForActivityResult(ActivityResultContracts.RequestPermission()) { accepted ->
if (accepted) {
startActivityForImageSelection()
}
}
private val pickImageActivityForResult = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
uri?.let {
previewImage.setImageURI(uri)
}
}
private fun startActivityForImageSelection() {
pickImageActivityForResult.launch("image/*")
}
그리고 아마 안드로이드 버전이 올라가면서 File provider라는 걸 제공해야 하는 걸로 기억하는데, 그 부분은 아랫처럼 AndroidManifest.xml에 File provider를 등록하시고,
<application
....
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
xml 리소스 폴더에 아래와 같이 provider_paths.xml 을 추가해주셔야 할 것 같습니다. 이렇게 해야 이미지를 선택할 때 캐시폴더에 접근하는데 문제가 생기지 않을 듯합니다.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path
name="cached_files"
path="." />
<files-path
name="images"
path="." />
</paths>
ResultAPI의 개발자 문서는 아래 링크에 있습니다.
https://developer.android.com/training/basics/intents/result