Android memilih gambar dari galeri


197

Saya ingin membuat pemilih gambar dari galeri. Saya menggunakan kode

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

Masalah saya adalah bahwa dalam aktivitas ini dan file video ditampilkan. Apakah ada cara untuk memfilter file yang ditampilkan sehingga tidak ada file video yang akan ditampilkan dalam kegiatan ini?


3
Artikel ini dengan baik menjelaskan cara memilih gambar dari galeri: androidbitmaps.blogspot.com/2015/04/...
Andy Res

Ada satu pertanyaan serupa seperti Anda. stackoverflow.com/a/31382240/1835650
TeeTracker

Jawaban:


346

Benar. Coba ini:

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

Jangan lupa juga untuk membuat PICK_IMAGE konstan , sehingga Anda dapat mengenali kapan pengguna kembali dari Galeri gambar Activity:

public static final int PICK_IMAGE = 1;

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

Begitulah cara saya memanggil galeri gambar. Masukkan dan lihat apakah itu cocok untuk Anda.

EDIT:

Ini memunculkan aplikasi Documents. Untuk memungkinkan pengguna juga menggunakan aplikasi galeri yang mungkin telah mereka instal:

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

6
Saya mendapatkan 2 opsi pada "Sistem Android" ini, "Dokumen". Jika saya memilih Sistem Android, maka itu memberi saya Galeri dan Foto. Bagaimana cara saya menyingkirkan daftar opsi perantara ini?
Uday

4
@Uday itu hanya karena Anda belum menetapkan default. Biarkan saja :)
Tristan Wiley

13
Apa yang harus diset oleh konstanta PICK_IMAGE? Itu mengatakan "Tidak dapat menyelesaikan simbol" PICK_IMAGE "
Michael

3
@ Michael yang PICK_IMAGE konstan memegang setiap static int nilai yang ditentukan oleh Anda di kelas ini sangat, ini lebih lanjut digunakan pada @Overridefungsi onActivityResult(int requestCode, resultCode, Intent data), di mana itu disarankan agar Anda menggunakan konstan ini untuk memeriksa requestCodeparameter sebelum melakukan tindakan apapun :)
Gabriel Checchia Vitali

Anda dapat mengambil Bitmap dari metode onActivityResult (...) dengan kode berikut (dengan asumsi RESULT_OK): Bitmap bitmap = data.getExtras (). GetParcelable ("data");
Shn_Android_Dev

197

Terkadang, Anda tidak bisa mendapatkan file dari gambar yang Anda pilih. Itu karena yang dipilih berasal dari Google+, Drive, Dropbox, atau penyedia lainnya.

Solusi terbaik adalah meminta sistem untuk memilih konten melalui Intent.ACTION_GET_CONTENT dan dapatkan hasilnya dengan penyedia konten.

Anda dapat mengikuti kode di bawah atau melihat intisari saya yang diperbarui .

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

14
if(resultCode == Activity.RESULT_OK) {...}dapat digunakan untuk mendeteksi keberhasilan / pembatalan
Thamme Gowda

Bagaimana Anda bisa mendapatkan jalan?
delive

@delive, saya pikir Anda bisa mencoba. new File(data.getData()).getAbsolutePath()Tebakan saja, saya belum mencobanya
Seseorang di suatu tempat

1
Peringatan pengecualian FileNotFound oleh Android Studio dalam fragmen dalam getActivity().getContentResolver().openInputStream(data.getData());.
Iqbal

1
Ini berfungsi pada perangkat tertentu di mana jalur file tidak dikembalikan. Namun, saya tidak melihat cara untuk menentukan - setelah saya memiliki InputStream - bagaimana cara mengetahui orientasi gambar.
Casey Perkins

30
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);


}

Terima kasih banyak. Jawaban ini membantu saya mengunggah gambar nanti
Rosário Pereira Fernandes

Saya kira maksud Anda kasus 1: bukannya kasus -1: di saklar di OnActivityResult.
Mathias

saya tahu ini adalah pertanyaan newibe tetapi, mengapa kita melakukan semua ini untuk mendapatkan jalur gambar, lalu apa data.getData kembali?
moumenShobakey

apa nilainya path? diFile file = new File(path);
Ravi Vaniya

23

Anda dapat menggunakan metode ini untuk memilih gambar dari galeri. Hanya gambar yang akan ditampilkan.

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

