💡 PhotoActivity.kt, activity_photo.xml, file_paths.xml, Manifest.xml
사진찍고 사진을 저장 → 이미지뷰에 띄우기(Bitmap) 예제를 해보겠습니다.
Manifest에 내 사진을 접근해줄 Provider추가. application 내부
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /> //접근할 위치? 라고 생각하면 될듯하다.
</provider>
android.support.v4.content.FileProvider에서 불러오면 안된다.
2020. 5월에 라이브러리 관리 중단
getBitmap()함수는 API29에서 더이상 지원하지 않는다. 버전별로 분기를 나누면 될듯하다.
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="my_images"
path="Android/data/com.example.fileproviderexample/files/Pictures" />
</paths>
<!--
저장될 외부 이미지 파일 경로이다.-->
activity_photo.xml

PhotoActivity.kt
onCreate
- 권한요청
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED && checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
) {
Log.d(TAG, "권한 설정 완료")
} else {
Log.d(TAG, "권한 설정 요청")
ActivityCompat.requestPermissions(
this@PhotoActivity,
arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE),
1
)
}
}
- 권한요청 request
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
Log.d(TAG, "onRequestPermissionsResult");
if (grantResults[0] == PackageManager.PERMISSION_GRANTED&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Permission: " + permissions[0] + "was " + grantResults[0]); }
}
- 사진찍기 버튼 클릭 이벤트
binding.photoBtn.setOnClickListener{
dispatchTakePictureIntent()
}
- 해당 메소드 dispatchTakePictureIntent
private fun dispatchTakePictureIntent() {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) //찍은 이미지의 섬네일을 가져올 수 있다.(찍은거 미리보기 창)
if (takePictureIntent.resolveActivity(packageManager) != null) { //ACTION_IMAGE_CAPTURE 해줄 수 있는 액티비티가 내 기기 내에 존재하는지
// 찾고 없으면 null을 반환
// resolveActivity를 호출할 때 패키지 매니저를 보내는 이유는 무엇일까?
var photoFile: File? = null
try {
photoFile = createImageFile() //toString해서 Log찍어보니 절대 경로가 다 나온다, 구현해놓은 함수
Log.d(TAG, photoFile.toString())
} catch (ex: IOException) {
}
if (photoFile != null) {
val photoURI: Uri =
FileProvider.getUriForFile(this,
"com.example.fileproviderexample.fileprovider", photoFile) //왜 this로 보내줄까?
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI) //Name은 딱히 안 중요한듯하다.(첫번쨰 인자가 Name) 우린 카메라 앱에서 사진이 담길 Uri를 보내줄거다
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO) //인텐트 보내자.
}
}
}
💡 패키지 매니저 역할 중 하나 : Software repository로부터 패키지를 찾고, 다운로드하고, 설치하고, 업데이트하는 역할
- 이미지 파일 경로 생성 및 파일 객체 반환
@Throws(IOException::class)
private fun createImageFile(): File? {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val imageFileName = "JPEG_" + timeStamp + "_" //파일 이름이다. 타임 스탬프로 이름 안 겹치게 해주려는듯하다.
val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES) // 픽쳐 디렉토리 파일 객체를 참조받아온다.
val image: File = File.createTempFile(imageFileName, ".jpg", storageDir) //파일 어떤 이름으로, 어떤 형식으로, 어디에 만들지 정해주는 아이이다.
mCurrentPhotoPath = image.absolutePath//이 경로로 저장을 요청할 것이다. 받아온다면 이 경로로 접근하면 되겠지?
return image.absoluteFile// 파일 객체로 반환한다. 그냥 image로도 된다. 둘 다 파일이긴하니깐
}
- 인텐트 결과를 받아오자.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode==REQUEST_TAKE_PHOTO) {
if (resultCode ==RESULT_OK) {
val file:File= File(mCurrentPhotoPath) //미리 저장해둔 경로로 파일을 받아오자.
val bitmap:Bitmap // 이미지 파일일테니깐 이미지로 변환해야겠지?
if (Build.VERSION.SDK_INT>= 29) { //getBitmap이 API 29이후 버전에다가 쓰면 안된다고 한다. 그래서 분기를 나누었다.
val source: ImageDecoder.Source =
ImageDecoder.createSource(contentResolver, Uri.fromFile(file))
Log.d(TAG, source.toString())
try {
bitmap = ImageDecoder.decodeBitmap(source) //이부분은 왜 try를 써야하는걸까?
if (bitmap != null) {
binding.imageView.setImageBitmap(bitmap) //받아온 이미지 여기에 불러올거다.
}
} catch (e: IOException) {
e.printStackTrace()
}
} else {
try { //이부분은 왜 try를 써야하는걸까?
bitmap = MediaStore.Images.Media.getBitmap(contentResolver, Uri.fromFile(file))
Log.d(TAG, bitmap.toString())
if (bitmap != null) {
binding.imageView.setImageBitmap(bitmap) //받아온 이미지 여기에 불러올거다.
}
} catch (e: IOException) {
e.printStackTrace()
}
}
} else {
Log.d("sadsadasdasdasd", "null!!!")
}
} else {
Log.d("sadasd", "null!!!")
}
}
결과



ref: https://ebbnflow.tistory.com/177
'Android(Kotlin) Study A부터 Z까지 등반' 카테고리의 다른 글
Broad Cast 이론 ( Android 공식문서 ) (0) | 2022.02.12 |
---|---|
안드로이드 서비스 + Notification(음악플레이어 컨트롤) (0) | 2022.01.23 |
Activitiy란? 4대 컴포넌트 중 하나에 대해서 (0) | 2022.01.11 |
==, ===, equals, hashcode란 (0) | 2022.01.11 |
Java, Kotlin 그리고 객체지향에 대해서 (0) | 2022.01.11 |