programing

갤러리에서 안드로이드 이미지 선택

starjava 2023. 10. 14. 09:27
반응형

갤러리에서 안드로이드 이미지 선택

갤러리에서 그림 선택자를 만들고 싶습니다.코드를 사용합니다.

 intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
 startActivityForResult(intent, TFRequestCodes.GALLERY);

제 문제는 이 활동과 동영상 파일이 표시된다는 것입니다.이 활동에서 비디오 파일이 표시되지 않도록 표시된 파일을 필터링할 수 있는 방법이 있습니까?

그렇고 말고요.시도해 보기:

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);

상수 PIK 생성도 잊지 마세요_IMAGE(이미지): 사용자가 이미지 갤러리에서 언제 돌아오는지 알 수 있습니다. 액티비티:

public static final int PICK_IMAGE = 1;

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == PICK_IMAGE) {
        //TODO: action
    }
}

저는 이미지 갤러리를 그렇게 부릅니다.그것을 넣고 그것이 당신에게 적합한지 알아보세요.

편집:

그러면 Documents 앱이 나타납니다.사용자가 설치했을지도 모르는 갤러리 앱을 사용할 수 있도록 하려면:

    Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
    getIntent.setType("image/*");

    Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    pickIntent.setType("image/*");

    Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});

    startActivityForResult(chooserIntent, PICK_IMAGE);

선택한 사진에서 파일을 얻을 수 없는 경우가 있습니다.왜냐하면 선택한 것은 Google+, Drive, Dropbox 또는 다른 공급업체에서 왔기 때문입니다.

가장 좋은 해결책은 인텐트(Intent)를 통해 시스템에 컨텐츠를 선택하도록 요청하는 것입니다.ACTION_GET_CONTERNATION을 수행하고 컨텐츠 공급자와 함께 결과를 가져옵니다.

당신은 아래의 코드를 따르거나 나의 업데이트된 요점을 볼 수 있습니다.

public void pickImage() {
  Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
  intent.setType("image/*");
  startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) {
        if (data == null) {
            //Display an error
            return;
        }
        InputStream inputStream = context.getContentResolver().openInputStream(data.getData());
        //Now you can do whatever you want with your inpustream, save it as file, upload to a server, decode a bitmap...
    }
}
public void FromCamera() {

    Log.i("camera", "startCameraActivity()");
    File file = new File(path);
    Uri outputFileUri = Uri.fromFile(file);
    Intent intent = new Intent(
            android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(intent, 1);

}

public void FromCard() {
    Intent i = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i, 2);
}

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 2 && resultCode == RESULT_OK
            && null != data) {

        Uri selectedImage = data.getData();
        String[] filePathColumn = { MediaStore.Images.Media.DATA };

        Cursor cursor = getContentResolver().query(selectedImage,
                filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();

        bitmap = BitmapFactory.decodeFile(picturePath);
        image.setImageBitmap(bitmap);

        if (bitmap != null) {
            ImageView rotate = (ImageView) findViewById(R.id.rotate);

        }

    } else {

        Log.i("SonaSys", "resultCode: " + resultCode);
        switch (resultCode) {
        case 0:
            Log.i("SonaSys", "User cancelled");
            break;
        case -1:
            onPhotoTaken();
            break;

        }

    }

}

protected void onPhotoTaken() {
    // Log message
    Log.i("SonaSys", "onPhotoTaken");
    taken = true;
    imgCapFlag = true;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    bitmap = BitmapFactory.decodeFile(path, options);
    image.setImageBitmap(bitmap);


}

이 방법을 사용하여 갤러리에서 이미지를 선택할 수 있습니다.영상만 표시됩니다.

public void pickImage() {
    Intent intent = new Intent(Intent.ACTION_PICK,
            MediaStore.Images.Media.INTERNAL_CONTENT_URI);
    intent.setType("image/*");
    intent.putExtra("crop", "true");
    intent.putExtra("scale", true);
    intent.putExtra("outputX", 256);
    intent.putExtra("outputY", 256);
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    intent.putExtra("return-data", true);
    startActivityForResult(intent, 1);
}

ActivityResults를 덮어씁니다.

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }
        if (requestCode == 1) {
            final Bundle extras = data.getExtras();
            if (extras != null) {
                //Get image
                Bitmap newProfilePic = extras.getParcelable("data");
            }
        }
    }

은 요청 에 를 () 에입니다로 합니다. 갤러리에서 이미지를 선택한 다음 이미지를 다음으로 변환합니다.bitmap아니면file

AndroidManifesh.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

