1. Camera
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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_result"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="촬영"/>
</LinearLayout>
</LinearLayout>
2) MainActivity.java
package com.example.cameraexample;
import static android.media.ExifInterface.TAG_ORIENTATION;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.gun0912.tedpermission.PermissionListener;
import com.gun0912.tedpermission.TedPermission;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_IMAGE_CAPTURE = 672;
private String imageFilePath;
private Uri photoUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 권한체크
TedPermission.with(this)
.setPermissionListener(permissionListener)
.setRationaleMessage("카메라 권한이 필요합니다.")
.setDeniedMessage("권한이 필요합니다.")
.setPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
.check();
findViewById(R.id.btn_capture).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
}
if (photoFile != null) {
photoUri = FileProvider.getUriForFile(getApplicationContext(), getPackageName(), photoFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
}
}
}
});
}
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "TEST_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName,
".jpg",
storageDir
);
imageFilePath = image.getAbsolutePath();
return image;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bitmap bitmap = BitmapFactory.decodeFile(imageFilePath);
ExifInterface exif = null;
try {
exif = new ExifInterface(imageFilePath);
} catch (IOException e) {
e.printStackTrace();
}
int exifOrientation;
int exifDegree;
if (exif !=null) {
exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
exifDegree = exifOrientationToDegress(exifOrientation);
} else {
exifDegree = 0;
}
((ImageView) findViewById(R.id.iv_result)).setImageBitmap(rotate(bitmap, exifDegree));
}
}
private int exifOrientationToDegress(int exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
return 90;
} else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
return 180;
} else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
return 270;
}
return 0;
}
private Bitmap rotate(Bitmap bitmap, float degree) {
Matrix matrix = new Matrix();
matrix.postRotation(degree);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
PermissionListener permissionListener = new PermissionListener() {
@Override
public void onPermissionGranted() {
Toast.makeText(getApplicationContext(), "권한이 허용됨", Toast.LENGTH_SHORT).show();
}
@Override
public void onPermissionDenied(List<String> deniedPermissions) {
Toast.makeText(getApplicationContext(), "권한이 거부됨", Toast.LENGTH_SHORT).show();
}
}
}
3) AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.CameraExample"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<provider
android:authorities="com.example.cameraexample"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
</application>
</manifest>
4) 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.cameraexample/files/Pictures"/>
</paths>
2. 코드 구성
1) 구성 절차
- activity_main에서 카메라를 실행시킬 버튼 선언 및 id 부여
- Manifest파일에서 카메라 기능 요청(<use-feature>)
- MainActivity에서 카메라 실행을 위한 코드 구성
전역변수 구성: private으로 이미지 캡쳐, 파일경로, URI 메소드 선언
권한 요청(Tedpermission 라이브러리 사용)
클릭 후 활성화 될 기능에 대한 정의(인텐트 호출 / 클릭하면 카메라 화면, , 찍은 사진이름 날짜(timestamp)로 자동 생성)
찍고나서의 활성화기능 정의(파일 디렉토리 설정)
미리보기 이미지 가져오기(onActivityResult / 비트맵으로 사진 인코딩, 또는 디코딩 방식 정의, exif 테그정보 연결)
미리보기 사진 회전기능
사진과 사진정보의 rotation기능
권한 부여여부에 대한 응답 토스트메시지 추가
- AndroidManifest 권한 허용 (uses-permission / 이전버전에서만 허용, 안드로이드 4.4이후부터는 디렉터리 접근 자체가 불가능하여 이전 버전에서는 권한요청을 하도록 사용, 예시에는 적용X)
- 새로운 file_paths.xml 생성, 파일 디렉토리 경로 지정
2) 참고 사항
- 링크
https://developer.android.com/training/camera/photobasics?hl=ko#java
- 과거보다 현재 버전이 권한에 대해 더욱 제한적이기때문에 지속적인 확인이 필요함, 여기 작성된 내용들은 4년전 정보를 바탕으로 작성되었으므로 로직만 참고하되 링크를 통해 차이점을 알고 적용
'Development > Android Studio' 카테고리의 다른 글
(Android Studio) Chapter6. Fragment (0) | 2023.02.24 |
---|---|
(Android Studio) Chapter5. Recycler View (0) | 2023.02.23 |
(Android Studio) Chapter3. ListView, Navigation Menu, Shared Preferences, Web View (0) | 2023.02.12 |
(Android Studio) Chapter2. ImageView, Package Structure (0) | 2023.02.05 |
(Android Studio) Chapter1. 개요 (0) | 2023.02.05 |