관리 메뉴

정상에서 IT를 외치다

[Android,GetImage] 카메라와 갤러리에서 이미지 가져오기 (Nougat 대응) 본문

안드로이드

[Android,GetImage] 카메라와 갤러리에서 이미지 가져오기 (Nougat 대응)

Black-Jin 2018. 10. 23. 12:14
728x90
반응형

안녕하세요. 블랙진입니다.!!


카메라와 갤러리에서 이미지 가져오기를 단계별로 포스팅을 진행하고 있습니다.


1. 카메라와 갤러리에서 이미지 가져오기

2. Nougat(Android OS 7) 대응하기

3. 카메라회전 각도를 고려한 이미지 가져오기

4. 가져온 이미지 크롭(Crop) 하기


이전 포스팅에 이어서 누가 버전에 대응할 수 있는 방법을 포스팅 하겠습니다.


Chapter 2. Nougat 대응하기


이슈


안드로이드 OS 누가 버전 이후부터는 file:// URI 의 노출을 금지하고 있습니다. 만약 URI 를 그냥 사용하게 되면 FileUriExposedException 발생하게 됩니다.


해결방안


FileProvider 을 통해 URI 를 감싸주면 됩니다.


<참고자료>

안드로이드 공식 페이지

http://programmar.tistory.com/4http://programmar.tistory.com/5




1. main/res 폴더 안에 provider_paths.xml 을 만들어 줍니다.



provider.paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="storage/emulated" path="."/>
</paths>



2.  AndroidManifest.xml 에 provide 를 추가해 줍니다.

<!-- 사진 촬영을 위한 provide -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="{package name}.provider"
android:exported="false"
android:grantUriPermissions="true">

<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>

AndroidManifest 에서 <application> .. </application> 사이에 추가해 주면 됩니다. 이 때 authorities 값은 '패키지명.provider' 로 설정해 주셔야합니다.



3. takePhoto 함수 수정

private void takePhoto() {

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

try {
tempFile = createImageFile();
} catch (IOException e) {
Toast.makeText(this, "이미지 처리 오류! 다시 시도해주세요.", Toast.LENGTH_SHORT).show();
finish();
e.printStackTrace();
}
if (tempFile != null) {

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {

Uri photoUri = FileProvider.getUriForFile(this,
"{package name}.provider", tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, PICK_FROM_CAMERA);

} else {

Uri photoUri = Uri.fromFile(tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, PICK_FROM_CAMERA);

}
}
}

카메라로 보내는 tempFile 의 uri 를 provider 로 감싸주는 로직이 추가되었습니다. 안드로이드 누가 하위 버전에서는 provider로 uri 를 감싸주면 동작하지 않는 경우가 있기 때문에 모든 기기에 적용하기 위해서는 버전 구분을 꼭 해주셔야 합니다.


Chapter2. 깃허브



관련 포스팅


1.  카메라와 갤러리에서 이미지 가져오기

2. Nougat(Android OS 7) 대응하기

3. 카메라회전 각도를 고려한 이미지 가져오기

4. 가져온 이미지 크롭(Crop) 하기

반응형
6 Comments
  • 프로필사진 감사합니다 2018.11.15 23:55 안녕하세요 덕분에 공부 잘 하고 있습니다
    궁금한점이 한가지 있는데 알려주신대로 1단계 2단계까지 진행해왔습니다만
    갤러리에 가서 사진을 선택하면 오류는없는데(팅기지 않습니다) 이미지뷰에 변함이 없습니다..
    로그캣에도 별 다른 오류가 발생하지 않고요.. 무엇이 문제 일까요?
  • 프로필사진 Black-Jin 2018.11.16 00:09 신고 안녕하세요~! 댓글 감사합니다:)
    먼저 오류가 없는데 안되는 거면....댓글만으로는 원인을 파악하기는 힘들것 같습니다.ㅠㅜ

    올려놓은 제 깃허브 소스를 다운받아 잘 실행되는지 확인 후 본인 코드와 비교 분석을 해보시는게 어떨까 싶습니다.

    2단계 에서 중요한 부분은 provider을 사용해서 이미지주소를 가져와야 되는것입니다. 포스팅 상단 <참고자료>에 적은 링크 또한 참고해 보면서 원인을 찾아 가시면 좋을 것 같습니다:D
  • 프로필사진 안녕하세요 2019.04.05 17:36 안녕하세요. 코드 그대로 따라했는데요. 카메라에서 뒤로가기 하면 제대로 돌아오는데(null 처리됨) 갤러리에서 뒤로가기 하면 오류 뜨면서 어플이 꺼집니다. 갤러리 뒤로가기 할때 널처리는 어떻게하면 좋을까요?
  • 프로필사진 Black-Jin 2019.04.05 21:59 신고 안녕하세요. 갤러리에서 뒤로가게 되면 onActivityResult 에서 if(resultCode != RESULT_OK) { } 스코프 안이 실행됩니다. 이때 tempFile 이 null 로 들어올 텐데 tempFile 이 null 인 상태에서 사용을 하게 되면 에러가 발생합니다. 간단한 방법으로는 if(tempFile == null) return 코드를 통해 tempFile 이 null 일 때 아래 코드들을 실행하지 말고 return 코드를 통해 넘어가 주세요.

    혹은 샘플 완성 코드인
    https://github.com/dlwls5201/MyImageSample
    를 확인하며 비교해주세요.
  • 프로필사진 질문있습니다 2020.05.04 17:28 안녕하세요
    게시글을 보고 열심히 공부중인 학생입니다.
    github 코드를 보며 따라해보던 중 오류가 생겨 댓글 남깁니다.

    제가 androidx 사용중인데, manifest파일 내에서
    android:name="com.soundcloud.android.crop.CropImageActivity"

    여기에서 에러가 발생해 다른 java파일들에서도 Crop부분에 에러가 뜨는 것 같은데
    이 부분을 어떻게 수정해주어야 할 지 잘 모르겠습니다.
    어떻게 해결해야 할 지 알려주실 수 있을까요?
  • 프로필사진 Wuny 2021.02.05 18:07 신고 지금쯤 이미 에러를 찾으셨겠지만..
    이런 에러를 겪는 분들을 위해 적습니다
    manifest.xml에

    <activity android:name="com.soundcloud.android.crop.CropImageActivity" />

    추가해주세요
댓글쓰기 폼