활동

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button_pick_image.setOnClickListener {
            pickImage()
        }
    }

    private fun pickImage() {
        if (ActivityCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            val intent = Intent(
                Intent.ACTION_PICK,
                MediaStore.Images.Media.INTERNAL_CONTENT_URI
            )
            intent.type = "image/*"
            intent.putExtra("crop", "true")
            intent.putExtra("scale", true)
            intent.putExtra("aspectX", 16)
            intent.putExtra("aspectY", 9)
            startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE)
        } else {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                READ_EXTERNAL_STORAGE_REQUEST_CODE
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == PICK_IMAGE_REQUEST_CODE) {
            if (resultCode != Activity.RESULT_OK) {
                return
            }
            val uri = data?.data
            if (uri != null) {
                val imageFile = uriToImageFile(uri)
                // todo do something with file
            }
            if (uri != null) {
                val imageBitmap = uriToBitmap(uri)
                // todo do something with bitmap
            }
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            READ_EXTERNAL_STORAGE_REQUEST_CODE -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // pick image after request permission success
                    pickImage()
                }
            }
        }
    }

    private fun uriToImageFile(uri: Uri): File? {
        val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = contentResolver.query(uri, filePathColumn, null, null, null)
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                val filePath = cursor.getString(columnIndex)
                cursor.close()
                return File(filePath)
            }
            cursor.close()
        }
        return null
    }

    private fun uriToBitmap(uri: Uri): Bitmap {
        return MediaStore.Images.Media.getBitmap(this.contentResolver, uri)
    }

    companion object {
        const val PICK_IMAGE_REQUEST_CODE = 1000
        const val READ_EXTERNAL_STORAGE_REQUEST_CODE = 1001
    }
}


://

2021 새로운 버전의 프래그먼트를 포함한 Kotlin 솔루션:

dependencies {
  implementation "androidx.fragment:fragment:1.3.3"
}
class YourFragment : Fragment() {

    private val fileChooserContract = registerForActivityResult(ActivityResultContracts.GetContent()) { imageUri ->
        if (imageUri != null) {
            // imageUri now contains URI to selected image
        }
    }

    // ...

    fun openFileChooser() {
        fileChooserContract.launch("image/*")
    }
}

저도 같은 문제가 있습니다.이 코드를 사용합니다.

의도를 추가

 Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Tack Image"), PICK_PHOTO);

활동 결과에 추가

 @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_PHOTO && resultCode == Activity.RESULT_OK) {
      if (data == null) {
      //error
        return;
      }
      try {
        Uri uri = data.getData();
        File file = FileUtil.from(currentActivity, uri);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

파일유틸 클래스

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FileUtil {
  private static final int EOF = -1;
  private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

  private FileUtil() {

  }

  public static File from(Context context, Uri uri) throws IOException {
    InputStream inputStream = context.getContentResolver().openInputStream(uri);
    String fileName = getFileName(context, uri);
    String[] splitName = splitFileName(fileName);
    File tempFile = File.createTempFile(splitName[0], splitName[1]);
    tempFile = rename(tempFile, fileName);
    tempFile.deleteOnExit();
    FileOutputStream out = null;
    try {
      out = new FileOutputStream(tempFile);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    if (inputStream != null) {
      copy(inputStream, out);
      inputStream.close();
    }

    if (out != null) {
      out.close();
    }
    return tempFile;
  }

  private static String[] splitFileName(String fileName) {
    String name = fileName;
    String extension = "";
    int i = fileName.lastIndexOf(".");
    if (i != -1) {
      name = fileName.substring(0, i);
      extension = fileName.substring(i);
    }

    return new String[]{name, extension};
  }

  private static String getFileName(Context context, Uri uri) {
    String result = null;
    if (uri.getScheme().equals("content")) {
      Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
      try {
        if (cursor != null && cursor.moveToFirst()) {
          result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
        }
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        if (cursor != null) {
          cursor.close();
        }
      }
    }
    if (result == null) {
      result = uri.getPath();
      int cut = result.lastIndexOf(File.separator);
      if (cut != -1) {
        result = result.substring(cut + 1);
      }
    }
    return result;
  }

  private static File rename(File file, String newName) {
    File newFile = new File(file.getParent(), newName);
    if (!newFile.equals(file)) {
      if (newFile.exists() && newFile.delete()) {
        Log.d("FileUtil", "Delete old " + newName + " file");
      }
      if (file.renameTo(newFile)) {
        Log.d("FileUtil", "Rename file to " + newName);
      }
    }
    return newFile;
  }

  private static long copy(InputStream input, OutputStream output) throws IOException {
    long count = 0;
    int n;
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
    while (EOF != (n = input.read(buffer))) {
      output.write(buffer, 0, n);
      count += n;
    }
    return count;
  }
}

이미지와 같은 xml 폴더에 provider_paths.xml을 추가해야 합니다.

provider_paths.xml

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

AndroidManifest.xml에서 마지막으로 아래를 추가합니다.

<application
...>

...
      <provider
          android:name="androidx.core.content.FileProvider"
          android:authorities="${applicationId}.provider"
          android:exported="false"
          android:grantUriPermissions="true">
          <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
        </provider>
...
</application>

내가 도와주고 싶었다.

Goodbye start ActivityForResult()

요즘 AndroidX Activity의 적절한 방법은 Activity Result API이며 Google에서 강력하게 추천하는 방법입니다.

private val selectImageFromGalleryResult = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
    uri?.let { previewImage.setImageURI(uri) }
}

필요할 때 ImageFromGallery()를 선택하기만 하면 됩니다.

private fun selectImageFromGallery() = selectImageFromGalleryResult.launch("image/*")

startActivityForResult()가 축소되므로 ActivityResultLauncher를 사용하여 다음과 같은 방법으로 갤러리에서 이미지만 선택할 수 있습니다.

는 해야 합니다.ActivityResultLauncher<String[]>합니다.onCreate() 우용)onViewCreated()우)

