본문 바로가기

안드로이드 스튜디오

[ 안드로이드 ] 카메라 / 앨범 사용법

다른 응용 프로그램과 공유할 모든 경로가 포함된 XML 파일 생성 : res > xml > fileprovider.xml 

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <root-path
        name="root"
        path="." />

    <cache-path
        name="cache"
        path="." /> <!--Context.getCacheDir() 내부 저장소-->
    <files-path
        name="files"
        path="." /> <!--Context.getFilesDir() 내부 저장소-->

    <external-path
        name="external"
        path="."/>  <!--  Environment.getExternalStorageDirectory() 외부 저장소-->
    <external-cache-path
        name="external-cache"
        path="."/> <!--  Context.getExternalCacheDir() 외부 저장소-->
    <external-files-path
        name="images"
        path="Pictures" /> <!--  Context.getExternalFilesDir() 외부 저장소-->
</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 );

//                //임시파일 생성
//                File file = createImgCacheFile( );
//                String cacheFilePath = file.getAbsolutePath( );


            // 압축시킨다. 해상도 낮춰서
            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);

//                imageView.setImageBitmap( getBitmapAlbum( imageView, albumUri ) );

        } 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;
    }


}

• 실행 화면 ( 카메라는 에뮬레이터에서 실행 불가능 )

안드로이드 스튜디오 에뮬레이터 실행 예제