블로그 이사했습니다!
👇 블로그 이전 공지 👇
👇 새 블로그에서 글 보기 👇
[Android] 이미지 가져오기 - 카메라, 갤러리 이용 — Win Record (tistory.com)
코드 흐름
카메라/갤러리 버튼 클릭 → 암시적 인텐트 동작 → 인텐트의 결과 액티비티에 띄우기
권한설정
- manifest.xml
카메라 사용을 위한 권한 설정
<!--카메라 및 저장위치를 위치 접근을 위한 권한 설정-->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--앱을 사용하기 위한 조건
required 값에 따라 반드시 필요한 속성일 수도, 없어도 일단 실행은 되는 속성일 수도 있음-->
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
안드로이드 공식 사이트에서는 android API 19부터 WRITE_EXTERNAL_STORAGE를 설정하지 않아도 된다고 하지만 몇 번 빌드를 하다 보니 추가하지 않고는 저장 관련 권한 설정이 안 바뀌어 일단 추가
카메라 촬영 시 이미지 파일 생성을 위한 provider
<application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.getimage.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/external" />
</provider>
...
</application>
- external.xml
provider에서 사용하는 resource 파일
res>xml 폴더 안에 생성한다.
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="sdcard"
path="." />
</paths>
- MainActivity.java
카메라 및 갤러리 접근을 위한 접근 확인 받기
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// 권한 체크
boolean hasCamPerm = checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
boolean hasWritePerm = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if (!hasCamPerm || !hasWritePerm) // 권한 없을 시 권한설정 요청
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
...
}
화면
- activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_main"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btn_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="@string/camera" />
<Button
android:id="@+id/btn_gallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="@string/gallery" />
</LinearLayout>
</LinearLayout>
버튼 클릭 이벤트
- MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// 권한체크
...
// 카메라 버튼 이벤트
findViewById(R.id.btn_camera).setOnClickListener(new View.OnClickListener() {
@SuppressLint("QueryPermissionsNeeded")
@Override
public void onClick(View view) {
intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
File imageFile = null;
try {
imageFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
if (imageFile != null) {
Uri imageUri = FileProvider.getUriForFile(getApplicationContext(),
"com.example.getimage.fileprovider",
imageFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CAMERA); // final int CAMERA = 100;
}
}
}
});
// 갤러리 버튼 이벤트
findViewById(R.id.btn_gallery).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
intent = new Intent(Intent.ACTION_PICK);
intent.setType(MediaStore.Images.Media.CONTENT_TYPE);
intent.setType("image/*");
startActivityForResult(intent, GALLERY); // final int GALLERY = 101;
}
});
...
}
파일 생성하는 메소드
@SuppressLint("SimpleDateFormat")
File createImageFile() throws IOException {
// 이미지 파일 생성
// SimpleDateFormat imageDate = new SimpleDateFormat("yyyyMMdd_HHmmss");
String timeStamp = imageDate.format(new Date()); // 파일명 중복을 피하기 위한 "yyyyMMdd_HHmmss"꼴의 timeStamp
String fileName = "IMAGE_" + timeStamp; // 이미지 파일 명
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file = File.createTempFile(fileName, ".jpg", storageDir); // 이미지 파일 생성
imagePath = file.getAbsolutePath(); // 파일 절대경로 저장하기, String
return file;
}
저장한 파일 위치: 내 PC\핸드폰명\Phone\Android\data\패키지명\files\Pictures
- external.xml
res>xml>external.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="sdcard"
path="." />
</paths>
이미지 세팅하기
인텐트의 결과를 받는 onActivityResult()에서 이미지 세팅
- MainActivity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) { // 결과가 있을 경우
Bitmap bitmap = null;
switch (requestCode) {
case GALLERY: // 갤러리에서 이미지로 선택한 경우
// 1) 이미지 절대경로로 이미지 세팅하기
Cursor cursor = getContentResolver().query(data.getData(), null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
imagePath = cursor.getString(index);
cursor.close();
}
// 2) InputStream 으로 이미지 세팅하기
try {
InputStream inputStream = getContentResolver().openInputStream(data.getData());
bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
imageView.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
break;
case CAMERA: // 카메라로 이미지 가져온 경우
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; // 이미지 축소 정도. 원 크기에서 1/inSampleSize 로 축소됨
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
imageView.setImageBitmap(bitmap);
}
}
갤러리에서 선택할 경우 1)절대경로를 가져와 세팅하는 방법, 2)InputStream을 사용하는 방법이 있음
결과 화면
1. 카메라
2. 갤러리 선택
전체코드
다음글
참고자료
[Android] 명시적 인텐트 & 암시적 인텐트 (tistory.com)
큰 비트맵을 효율적으로 로드 | Android 개발자 | Android Developers
Getting image from storage and camera. | by Md. Razon Hossain | Medium
안드로이드 이미지의 절대 경로 가져오기 (tistory.com)
사진 촬영 | Android 개발자 | Android Developers
Getting image from storage and camera. | by Md. Razon Hossain | Medium
안드로이드 카메라 예제 (2/3) - 카메라 .. : 네이버블로그 (naver.com)
공부하며 정리한 글입니다. 내용에 대한 피드백은 언제나 환영입니다.
'android' 카테고리의 다른 글
가져온 이미지 회전 막기 (0) | 2021.01.14 |
---|---|
Glide 사용하기 (0) | 2021.01.14 |
Firebase와 안드로이드 프로젝트 연결하기 (0) | 2021.01.11 |
디데이 계산기 (0) | 2021.01.11 |
WebView 웹뷰 (0) | 2021.01.10 |
댓글