ActivityResultLauncher<String[]> galleryActivityLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), new ActivityResultCallback<Uri>() {
    @Override
    public void onActivityResult(Uri result) {
        if (result != null) {
            // perform desired operations using the result Uri
        } else {
            Log.d(TAG, "onActivityResult: the result is null for some reason");
        }
    }
});

할 때 를 열어야 submitButton클릭됩니다.

에 에.onClickListener.

galleryActivityLauncher.launch(new String[]{"image/*"});

서의 비결은 입니다에 입니다.launch()해서."image/*"인수 배열에 파일 탐색기가 이미지만 로드하도록 지정합니다.

문서에 따라 API min 19를 사용하는 사람들에게 답변에 대한 업데이트를 제공합니다.

Android 4.4(API 레벨 19) 이상에서는 ACTION_OPEN_DOUCTION intent를 사용할 수 있는 추가 옵션이 있습니다. 이 옵션은 사용자가 다른 앱에서 사용 가능하게 만든 모든 파일을 검색할 수 있도록 시스템에서 제어하는 선택 UI를 표시합니다.이 단일 UI에서 사용자는 지원되는 모든 앱에서 파일을 선택할 수 있습니다.

Android 5.0(API 레벨 21) 이상에서는 ACTION_OPEN_DOCUTION_TREE intent를 사용할 수 있으며, 이를 통해 사용자는 클라이언트 앱이 액세스할 디렉토리를 선택할 수 있습니다.

스토리지 액세스 프레임워크를 사용하여 파일 열기 - Android Docs

     val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
     intent.type = "image/*"
     startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE)

OnActivityResult 메서드가 더 이상 사용되지 않습니다.

val singleImageResultLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    // There are no request codes
                    val data: Intent? = result.data
                    val selectedImageUri: Uri? = data?.data
                    if (null != selectedImageUri) {
                        // Get the path from the Uri
                        val path = getPathFromURI(selectedImageUri)
                        findViewById<TextView>(R.id.textView).text = path
                        findViewById<ImageView>(R.id.imageView2).setImageURI(selectedImageUri)
                    }
                }
            }
findViewById<Button>(R.id.oneImageSelectBtn).setOnClickListener {
            val intent = Intent()
            intent.type = "image/*"
            intent.action = Intent.ACTION_GET_CONTENT
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
            singleImageResultLauncher.launch(Intent.createChooser(intent, "Select Picture"))

        }
private fun getPathFromURI(uri: Uri?): String {
        var path = ""
        if (contentResolver != null) {
            val cursor = contentResolver.query(uri!!, null, null, null, null)
            if (cursor != null) {
                cursor.moveToFirst()
                val idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME)
                path = cursor.getString(idx)
                cursor.close()
            }
        }
        return path
}

영상과 다중 선택만 찾는 경우.

@once https://stackoverflow.com/a/15029515/1136023 보기

미래에 도움이 됩니다.저는 개인적으로 Multiple ImagePick을 사용해서 기분이 좋습니다.

mklkj 덕분에

활동 버전입니다.

fileChooserContract이미지를 선택할 수 있습니다.filesChooserContract여러 이미지를 선택할 수 있습니다.

class MainActivity : AppCompatActivity() {

    companion object {
        private const val TAG = "MainActivity"
    }

