안드로이드 이미지(카메라, 앨범) 가져와 ImageView 이미지 뷰 보이기
첫 화면 입니다. “사진 선택” 버튼을 누르면 팝업창이 뜹니다.
팝업창은 앨범선택과 사진촬영 그리고 취소 버튼으로 구성됩니다.
앨범선택은 핸드폰 기기내 앨범저장소에서 사진을 선택합니다.
사진촬영은 카메라를 이용해 사진을 촬영하고 선택합니다.
앨범에 사진을 고르고 선택된 사진을 크롭한(crop) 후 이미지 뷰에 보여줍니다.
카메라를 통해 사진을 찍고, 찍은 사진을 크롭한(crop) 후 이미지 뷰에 보여줍니다.
코드 작성에 앞서 우선 먼저 레이아웃을 살펴보겠습니다.
레이아웃
activity_SignUp_Photo.xml
버튼을 두 개 구성하였습니다. 살펴보실 부분은 이미지뷰 와 버튼 입니다.
activity_SignUp_Photo.xml 소스 코드입니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1"
android:background="@color/color_WHITE">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="프로필 사진"
android:layout_marginTop="20dp"
android:textSize="40sp"
android:gravity="center_horizontal"
android:textColor="@color/color_MAIN" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="사진 한 장을 골라주세요!"
android:textSize="20sp"
android:gravity="center_horizontal"
android:textColor="@color/color_black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_marginTop="20sp"
>
<ImageView
android:id="@+id/user_image"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:maxWidth="200dp"
android:maxHeight="200dp"
android:adjustViewBounds="true"
android:src="@drawable/image_border"
android:onClick="onClick"/>
<Button
android:id="@+id/btn_UploadPicture"
android:layout_width="200dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="@color/color_button"
android:text="사진 선택"
android:onClick="onClick"
android:textSize="15sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
</LinearLayout>
<Button
android:layout_width="285dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:id="@+id/btn_signupfinish"
android:text="회원 가입 완료"
android:textColor="@color/color_WHITE"
android:background="@color/color_button"
android:onClick="onClick"/>
</LinearLayout>
</LinearLayout>
자바 코드
SignUpPhotoActivity.java
전체적인 소스 코드에 앞 서 핵심적인 기능 위주로 설명을 먼저 하겠습니다.
버튼 클릭 처리
버튼 클릭 리스너 부분 처리입니다.
btn_UploadPicture 버튼이 클릭 시 다이얼로그(팝업 창)을 띄웁니다.
다이얼로그 생성은 new AlertDialog.Builder(this) 이 부분 입니다.
.show();
를 통해 다이얼로그를 띄웁니다.
DialogInterface.onClickListener를 통해 다이얼로그의 사진촬영, 앨범선택 취소 버튼의 리스너를 생성합니다.
예로 취소버튼 리스너입니다. DialogInterface.OnClickListener cameraListener = new DialogInterface.OnClickListener() {
각 다이얼로그 액션 리스너는 함수 호출을 통해 처리를 합니다.
doTakePhotoAction(); 카메라를 통해 사진을 찍는 함수입니다.
doTakeAlbumAction(); 앨범에서 이미지를 가져오는 함수입니다.
@Override
public void onClick(View v) {
id_view = v.getId();
if(v.getId() == R.id.btn_signupfinish) {
/** SharedPreference 환경 변수 사용 **/
SharedPreferences prefs = getSharedPreferences("login", 0);
/** prefs.getString() return값이 null이라면 2번째 함수를 대입한다. **/
String login = prefs.getString("USER_LOGIN", "LOGOUT");
String facebook_login = prefs.getString("FACEBOOK_LOGIN", "LOGOUT");
String user_id = prefs.getString("USER_ID","");
String user_name = prefs.getString("USER_NAME", "");
String user_password = prefs.getString("USER_PASSWORD", "");
String user_phone = prefs.getString("USER_PHONE", "");
String user_email = prefs.getString("USER_EMAIL", "");
dbmanger.select(user_id,user_name,user_password, user_phone, user_email);
dbmanger.selectPhoto(user_name, mImageCaptureUri, absoultePath);
Intent mainIntent = new Intent(SignUpPhotoActivity.this, LoginActivity.class);
SignUpPhotoActivity.this.startActivity(mainIntent);
SignUpPhotoActivity.this.finish();
Toast.makeText(this, "회원가입이 완료되었습니다.", Toast.LENGTH_SHORT).show();
}else if(v.getId() == R.id.btn_UploadPicture) {
DialogInterface.OnClickListener cameraListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
doTakePhotoAction();
}
};
DialogInterface.OnClickListener albumListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
doTakeAlbumAction();
}
};
DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
};
new AlertDialog.Builder(this)
.setTitle("업로드할 이미지 선택")
.setPositiveButton("사진촬영", cameraListener)
.setNeutralButton("앨범선택", albumListener)
.setNegativeButton("취소", cancelListener)
.show();
}
}
위의 다이얼로그 버튼 클릭시 호출하는 함수에 대한 설명입니다.
카메라를 통해 사진 찍기
/**
* 카메라에서 사진 촬영
*/
public void doTakePhotoAction() // 카메라 촬영 후 이미지 가져오기
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 임시로 사용할 파일의 경로를 생성
String url = "tmp_" + String.valueOf(System.currentTimeMillis()) + ".jpg";
mImageCaptureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), url));
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
startActivityForResult(intent, PICK_FROM_CAMERA);
}
앨범에서 이미지 가져오기
/**
* 앨범에서 이미지 가져오기
*/
public void doTakeAlbumAction() // 앨범에서 이미지 가져오기
{
// 앨범 호출
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
startActivityForResult(intent, PICK_FROM_ALBUM);
}
각 함수들은 startActivityForResult 함수를 호출합니다.
onActivityResult 함수
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode,resultCode,data);
if(resultCode != RESULT_OK)
return;
switch(requestCode)
{
case PICK_FROM_ALBUM:
{
}
case PICK_FROM_CAMERA:
{
}
case CROP_FROM_IMAGE:
{
}
}
}
requestCode를 통해 switch문으로 분기합니다.
private static final int PICK_FROM_CAMERA = 0;
private static final int PICK_FROM_ALBUM = 1;
private static final int CROP_FROM_IMAGE = 2;
PICK_FROM_CAMERA 는 사진을 촬영하고 찍힌 이미지를 처리하는 부분
PICK_FROM_ALBUM 은 앨범에서 사진을 고르고 이미지를 처리하는 부분
CROP_FROM_IMAGE 는 이미지를 크롭하는 부분
case PICK_FROM_ALBUM:
{
// 이후의 처리가 카메라와 같으므로 일단 break없이 진행합니다.
// 실제 코드에서는 좀더 합리적인 방법을 선택하시기 바랍니다.
mImageCaptureUri = data.getData();
Log.d("SmartWheel",mImageCaptureUri.getPath().toString());
}
case PICK_FROM_CAMERA:
{
// 이미지를 가져온 이후의 리사이즈할 이미지 크기를 결정합니다.
// 이후에 이미지 크롭 어플리케이션을 호출하게 됩니다.
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(mImageCaptureUri, "image/*");
// CROP할 이미지를 200*200 크기로 저장
intent.putExtra("outputX", 200); // CROP한 이미지의 x축 크기
intent.putExtra("outputY", 200); // CROP한 이미지의 y축 크기
intent.putExtra("aspectX", 1); // CROP 박스의 X축 비율
intent.putExtra("aspectY", 1); // CROP 박스의 Y축 비율
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
startActivityForResult(intent, CROP_FROM_iMAGE); // CROP_FROM_CAMERA case문 이동
break;
}
case CROP_FROM_iMAGE:
{
// 크롭이 된 이후의 이미지를 넘겨 받습니다.
// 이미지뷰에 이미지를 보여준다거나 부가적인 작업 이후에
// 임시 파일을 삭제합니다.
if(resultCode != RESULT_OK) {
return;
}
final Bundle extras = data.getExtras();
// CROP된 이미지를 저장하기 위한 FILE 경로
String filePath = Environment.getExternalStorageDirectory().getAbsolutePath()+
"/SmartWheel/"+System.currentTimeMillis()+".jpg";
if(extras != null)
{
Bitmap photo = extras.getParcelable("data"); // CROP된 BITMAP
iv_UserPhoto.setImageBitmap(photo); // 레이아웃의 이미지칸에 CROP된 BITMAP을 보여줌
storeCropImage(photo, filePath); // CROP된 이미지를 외부저장소, 앨범에 저장한다.
absoultePath = filePath;
break;
}
// 임시 파일 삭제
File f = new File(mImageCaptureUri.getPath());
if(f.exists())
{
f.delete();
}
}
외부저장소(앨범)에 크롭된 이미지를 저장하는 함수
/SmartWheel 이라는 디렉토리가 있는지 if문을 체크를 한다.
디렉터리 폴더가 없다면 .mkdir() 함수호출을 통해 폴더를 만든다.
이후에 createNewFile()를 통해 파일을 생성하고 BufferedOutputStream과 FileOutputStream 복사를 진행한다.
sendBroadcast() 함수는 폰의 앨범에 크롭된 사진을 갱신하는 함수이다!!
이 함수를 쓰지 않는다면 크롭된 사진을 저장해도 앨범에 안보이며, 직접 파일 관리자 앱을 통해
폴더를 들어가야만 사진을 볼 수 있다.
/*
* Bitmap을 저장하는 부분
*/
private void storeCropImage(Bitmap bitmap, String filePath) {
String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/SmartWheel";
File directory_SmartWheel = new File(dirPath);
if(!directory_SmartWheel.exists()) // SmartWheel 디렉터리에 폴더가 없다면 (새로 이미지를 저장할 경우에 속한다.)
directory_SmartWheel.mkdir();
File copyFile = new File(filePath);
BufferedOutputStream out = null;
try {
copyFile.createNewFile();
out = new BufferedOutputStream(new FileOutputStream(copyFile));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(copyFile)));
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
SignUpPhotoActivity.Java 전체 소스 코드입니다.
package sincere.kimjungchul.smartwheel.SignUp;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import sincere.kimjungchul.smartwheel.DB.DB_Manger;
import sincere.kimjungchul.smartwheel.Login.LoginActivity;
import sincere.kimjungchul.smartwheel.R;
/**
* Created by user on 2016-01-20.
* Make by Kim Jung Chul
*/
public class SignUpPhotoActivity extends Activity implements View.OnClickListener {
private static final int PICK_FROM_CAMERA = 0;
private static final int PICK_FROM_ALBUM = 1;
private static final int CROP_FROM_iMAGE = 2;
private Uri mImageCaptureUri;
private ImageView iv_UserPhoto;
private int id_view;
private String absoultePath;
private DB_Manger dbmanger;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_signup_photo);
dbmanger = new DB_Manger();
iv_UserPhoto = (ImageView) this.findViewById(R.id.user_image);
Button btn_agreeJoin = (Button) this.findViewById(R.id.btn_UploadPicture);
btn_agreeJoin.setOnClickListener(this);
}
/**
* 카메라에서 사진 촬영
*/
public void doTakePhotoAction() // 카메라 촬영 후 이미지 가져오기
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 임시로 사용할 파일의 경로를 생성
String url = "tmp_" + String.valueOf(System.currentTimeMillis()) + ".jpg";
mImageCaptureUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), url));
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
startActivityForResult(intent, PICK_FROM_CAMERA);
}
/**
* 앨범에서 이미지 가져오기
*/
public void doTakeAlbumAction() // 앨범에서 이미지 가져오기
{
// 앨범 호출
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
startActivityForResult(intent, PICK_FROM_ALBUM);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode,resultCode,data);
if(resultCode != RESULT_OK)
return;
switch(requestCode)
{
case PICK_FROM_ALBUM:
{
// 이후의 처리가 카메라와 같으므로 일단 break없이 진행합니다.
// 실제 코드에서는 좀더 합리적인 방법을 선택하시기 바랍니다.
mImageCaptureUri = data.getData();
Log.d("SmartWheel",mImageCaptureUri.getPath().toString());
}
case PICK_FROM_CAMERA:
{
// 이미지를 가져온 이후의 리사이즈할 이미지 크기를 결정합니다.
// 이후에 이미지 크롭 어플리케이션을 호출하게 됩니다.
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(mImageCaptureUri, "image/*");
// CROP할 이미지를 200*200 크기로 저장
intent.putExtra("outputX", 200); // CROP한 이미지의 x축 크기
intent.putExtra("outputY", 200); // CROP한 이미지의 y축 크기
intent.putExtra("aspectX", 1); // CROP 박스의 X축 비율
intent.putExtra("aspectY", 1); // CROP 박스의 Y축 비율
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
startActivityForResult(intent, CROP_FROM_iMAGE); // CROP_FROM_CAMERA case문 이동
break;
}
case CROP_FROM_iMAGE:
{
// 크롭이 된 이후의 이미지를 넘겨 받습니다.
// 이미지뷰에 이미지를 보여준다거나 부가적인 작업 이후에
// 임시 파일을 삭제합니다.
if(resultCode != RESULT_OK) {
return;
}
final Bundle extras = data.getExtras();
// CROP된 이미지를 저장하기 위한 FILE 경로
String filePath = Environment.getExternalStorageDirectory().getAbsolutePath()+
"/SmartWheel/"+System.currentTimeMillis()+".jpg";
if(extras != null)
{
Bitmap photo = extras.getParcelable("data"); // CROP된 BITMAP
iv_UserPhoto.setImageBitmap(photo); // 레이아웃의 이미지칸에 CROP된 BITMAP을 보여줌
storeCropImage(photo, filePath); // CROP된 이미지를 외부저장소, 앨범에 저장한다.
absoultePath = filePath;
break;
}
// 임시 파일 삭제
File f = new File(mImageCaptureUri.getPath());
if(f.exists())
{
f.delete();
}
}
}
}
@Override
public void onClick(View v) {
id_view = v.getId();
if(v.getId() == R.id.btn_signupfinish) {
/** SharedPreference 환경 변수 사용 **/
SharedPreferences prefs = getSharedPreferences("login", 0);
/** prefs.getString() return값이 null이라면 2번째 함수를 대입한다. **/
String login = prefs.getString("USER_LOGIN", "LOGOUT");
String facebook_login = prefs.getString("FACEBOOK_LOGIN", "LOGOUT");
String user_id = prefs.getString("USER_ID","");
String user_name = prefs.getString("USER_NAME", "");
String user_password = prefs.getString("USER_PASSWORD", "");
String user_phone = prefs.getString("USER_PHONE", "");
String user_email = prefs.getString("USER_EMAIL", "");
dbmanger.select(user_id,user_name,user_password, user_phone, user_email);
dbmanger.selectPhoto(user_name, mImageCaptureUri, absoultePath);
Intent mainIntent = new Intent(SignUpPhotoActivity.this, LoginActivity.class);
SignUpPhotoActivity.this.startActivity(mainIntent);
SignUpPhotoActivity.this.finish();
Toast.makeText(this, "회원가입이 완료되었습니다.", Toast.LENGTH_SHORT).show();
}else if(v.getId() == R.id.btn_UploadPicture) {
DialogInterface.OnClickListener cameraListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
doTakePhotoAction();
}
};
DialogInterface.OnClickListener albumListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
doTakeAlbumAction();
}
};
DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
};
new AlertDialog.Builder(this)
.setTitle("업로드할 이미지 선택")
.setPositiveButton("사진촬영", cameraListener)
.setNeutralButton("앨범선택", albumListener)
.setNegativeButton("취소", cancelListener)
.show();
}
}
/*
* Bitmap을 저장하는 부분
*/
private void storeCropImage(Bitmap bitmap, String filePath) {
// SmartWheel 폴더를 생성하여 이미지를 저장하는 방식이다.
String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/SmartWheel";
File directory_SmartWheel = new File(dirPath);
if(!directory_SmartWheel.exists()) // SmartWheel 디렉터리에 폴더가 없다면 (새로 이미지를 저장할 경우에 속한다.)
directory_SmartWheel.mkdir();
File copyFile = new File(filePath);
BufferedOutputStream out = null;
try {
copyFile.createNewFile();
out = new BufferedOutputStream(new FileOutputStream(copyFile));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
// sendBroadcast를 통해 Crop된 사진을 앨범에 보이도록 갱신한다.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(copyFile)));
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
'Android' 카테고리의 다른 글
Google Map Fragment 만들기 (5) | 2016.02.12 |
---|---|
GOOGLE MAP API 빌드 오류에 대한 해결법 (1) | 2016.02.12 |
Google Map API App 및 Activity 생성 (23) | 2016.01.26 |
Google Maps API Andriod (0) | 2016.01.26 |
안드로이드란 무엇인가? (0) | 2015.01.27 |