반응형
1. 크롭 라이브러리 추가 - build.gradle의 dependencies
implementation 'com.soundcloud.android:android-crop:1.0.1@aar'
2. 권한 추가 - AndroidManifest.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_STORAG"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
3. activity_main.xml 에 버튼과 이미지뷰 추가
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_takepicture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"/>
<Button
android:id="@+id/btn_takepicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:text="카메라"/>
</RelativeLayout>
4. MainActivity.java 작업하기
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
ImageView imageView;
Button btnCamera;
final static int TAKE_PICTURE = 1;
final static int CROP_PICTURE = 2;
private Uri pictureUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView)findViewById(R.id.iv_takepicture);
btnCamera = (Button)findViewById(R.id.btn_takepicture);
btnCamera.setOnClickListener(this);
//Uri exposure 무시
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
//권한 요청
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 && checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
}
else { //권한 허용 요청
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED && grantResults[2] == PackageManager.PERMISSION_GRANTED){
}
}
@Override
public void onClick(View view) {
switch (view.getId())
{
// 버튼 눌렀을 때, 카메라에서 이미지 가져오기
case R.id.btn_takepicture:
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 임시로 사용할 파일의 경로를 생성
String url = "tmp_" + String.valueOf(System.currentTimeMillis()) + ".jpg";
pictureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), url));
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, pictureUri);
cameraIntent.putExtra("return-data", true);
startActivityForResult(cameraIntent, CROP_PICTURE);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
//크롭된 이미지 가져와서 이미지뷰에 보여주기
case TAKE_PICTURE:
if (resultCode == RESULT_OK && data.hasExtra("data")) { //데이터를 가지고 있는지 확인
final Bundle extras = data.getExtras();
if(extras != null)
{
Bitmap photo = extras.getParcelable("data"); //크롭한 이미지 가져오기
imageView.setImageBitmap(photo); //이미지뷰에 넣기
}
// 임시 파일 삭제
File f = new File(pictureUri.getPath());
if(f.exists())
f.delete();
break;
}
break;
// 이미지 크롭
case CROP_PICTURE: {
// 이미지를 가져온 이후의 리사이즈할 이미지 크기를 결정합니다.
// 이후에 이미지 크롭 어플리케이션을 호출하게 됩니다.
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(pictureUri, "image/*");
intent.putExtra("outputX", 200); //크롭한 이미지 x축 크기
intent.putExtra("outputY", 200); //크롭한 이미지 y축 크기
intent.putExtra("aspectX", 1); //크롭 박스의 x축 비율
intent.putExtra("aspectY", 1); //크롭 박스의 y축 비율
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
startActivityForResult(intent, TAKE_PICTURE);
break;
}
}
}
}
SDK version이 24이상에서는 이런 오류가 발생할 수 있습니다.
android.os.FileUriExposedException: file:///storage/emulated/0/tmp_1608973420078.jpg exposed beyond app through ClipData.Item.getUri()
이 오류를 해결하기 위해서는 FileProvide를 사용하는 방법이 있습니다. FileProvide는 여러 가지로 복잡해서 여기서는 onCreate( )에 다음 코드를 추가해서 해결해주었습니다.
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
FileProvide를 사용하려면 다음 링크를 참조하면 도움이 될 것입니다.
android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
The app is crashing when I'm trying to open a file. It works below Android Nougat, but on Android Nougat it crashes. It only crashes when I try to open a file from the SD card, not from the system
stackoverflow.com
실행화면
반응형
'Android' 카테고리의 다른 글
[Android] 8주차 스터디 (Firebase) (1) | 2021.01.07 |
---|---|
[Android] 네비게이션 드로어(Navigation Drawer) 사용하기 + 풀스크린(Fullscreen) (0) | 2020.12.27 |
[Android] Room 데이터 베이스 (0) | 2020.12.18 |
[Android] 7주차 스터디 (Camera) (0) | 2020.11.29 |
[Android] 6주차 스터디 (Gallery) (0) | 2020.11.29 |