    lateinit var viewBinding: ActivityMainBinding

    private val fileChooserContract = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
        Log.d(TAG, "onActivityResult: uri $uri")
    }

    private val filesChooserContract = registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { uriList ->
        for (uri in uriList) {
            Log.d(TAG, "onActivityResult: uri $uri")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        viewBinding.btnPick.setOnClickListener {
            fileChooserContract.launch("image/*")
        }

        viewBinding.btnPickMulti.setOnClickListener {
            filesChooserContract.launch("image/*")
        }
    }
}

OPTION-1

아래 코드를 사용하면 파일 탐색기 응용 프로그램에서 이미지를 선택할 수 있습니다.

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_CODE);

그러나 일부 장치에서는 위 솔루션이 방향과 같은 EXIF 정보로 이미지를 가져오지 않습니다.따라서 해당 장치에서는 이미지 방향 변경과 같은 EXIF 처리를 예상대로 수행할 수 없었습니다.

OPTION-2

아래 코드를 사용하면 갤러리 애플리케이션에서 이미지를 선택할 수 있습니다.

Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult ( intent, PICK_IMAGE_CODE );

하면서 위 에서를 들어, 입니다, 하면서))를 MediaStore.Images.Media.EXTERNAL_CONTENT_URI갤러리 오픈 과정에 방해가 될 수 있습니다.

OPTION-3

마지막으로, 저는 사용자가 어떠한 문제를 일으키지 않고 어떠한 경고도 표시되지 않는 갤러리 어플리케이션에서 이미지를 선택할 수 있는 아래의 코드를 제안합니다.

Intent intent = new Intent ();
intent.setAction ( Intent.ACTION_PICK );
intent.setDataAndType ( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*" );
startActivityForResult ( intent, PICK_IMAGE_CODE );

다음은 코틀린의 작업 코드 util 방법입니다.

fun launchGalleryWithFragment() {
        val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
        intent.type = "image/*"
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1001)
    }

이제 ActivityResult 메서드를 재정의합니다.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
var path: Uri? = null
        if (requestCode == PICK_IMAGE_REQUEST && resultCode == Activity.RESULT_OK) {
            if(dataIntent == null || dataIntent.data == null){
                return null
            }
            path = dataIntent.data
        }

}

로컬에서 선택한 경우에만 다음을 추가합니다.

        i.putExtra(Intent.EXTRA_LOCAL_ONLY,true)

그리고 잘 작동하는군요

    val i = Intent(Intent.ACTION_GET_CONTENT,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
    i.type = "image/*"
    i.putExtra(Intent.EXTRA_LOCAL_ONLY,true)
    startActivityForResult(Intent.createChooser(i,"Select Photo"),pickImageRequestCode)

KotlinKotlin열기ACTION_GET_CONTENT사용자에게 메시지를 표시할 경우:

val intent = Intent(Intent.ACTION_GET_CONTENT).apply { type = "image/*" }
startActivityForResult(intent, 9998)

합니다.onActivityResult사용자 활동의 기능입니다.를 들어.ImageView앱 캐시에 저장합니다.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == 9998) {
        val uri: Uri = data?.data ?: return
        val bytes = contentResolver.openInputStream(uri)?.readBytes() ?: return
        imageView.setImageBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.size))
        File("$cacheDir/imgPicked").writeBytes(bytes)  // if needed: store to cache
    }
}

이상적으로 교체합니다.9998일부 내부 요청 코드와 함께 당신의 앱이 사용하는 것을 열거합니다.이는 단지 콜백을 자신의 요청과 구별할 수 있도록 하기 위함입니다.

와는 달리getParcelable("data")사용 권한이 필요 없습니다.

이것은 Exif 회전 비트를 설정한 영상에서 처리하지 않으므로 일부 영상은 방향이 틀리게 됩니다(Kotlin 솔루션).

새 제품을 사용하는 Kotlin의 경우ActivityResultContracts부터startActivityForResult은(는) 설명되어 있습니다.

private val mSelectedPicDataResult = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        val selectedPicUri = result.data?.data
        //use your selected pic
    }
}

private fun startSelectPic() {
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
    intent.addCategory(Intent.CATEGORY_OPENABLE)
    intent.type = "image/*"
    mSelectedPicDataResult.launch(intent)
}

다음 답변보다 쉽게 수행할 수 있습니다.

Uri Selected_Image_Uri = data.getData();
ImageView imageView = (ImageView) findViewById(R.id.loadedimg);
imageView.setImageURI(Selected_Image_Uri);

언급URL : https://stackoverflow.com/questions/5309190/android-pick-images-from-gallery

반응형