• 다른 응용 프로그램과 공유할 모든 경로가 포함된 XML 파일 생성 : res > xml > fileprovider.xml
<?xml version="1.0" encoding="utf-8"?>
<paths >
<root-path
name ="root"
path ="." />
<cache-path
name ="cache"
path ="." />
<files-path
name ="files"
path ="." />
<external-path
name ="external"
path ="." />
<external-cache-path
name ="external-cache"
path ="." />
<external-files-path
name ="images"
path ="Pictures" />
</paths >
• AndroidManifest.xml 권한 및 파일 공유 설정
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<application
...
<provider
android:authorities="com.wngml.camera.fileprovider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/fileprovider" />
</provider>
...
/>
• 라이브러리 추가 (buil.gradle)
dependencies {
...
implementation 'commons-io:commons-io:2.4'
...
}
• 사진 찍는 코드 ( camera() ) / 앨범에서 사진 가져오는 코드 ( album() ) 작성
private void camera () {
int permissionCheck = ContextCompat.checkSelfPermission(
MainActivity.this , Manifest.permission.CAMERA);
if (permissionCheck != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this ,
new String[]{Manifest.permission.CAMERA} ,
1000 );
Toast.makeText(MainActivity.this , "카메라 권한 필요합니다." ,
Toast.LENGTH_SHORT).show();
return ;
} else {
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (i.resolveActivity(MainActivity.this .getPackageManager()) != null ){
String fileName = new SimpleDateFormat("yyyyMMdd_HHmmss" ).format(new Date());
photoFile = getPhotoFile(fileName);
Uri fileProvider = FileProvider.getUriForFile(MainActivity.this ,
"com.wngml.camera.fileprovider" , photoFile);
i.putExtra(MediaStore.EXTRA_OUTPUT, fileProvider);
startActivityForResult(i, 100 );
} else {
Toast.makeText(MainActivity.this , "이폰에는 카메라 앱이 없습니다." ,
Toast.LENGTH_SHORT).show();
}
}
}
private File getPhotoFile (String fileName) {
File storageDirectory = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
try {
return File.createTempFile(fileName, ".jpg" , storageDirectory);
}catch (IOException e){
e.printStackTrace();
return null ;
}
}
private void album () {
if (checkPermission()){
displayFileChoose();
}else {
requestPermission();
}
}
private void requestPermission () {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this ,
Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(MainActivity.this , "권한 수락이 필요합니다." ,
Toast.LENGTH_SHORT).show();
}else {
ActivityCompat.requestPermissions(MainActivity.this ,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 500 );
}
}
private boolean checkPermission () {
int result = ContextCompat.checkSelfPermission(MainActivity.this ,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_DENIED){
return false ;
}else {
return true ;
}
}
private void displayFileChoose () {
Intent i = new Intent();
i.setType("image/*" );
i.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(i, "SELECT IMAGE" ), 300 );
}
@Override
public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, @NonNull int [] grantResults) {
super .onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1000 : {
if (grantResults.length > 0 && grantResults[0 ] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this , "권한 허가 되었음" ,
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this , "아직 승인하지 않았음" ,
Toast.LENGTH_SHORT).show();
}
break ;
}
case 500 : {
if (grantResults.length > 0 && grantResults[0 ] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this , "권한 허가 되었음" ,
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this , "아직 승인하지 않았음" ,
Toast.LENGTH_SHORT).show();
}
}
}
}
@Override
protected void onActivityResult (int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == 100 && resultCode == RESULT_OK){
Bitmap photo = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
ExifInterface exif = null ;
try {
exif = new ExifInterface(photoFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
photo = rotateBitmap(photo, orientation);
OutputStream os;
try {
os = new FileOutputStream(photoFile);
photo.compress(Bitmap.CompressFormat.JPEG, 50 , os);
os.flush();
os.close();
} catch (Exception e) {
Log.e(getClass().getSimpleName(), "Error writing bitmap" , e);
}
photo = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
imageView.setImageBitmap(photo);
imageView.setScaleType(ImageView.ScaleType.CENTER);
}else if (requestCode == 300 && resultCode == RESULT_OK && data != null &&
data.getData() != null ){
Uri albumUri = data.getData( );
String fileName = getFileName( albumUri );
try {
ParcelFileDescriptor parcelFileDescriptor = getContentResolver( ).openFileDescriptor( albumUri, "r" );
if ( parcelFileDescriptor == null ) return ;
FileInputStream inputStream = new FileInputStream( parcelFileDescriptor.getFileDescriptor( ) );
photoFile = new File( this .getCacheDir( ), fileName );
FileOutputStream outputStream = new FileOutputStream( photoFile );
IOUtils.copy( inputStream, outputStream );
Bitmap photo = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
OutputStream os;
try {
os = new FileOutputStream(photoFile);
photo.compress(Bitmap.CompressFormat.JPEG, 60 , os);
os.flush();
os.close();
} catch (Exception e) {
Log.e(getClass().getSimpleName(), "Error writing bitmap" , e);
}
imageView.setImageBitmap(photo);
imageView.setScaleType(ImageView.ScaleType.CENTER);
} catch ( Exception e ) {
e.printStackTrace( );
}
}
super .onActivityResult(requestCode, resultCode, data);
}
public static Bitmap rotateBitmap (Bitmap bitmap, int orientation) {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1 , 1 );
break ;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180 );
break ;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180 );
matrix.postScale(-1 , 1 );
break ;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90 );
matrix.postScale(-1 , 1 );
break ;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90 );
break ;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90 );
matrix.postScale(-1 , 1 );
break ;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90 );
break ;
default :
return bitmap;
}
try {
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0 , 0 , bitmap.getWidth(), bitmap.getHeight(), matrix, true );
bitmap.recycle();
return bmRotated;
}
catch (OutOfMemoryError e) {
e.printStackTrace();
return null ;
}
}
public String getFileName ( Uri uri ) {
Cursor cursor = getContentResolver( ).query( uri, null , null , null , null );
try {
if ( cursor == null ) return null ;
cursor.moveToFirst( );
@SuppressLint("Range") String fileName = cursor.getString( cursor.getColumnIndex( OpenableColumns.DISPLAY_NAME ) );
cursor.close( );
return fileName;
} catch ( Exception e ) {
e.printStackTrace( );
cursor.close( );
return null ;
}
}
public Bitmap getBitmapAlbum ( View targetView, Uri uri ) {
try {
ParcelFileDescriptor parcelFileDescriptor = getContentResolver( ).openFileDescriptor( uri, "r" );
if ( parcelFileDescriptor == null ) return null ;
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor( );
if ( fileDescriptor == null ) return null ;
int targetW = targetView.getWidth( );
int targetH = targetView.getHeight( );
BitmapFactory.Options options = new BitmapFactory.Options( );
options.inJustDecodeBounds = true ;
BitmapFactory.decodeFileDescriptor( fileDescriptor, null , options );
int photoW = options.outWidth;
int photoH = options.outHeight;
int scaleFactor = Math.min( photoW / targetW, photoH / targetH );
if ( scaleFactor >= 8 ) {
options.inSampleSize = 8 ;
} else if ( scaleFactor >= 4 ) {
options.inSampleSize = 4 ;
} else {
options.inSampleSize = 2 ;
}
options.inJustDecodeBounds = false ;
Bitmap reSizeBit = BitmapFactory.decodeFileDescriptor( fileDescriptor, null , options );
ExifInterface exifInterface = null ;
try {
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ) {
exifInterface = new ExifInterface( fileDescriptor );
}
} catch ( IOException e ) {
e.printStackTrace( );
}
int exifOrientation;
int exifDegree = 0 ;
if ( exifInterface != null ) {
exifOrientation = exifInterface.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL );
if ( exifOrientation == ExifInterface.ORIENTATION_ROTATE_90 ) {
exifDegree = 90 ;
} else if ( exifOrientation == ExifInterface.ORIENTATION_ROTATE_180 ) {
exifDegree = 180 ;
} else if ( exifOrientation == ExifInterface.ORIENTATION_ROTATE_270 ) {
exifDegree = 270 ;
}
}
parcelFileDescriptor.close( );
Matrix matrix = new Matrix( );
matrix.postRotate( exifDegree );
Bitmap reSizeExifBitmap = Bitmap.createBitmap( reSizeBit, 0 , 0 , reSizeBit.getWidth( ), reSizeBit.getHeight( ), matrix, true );
return reSizeExifBitmap;
} catch ( Exception e ) {
e.printStackTrace( );
return null ;
}
}
• 실행 화면 ( 카메라는 에뮬레이터에서 실행 불가능 )
안드로이드 스튜디오 에뮬레이터 실행 예제