글
간단히 사진 찍기
Android
2014. 1. 29. 09:26
아래의 퍼미션이 필요하다.
<manifest ... >
<uses-feature android:name="android.hardware.camera"
android:required="true" />
...
</manifest>
- 만약 required를 false로 한다면, Runtime에 hasSystemFeature(PackageManager.FEATURE_CAMERA)를 통해 카메라가 사용 가능한지 알아볼 수 있다.
간단히 내장 카메라 앱을 통해 사진을 찍으려면 아래와 같이 한다. (resolveActivity 체크를 해야 앱이 죽는 걸 방지할 수 있다)
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
(내장 카메라 앱) 썸네일을 얻기 위해서는 아래와 같이 결과를 받는다.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}- 다른 앱과 공유해도 되는 사진의 경우 아래 메소드로 얻을 수 있는 경로에 저장하는 것을 권장한다.
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); - 다른 앱과 공유하면 안되는 사진의 경우 getExternalFilesDir()로 얻을 수 있는 경로에 저장하는 것을 권장한다. 이 경로는 앱 삭제시에 함께 삭제된다.
- 외장 저장 장치의 경우 아래의 퍼미션이 필요하다. (Android 4.4 부터는 별도의 퍼미션이 필요없다. 타 앱에서 접근 하지 못함)
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
...
</manifest> - 파일명 중복을 방지하도록 임시 파일을 생성하려면, 아래와 같은 방식을 추천한다.
String mCurrentPhotoPath;
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
} - (내장 카메라 앱) 이제 전체 사진을 위에 만든 임시 파일에 받아오자!
static final in REQUEST_TAKE_PHOTO = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
} - 한정된 메모리로 전체 사진을 로드하면, Out of Memory가 발생할 수 있다. 메모리 사용량을 줄이기 위해서 아래와 같은 방법을 사용하면 좋다.
private void setPic() {
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
출처 : http://developer.android.com/