반응형
다중이미지 미리보기를 구현해봤습니다.
카메라, 갤러리 권한을 ted permission을 사용하여 허용시켜줍니다.
build gradle
implementation "gun0912.ted:tedpermission:2.1.0"
Image_activity.class
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_mypage_fields_add);
ted();
}
void ted() {
//파일 읽기 권한
PermissionListener permissionListener = new PermissionListener() {
@Override
public void onPermissionGranted() {
//권한 요청 성공
//갤러리 동영상 호출
Intent vod_intent = new Intent(Intent.ACTION_PICK);
//ACTION_GET_CONTENT을 하게되면, 갤러리뿐 아니라 다른 저장공간에도 접근한다.
vod_intent.setType(MediaStore.Video.Media.CONTENT_TYPE);
}
@Override
public void onPermissionDenied(ArrayList<String> deniedPermissions) {
// 권한 요청 실패
Log.d(TAG, "onPermissionDenied: ");
}
};
TedPermission.with(this)
.setPermissionListener(permissionListener)
.setRationaleMessage("설정에서 권한을 허용해주세요.")
.setDeniedMessage("접근 권한이 필요합니다.")
.setPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA})
.check();
}
먼저 카메라 혹은 갤러리로 이동할 수 있는 버튼과 미리보기 layout을 xml에 정의해줍니다.
activity_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="vertical">
<ImageButton
android:id="@+id/addImageButton"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="15dp"
android:backgroundTint="@color/white"
app:srcCompat="@drawable/ic_image__9_" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="15dp"
android:orientation="vertical" />
</ScrollView>
</LinearLayout>
</LinearLayout>
카메라, 갤러리로 이동할 버튼의 뷰 매칭 및 갤러리 화면에서 받을 result 분기점을 정의합니다.
Image_Activity.java
//카메라, 혹은 갤러리로 이동할 버튼
ImageButton addImageButton;
//앨범에서 가져온 파일들 (다중선택 가능)
private static final int PICK_FROM_ALBUM = 1;
//카메라 캡처로 가져온 사진
public static final int REQUEST_IMAGE_CAPTURE = 3;
//카메라 혹은 앨범으로 이동할 dialog 정의
public ProgressDialog pDialog;
//미리보기 이미지를 담을 layout
private LinearLayout layout;
//파일의 실제 경로를 담을 arraylist
private ArrayList<String> filePaths = new ArrayList<String>();
버튼과 view를 연결해줍니다.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_mypage_fields_add);
ted();
//미리보기 이미지를 담을 뷰
layout = findViewById(R.id.layout);
//미리보기 이미지 추가할 버튼
addImageButton = findViewById(R.id.addImageButton);
}
코드 가독성을 위해 카메라나 갤러리로 이동하는 메소드를 따로 빼줍니다.
//이미지 관련 작업내용들
addImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
photoDialogList();
}
});
앨범선택과 사진촬영 중 원하는 부분을 선택하도록 Alertdialog를 생성해줍니다.
//사진 선택 다이얼로그
void photoDialogList() {
final List<String> ListItems = new ArrayList<>();
ListItems.add("앨범 선택");
ListItems.add("사진 촬영");
final CharSequence[] items = ListItems.toArray(new String[ListItems.size()]);
//alertdialog 객체 생성
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int pos) {
String selectedText = items[pos].toString();
if (selectedText.contains("앨범 선택")) {
goToAlbum();
} else {
takephoto();
}
}
});
builder.show();
}
goToAlbum()
//앨범으로
private void goToAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(MediaStore.Images.Media.CONTENT_TYPE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
//갤러리의 이미지만 확인하겠다.
intent.setType("image/*");
//결과값은 PICK_FROM_ALBUM 에서 받겠다.
startActivityForResult(intent, PICK_FROM_ALBUM);
}
takephoto()
//카메라로 이동
public void takephoto() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
//임시파일 생성
File tempDir = getCacheDir();
String timeStamp = new SimpleDateFormat("yyyyMMdd", Locale.KOREA).format(new Date());
String imageFileName = "Capture_" + timeStamp + "_";
File tempImage = File.createTempFile(
imageFileName,
".jpg",
tempDir
);
//임시파일의 절대경로
mCurrentPhotoPath = tempImage.getAbsolutePath();
photoFile = tempImage;
} catch (Exception e) {
Log.w(TAG, "파일 생성 에러!", e);
}
Log.e(TAG, photoFile + "포토파일");
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
getPackageName() + ".fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
//결과값을 REQUEST_IMAGE_CAPTURE 에서 받겠다.
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
앨범이나, 카메라 이동 후 가져온 이미지들 처리할 onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode) {
//카메라
case REQUEST_IMAGE_CAPTURE:
if (resultCode == RESULT_OK) {
//받아온 사진의 경로를 파일로 생성한다.
File file = new File(mCurrentPhotoPath);
//file의 uri 경로를 가져온다.
Uri imageUri = Uri.fromFile(file);
//미리보기에 삽입
makeImageView(imageUri);
}
break;
//앨범
case PICK_FROM_ALBUM:
if (resultCode == RESULT_OK) {
//가져온 다수의 사진을 이미지 미리보기에 넣는다.
ClipData clipData = intent.getClipData();
if (clipData != null) {
for (int i = 0; i < clipData.getItemCount(); i++) {
if (i < clipData.getItemCount()) {
Uri imageUri = clipData.getItemAt(i).getUri();
makeImageView(imageUri);
}
}
}
}
break;
}
}
makeImageView() --> 이미지 미리보기 생성
private void makeImageView(Uri uri) {
//이미지 삭제 버튼을 넣어주기 위한 프레임 레이아웃인데 이미지를 프레임에 넣고, 삭제 버튼이미지도 프레임에 넣어준다
FrameLayout frameLayout = new FrameLayout(this);
//삭제버튼 이미지
ImageView deleteView = new ImageView(this);
ImageView imageView = new ImageView(this);
//파일의 절대 경로를 알아온다
String absolutePath = getRealPathFromURI(getApplicationContext(), uri);
filePaths.add(absolutePath);
if (frameLayout != null) {
frameLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
layout.removeView(frameLayout);
//위에서 만들 file을 사용하여 데이터를 지워준다.
System.out.println("지워지는 데이터 : " + uri);
System.out.println("리스트의 데이터 : " + filePaths);
//리스트에서도 같이 지워준다.
filePaths.remove(absolutePath);
}
});
}
//딜리트이미지 세팅
deleteView.setImageResource(R.drawable.remove);
//삭제 이미지뷰의 크기 조절
LinearLayout.LayoutParams deleteImgParams = new LinearLayout.LayoutParams(60, 60);
//삭제 이미지뷰의 위치 조절
deleteImgParams.setMargins(940, 0, 0, 0);
deleteView.setLayoutParams(deleteImgParams);
System.out.println("이건 이미지!");
//글라이드로 이미지 크기 조정
Glide.with(imageView)
.load(uri)
.override(MATCH_PARENT, MATCH_PARENT)
.into(imageView);
//이미지뷰의 크기 조절
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(1000, 500);
params.topMargin = 15;
params.leftMargin = 15;
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
frameLayout.setLayoutParams(params);
frameLayout.addView(imageView);
frameLayout.addView(deleteView);
layout.addView(frameLayout);
System.out.println("현재 이미지 리스트의 데이터들 : " + filePaths);
}
혹시라도 본인의 서버에 업로드하기위해 이미지의 uri 경로 말고 절대경로가 필요할 수 있으니 절대경로를 구하는 메소드도 함께 업로드하겠습니다.
//파일의 절대경로를 알아오는 메서드
public static String getRealPathFromURI(final Context context, final Uri uri) {
// DocumentProvider
if (DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/"
+ split[1];
} else {
String SDcardpath = getRemovableSDCardPath(context).split("/Android")[0];
return SDcardpath + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else {
Toast.makeText(context.getApplicationContext(), "이미지가 아닙니다.", Toast.LENGTH_SHORT).show();
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{split[1]};
return getDataColumn(context, contentUri, selection,
selectionArgs);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri,
String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
public static String getRemovableSDCardPath(Context context) {
File[] storages = ContextCompat.getExternalFilesDirs(context, null);
if (storages.length > 1 && storages[0] != null && storages[1] != null)
return storages[1].toString();
else
return "";
}
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri
.getAuthority());
}
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri
.getAuthority());
}
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri
.getAuthority());
}
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri
.getAuthority());
}
궁금한점이나 안되는 부분은 댓글 달아주세요.
반응형
'Android' 카테고리의 다른 글
Android/Kotlin - 내부저장 Shared Preferences vs Data Store vs Room (0) | 2022.08.09 |
---|---|
Protocol Buffer - 프로토콜 버퍼 (0) | 2022.08.09 |
[Java] 하나의 RecyclerView에 서로 다른 뷰 넣기 ( TCP 채팅 예제 - 카카오톡 채팅화면) (0) | 2022.01.12 |
댓글