많은 수의 앱에서 갤러리에서 사진을 업로드하고 카메라로 사진을 찍어서 올리는 행위를 합니다.
인스타그램이나 페이스북처럼 sns을 통해서 자신의 일상을 사진의 형태로 공유하기 때문인데요. 그러다보니 저도 앱들을 개발하면서 이미지 관련 포스팅을 여러개 남겼습니다.
웹뷰에서 이미지 업로드 , 카메라 갤러리에서 이미지 가져오기 (코틀린), 카메라 갤러리에서 이미지 가져오기 (자바)
그런데 또 같은 주제로 포스팅을 하는 이유는 'targetSdk 30' 강제 적용 때문입니다. ( 공식문서 )
간략하게 설명드리자면 외부 저장소를 모든 앱들과 공용으로 사용했었는데 앱별 외부 저장소를 제공하도록 변경됐습니다. 자세한 사항은 구글링이나 제가 참고한 블로그 포스팅을 참고해주세요.
구현 코드는 마이그레이션 하는 분들을 위해 간략하게 설명드리고 전체 소스는 뒤에 붙이도록 하겠습니다.
| 기본 원리
기본 카메라 앱을 실행시켜서 찍은 사진을 onActivityResult로 결과 값을 받아서 미리 지정된 경로에 이미지 파일을 코드로 저장하는 방식으로 코드 구현 합니다.
targetSdk30으로 마이그레이션 하는 경우 이미지 파일 저장시 사용된 경로만 변경해주면 됩니다.
기존에 구현된 버전을 마이그레이션 하는 경우
private fun createImageFile(): File { // 사진이 저장될 폴더 있는지 체크
var imageName = "plantdiary_${System.currentTimeMillis()}"
var file: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(imageName,".jpg", file).apply {
cameraImagePath = absolutePath
}
}
'getExternalFilesDir' 경로에 파일을 생성해 리턴하고 그 경로를 'cameraImagePath' 변수에 담아서 이미지를 헨들링합니다.
처음 구현하시는 경우 ( createImageFile 메소드 외 전체 코드 )
카메라 권한 체크
<uses-permission android:name="android.permission.CAMERA" />
private fun showCamera() {
var cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
var storagePermission =
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (cameraPermission == PackageManager.PERMISSION_DENIED || storagePermission == PackageManager.PERMISSION_DENIED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(
Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE
),
REQ_PERMISSION_CAMERA
)
} else {
var state = Environment.getExternalStorageState()
if (TextUtils.equals(state, Environment.MEDIA_MOUNTED)) {
var intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.resolveActivity(packageManager)?.let {
createImageFile().let {
var photoUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID + ".provider",
it
)
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
startActivityForResult(intent, REQ_CAMERA)
}
}
}
}
}
카메라로 찍은 사진 처리
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQ_CAMERA -> {
// cameraImagePath 변수 사용 하여 처리
....
}
}
}
provider 설정 ( os 7.0 이상 부터 적용 해야하는 부분 )
androidManifest.xml
<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>
res > xml 폴더 생성 및 파일 생성 ( 파일명 : provider_paths, 소스상 네이밍으로 변경 가능 )
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="hidden" path="path"/>
<external-path name="external_files" path="."/>
</paths>
매번 바뀌는 정책들로 고생하시는 개발자분들 힘내세욥 화이팅
'안드로이드 > 팁' 카테고리의 다른 글
[AOS] 데이터 보안 양식 제출 (0) | 2022.02.04 |
---|---|
[AOS] UGC 정책 위반 해결하기 (0) | 2022.01.11 |
[AOS] adb pair로 빌드 간편하게 하기 (0) | 2021.11.12 |
[Android] Edittext 천단위 콤마(,) 설정 - 소수점 포함 (0) | 2021.07.06 |
[And] 백그라운드 위치 권한 사용하기 ( Android9,10 대응 ) (0) | 2021.04.29 |