dan timpa onActivityResult sebagai

    @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");
            }
        }
    }

2
@Abhishek ... di mana Anda menemukan daftar ekstra yang diizinkan untuk maksud ACTION_PICK? Terima kasih!
Johnny Wu

1
Harap jangan lupa untuk menambahkan izin runtime untuk READ_EXTERNAL_STORAGE dan WRITE_EXTERNAL_STORAGE untuk api level 23 dan lebih tinggi. Kalau tidak, Anda tidak akan mendapatkan bitmap dari galeri sebagai bukan nol. Lihat stackoverflow.com/a/35285667/3341089
oguzhan

1
Memanggil setType setelah pengaturan URI akan menghapus data.
Taslim Oseni

11

Ini adalah contoh lengkap untuk izin permintaan (jika perlu), pilih gambar dari galeri, lalu konversikan gambar ke bitmapataufile

AndroidManifesh.xml

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

Aktivitas

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

Demo
https://github.com/PhanVanLinh/AndroidPickImage


Ini tidak kurang dari perpustakaan, terutama dengan fitur rasio aspek dan pemotongan. Saya tidak pernah tahu hal seperti itu ada. Terima kasih banyak Pak.
Lalit Fauzdar

1
Kembali ke sini, itu tidak begitu baik seperti yang saya harapkan melihat kesan pertama. Itu tidak memilih gambar ketika diedit dengan snapseed, tidak ada crash tapi tidak ada gambar, aplikasi galeri default huawei tidak melakukan apa-apa ketika saya mengklik berikutnya setelah mengedit, itu tidak mengedit gambar ketika diambil dari foto google, membawanya kembali tanpanya secara langsung. Ini berfungsi baik hanya jika saya memilih galeri default huawei dan foto google untuk mengeditnya.
Lalit Fauzdar


2

Hanya untuk menawarkan pembaruan pada jawaban untuk orang-orang dengan API min 19, per dokumen:

Pada Android 4.4 (API level 19) dan lebih tinggi, Anda memiliki opsi tambahan untuk menggunakan maksud ACTION_OPEN_DOCUMENT, yang menampilkan pemilih UI yang dikontrol sistem yang dikendalikan yang memungkinkan pengguna untuk menelusuri semua file yang disediakan aplikasi lain. Dari UI tunggal ini, pengguna dapat memilih file dari salah satu aplikasi yang didukung.

Pada Android 5.0 (API level 21) dan lebih tinggi, Anda juga dapat menggunakan maksud ACTION_OPEN_DOCUMENT_TREE, yang memungkinkan pengguna untuk memilih direktori untuk diakses oleh aplikasi klien.

Buka file menggunakan kerangka kerja akses penyimpanan - Android Docs

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

0

Untuk hanya memilih dari lokal, tambahkan ini:

        i.putExtra(Intent.EXTRA_LOCAL_ONLY,true)

Dan ini berfungsi dengan baik:

    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)

-7

Anda dapat melakukannya dengan lebih mudah daripada jawaban ini:

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

saya melakukannya, dan itu berhasil. jika Anda perlu menggunakan file misalnya untuk mengirim ke server Anda harus menggunakan cara lain tetapi hanya untuk memuat gambar ke imageview Anda dapat melakukan solusi mudah ini.
Alireza Taghizadeh

5
Selamat datang di SO! Alih-alih mengomentari kiriman Anda sendiri, Anda juga dapat mengedit kiriman Anda. Jika komentar Anda seharusnya menjelaskan jawabannya, lalu mengapa tidak memasukkannya ke dalam jawaban itu sendiri? Secara pribadi, saya tidak melihat bagaimana jawaban Anda (terlambat) untuk pertanyaan lama ini terkait dengan pertanyaan itu. Bolehkah saya menyarankan untuk fokus menjawab pertanyaan pertama, yang belum menerima jawaban?
cfi

1
saya tidak dapat menemukan pertanyaan android. bagaimana saya bisa melihat hanya pertanyaan android?
Alireza Taghizadeh

3
Silakan baca halaman bantuan. Juga, komentar bukan untuk diskusi tentang bagaimana situs ini bekerja, Anda dapat menggunakan ruang obrolan untuk diskusi langsung dengan pengguna lain, dan Anda dapat mengajukan pertanyaan spesifik tentang Meta (help-> Meta)
cfi
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.