1. 사진 촬영
카메라에서 찍은 사진을 "ActivityResultLauncher"로 읽어온다. "ActivityResultLauncher"는 "startActivityForResult" 의 대체로 "startActivityForResult"는 한 클래스 안에서 구현되는 Intent값을 모두 같은 "onActivityResult" 에서 받아야 함으로 Switch case로 분기처리 하여 받아야 했었다. "ActivityResultLauncher"는 메서드화 하여 각각 다른 이름으로 선언하여 원하는 위치에서 값을 받을 수 있다. "ActivityResultLauncher"에서 파일을 삭제하는 부분이 있는데 Scoped Storage 특성상 원본파일을 수정할 수 없음으로 전송시 파일을 전송한 뒤 삭제 하도록 하자.
Code
ActivityResultLauncher<Intent> photoCameraResultLauncher;
String imageName; // 카메라로 찍은 사진 이름
Uri imageUri; // 카메라로 찍은 사진 Uri
//카메라
public void openPhotoCamera() {
@SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
imageName = "TEMP_CAMERA_"+timeStamp+".jpg";
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = createImageUri(imageName, "image/jpeg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
photoCameraResultLauncher.launch(intent);
}
private Uri createImageUri(String fileName, String mimeType) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.IS_PENDING,0);
values.put(MediaStore.Images.Media.RELATIVE_PATH,Environment.DIRECTORY_PICTURES + File.separator + "UC Download" + File.separator + "TEMP" + File.separator); // 경로 설정
values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName); // 확장자가 붙어있는 파일명 ex) sample.jpg
values.put(MediaStore.Images.Media.MIME_TYPE, mimeType); // ex) image/jpeg
ContentResolver contentResolver = getContentResolver();
return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}
// 카메라에서 찍은 사진 처리
photoCameraResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if(result.getResultCode() == Activity.RESULT_OK){
if (imageUri != null) {
//데이터 전송 후 삭제
//getContentResolver().delete(imageUri, null, null);
}
}else {
// 사진을 찍고 x 버튼을 누른 경우 등...
// 생성한 파일을 삭제한다. 삭제하지 않으면 갤러리에 빈 파일이 남아있다.
getContentResolver().delete(imageUri, null, null);
}
});
2. 동영상 촬영
동영상도 사진촬영과 마찬가지로 동일하게 진행한다. 하지만 createVideoUri를 살펴보면 확장자명이 다름을 알 수 있다. 또한 Intent시 미디어스토어 비디오 촬영으로 접근해야 함의 차이가 있다.
Code
ActivityResultLauncher<Intent> videoCameraResultLauncher;
String videoName; // 카메라로 찍은 사진 이름
Uri videoUri; // 카메라로 찍은 사진 Uri
//비디오
public void openVideoCamera() {
@SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
videoName = "TEMP_CAMERA_"+timeStamp+".mp4";
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
videoUri = createVideoUri(videoName, "video/mp4");
intent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri);
videoCameraResultLauncher.launch(intent);
}
private Uri createVideoUri(String fileName, String mimeType) {
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.IS_PENDING,0);
values.put(MediaStore.Video.Media.RELATIVE_PATH,Environment.DIRECTORY_MOVIES + File.separator + "UC Download" + File.separator + "TEMP" + File.separator); // 경로 설정
values.put(MediaStore.Video.Media.DISPLAY_NAME, fileName); // 확장자가 붙어있는 파일명 ex) sample.mp4
values.put(MediaStore.Video.Media.MIME_TYPE, mimeType); // ex) video/mp4
ContentResolver contentResolver = getContentResolver();
return contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
}
//비디오 카메라에서 찍은 영상
videoCameraResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if(result.getResultCode() == Activity.RESULT_OK){
if (videoUri != null) {
}
}else {
getContentResolver().delete(videoUri, null, null);
}
});
최근 리팩토링을 진행하며 Target SDK33으로 변경하기 위하여 Scoped Storage를 적용하였다. Scoped Storage 적용 중 파일 권한에 관하여 Android 9 이하, 13 이하, 14 이상으로 나누어 코드를 구현하였는데 디바이스 내부 파일에 접근하는 방식이 OS 별로 달라져서 3가지 모두 권한 및 구현 방식의 분기 처리가 필요했다. 버전별로 모두 분기 처리하여 대응하였지만 다른 분들도 모두 이렇게 나누어 처리하였는지 궁금증이 생기는 순간이었다. 정말 이 방법밖에 없을까?? 아직 이 부분에 대하여 정확하게 나누어 언급되어 있는 자료가 없어 좀 더 지켜봐야 할 것 같다.
'Android > Android Java' 카테고리의 다른 글
[Android Java] TreeView (0) | 2023.12.20 |
---|---|
[Android Java] China Push, Doze Mode (0) | 2023.11.23 |
[Android Java] Scoped Storage 대응 (1) | 2023.11.21 |
[Android Java] Notification Action, RemoteInput (1) | 2023.11.13 |
[Android Java] Notification (0) | 2023.11.09 |