Android เลือกภาพจากแกลเลอรี่


197

ฉันต้องการสร้างตัวเลือกรูปภาพจากแกลเลอรี่ ฉันใช้รหัส

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

ปัญหาของฉันคือว่าในกิจกรรมนี้และไฟล์วิดีโอจะปรากฏขึ้น มีวิธีกรองไฟล์ที่แสดงเพื่อไม่ให้ไฟล์วิดีโอแสดงในกิจกรรมนี้หรือไม่?


3
บทความนี้อธิบายวิธีการเลือกภาพจากแกลเลอรี่เป็นอย่างดี: androidbitmaps.blogspot.com/2015/04/…
Andy Res

มีคำถามเดียวที่คล้ายกันกับคุณ stackoverflow.com/a/31382240/1835650
TeeTracker

คำตอบ:


347

อย่างแน่นอน ลองสิ่งนี้:

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

อย่าลืมสร้างPICK_IMAGEให้คงที่เพื่อให้คุณสามารถจดจำได้เมื่อผู้ใช้กลับมาจากแกลเลอรี่รูปภาพกิจกรรม:

public static final int PICK_IMAGE = 1;

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

นั่นคือวิธีที่ฉันเรียกว่าแกลเลอรี่ภาพ ใส่ไว้ในและดูว่าเหมาะกับคุณหรือไม่

แก้ไข:

นี่จะเป็นการเปิดแอปเอกสารขึ้นมา เพื่อให้ผู้ใช้สามารถใช้แอพแกลเลอรีที่พวกเขาอาจติดตั้ง:

    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
ฉันได้รับ 2 ตัวเลือกใน "ระบบ Android" นี้ "เอกสาร" ถ้าฉันเลือกระบบ Android แสดงว่าฉันมีคลังภาพและรูปถ่าย ฉันจะกำจัดรายการตัวเลือกขั้นกลางนี้ได้อย่างไร
Uday

4
@ ทุกวันเป็นเพียงเพราะคุณไม่ได้ตั้งค่าเริ่มต้น เพียงแค่ทิ้ง :)
Tristan Wiley

13
ค่าคงที่ PICK_IMAGE ต้องตั้งค่าเป็นอะไร มีข้อความระบุว่า "ไม่สามารถแก้ไขสัญลักษณ์" PICK_IMAGE "
Michael

3
@Michael PICK_IMAGEคงถือใด ๆint คงคุ้มค่าที่กำหนดโดยคุณในระดับนี้มากนี้จะใช้เพิ่มเติมเกี่ยวกับ@Overrideฟังก์ชั่นonActivityResult(int requestCode, resultCode, Intent data)ที่ก็ขอแนะนำให้คุณใช้อย่างต่อเนื่องนี้เพื่อตรวจสอบrequestCodeพารามิเตอร์ก่อนที่จะทำดำเนินการใด ๆ :)
Gabcvit

คุณสามารถดึงข้อมูลบิตแมปจากวิธี onActivityResult (... ) ด้วยโค้ดต่อไปนี้ (สมมติว่า RESULT_OK): บิตแมปบิตแมป = data.getExtras (). getParcelable ("data");
Shn_Android_Dev

197

บางครั้งคุณไม่สามารถรับไฟล์จากภาพที่คุณเลือก เป็นเพราะคนที่เลือกมาจาก Google+, Drive, Dropbox หรือผู้ให้บริการอื่น ๆ

ทางออกที่ดีที่สุดคือขอให้ระบบเลือกเนื้อหาผ่านIntent.ACTION_GET_CONTENTและรับผลลัพธ์กับผู้ให้บริการเนื้อหา

คุณสามารถปฏิบัติตามตะโกนรหัสหรือดูที่ฉันสรุปสาระสำคัญการปรับปรุง

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) {...}สามารถใช้เพื่อตรวจจับความสำเร็จ / ยกเลิก
Thamme Gowda

คุณจะหาเส้นทางได้อย่างไร
delive

@delive ฉันคิดว่าคุณสามารถลองnew File(data.getData()).getAbsolutePath()เดาฉันไม่ได้ลอง
บางคนที่

1
คำเตือนข้อยกเว้น FileNotFound โดย Android Studio เป็นส่วนgetActivity().getContentResolver().openInputStream(data.getData());
อิกบัล

1
ใช้งานได้กับอุปกรณ์บางอย่างที่ไม่ได้คืนพา ธ ของไฟล์ อย่างไรก็ตามฉันไม่เห็นวิธีการกำหนด - เมื่อฉันมี InputStream - วิธีการหาทิศทางของภาพ
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);


}

ขอบคุณมาก. คำตอบนี้ช่วยให้ฉันอัปโหลดภาพในภายหลัง
Rosário Pereira Fernandes

ฉันเดาว่าคุณหมายถึงกรณีที่ 1: แทนที่จะเป็นกรณีที่ -1: ในสวิตช์ใน OnActivityResult
งัด

ฉันรู้ว่ามันเป็นคำถามที่แปลกใหม่ แต่ทำไมเราทำทั้งหมดนี้เพื่อให้ได้เส้นทางของรูปภาพ data.getData จะกลับมาได้อย่างไร
moumenShobakey

คุณค่าของpathคืออะไร? ในFile file = new File(path);
Ravi Vaniya

24

คุณสามารถใช้วิธีนี้เพื่อเลือกภาพจากแกลเลอรี่ จะแสดงเฉพาะภาพ

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

และแทนที่ onActivityResult เป็น

    @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 ... คุณพบรายการพิเศษที่อนุญาตสำหรับเจตนา ACTION_PICK ที่ไหน ขอบคุณ!
Johnny Wu

1
โปรดอย่าลืมเพิ่มสิทธิ์การใช้งานจริงสำหรับ READ_EXTERNAL_STORAGE และ WRITE_EXTERNAL_STORAG ​​E สำหรับระดับที่ 23 และสูงกว่า มิฉะนั้นคุณอาจไม่ได้รับบิตแมปจากแกลเลอรี่เป็นไม่เป็นโมฆะ ดูstackoverflow.com/a/35285667/3341089
oguzhan

1
การเรียกใช้ setType หลังจากตั้งค่า URI จะล้างข้อมูล
Taslim Oseni

11

นี่คือตัวอย่างเต็มรูปแบบสำหรับการขออนุญาต (ถ้าจำเป็น) เลือกภาพจากแกลเลอรี่แล้วแปลงภาพเป็น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
    }
}

สาธิต
https://github.com/PhanVanLinh/AndroidPickImage


นี่คืออะไรไม่น้อยไปกว่าห้องสมุดโดยเฉพาะอย่างยิ่งกับคุณสมบัติการครอบตัดและอัตราส่วน ฉันไม่เคยรู้เรื่องนี้มาก่อน ขอบคุณมาก ๆ ท่าน.
Lalit Fauzdar

1
กลับมาที่นี่มันไม่ดีเท่าที่ฉันหวังว่าจะได้เห็นความประทับใจครั้งแรก ไม่เลือกรูปภาพเมื่อแก้ไขด้วย snapseed ไม่มีข้อผิดพลาด แต่ไม่มีรูปภาพแอพแกลเลอรีเริ่มต้นของ huawei ไม่ทำอะไรเลยเมื่อฉันคลิกที่ถัดไปหลังจากแก้ไขมันไม่แก้ไขรูปภาพเมื่อเลือกจาก google photos นำกลับมา ไม่มีมันโดยตรง ใช้งานได้ดีถ้าฉันเลือกแกลเลอรีเริ่มต้นของ huawei และ google photos เพื่อแก้ไข
Lalit Fauzdar

2

หากคุณกำลังมองหารูปภาพและตัวเลือกที่หลากหลาย

ดู @ หนึ่งครั้งhttps://stackoverflow.com/a/15029515/1136023

มันเป็นประโยชน์สำหรับ future.I เองรู้สึกดีโดยใช้MultipleImagePick


วิธีที่เร็วที่สุดในการใช้ MultipleImagePick เป็นห้องสมุดคืออะไร มันมาเป็นโครงการ / แอปพลิเคชันแบบสแตนด์อโลน ..
ticofab

2

เพียงเพื่อเสนอการอัปเดตคำตอบสำหรับผู้ที่มี API ขั้นต่ำ 19 ต่อเอกสาร:

บน Android 4.4 (API ระดับ 19) และสูงกว่าคุณมีตัวเลือกเพิ่มเติมในการใช้ความตั้งใจ ACTION_OPEN_DOCUMENT ซึ่งจะแสดง UI ตัวเลือกที่ควบคุมโดยระบบซึ่งควบคุมให้ผู้ใช้สามารถเรียกดูไฟล์ทั้งหมดที่แอปอื่น ๆ จาก UI เดียวนี้ผู้ใช้สามารถเลือกไฟล์จากแอพที่รองรับใด ๆ

บน Android 5.0 (API ระดับ 21) และสูงกว่าคุณสามารถใช้ความตั้งใจ ACTION_OPEN_DOCUMENT_TREE ซึ่งช่วยให้ผู้ใช้สามารถเลือกไดเรกทอรีสำหรับแอปไคลเอ็นต์ในการเข้าถึง

เปิดไฟล์โดยใช้เฟรมเวิร์กการเข้าถึงที่จัดเก็บข้อมูล - Android เอกสาร

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

0

สำหรับการเลือกจากท้องถิ่นเท่านั้นเพิ่ม:

        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)

-7

คุณสามารถทำได้ง่ายกว่าคำตอบนี้:

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

ฉันทำและมันได้ผล ถ้าคุณต้องการใช้ไฟล์เช่นส่งไปยังเซิร์ฟเวอร์คุณต้องใช้วิธีอื่น แต่เพียงแค่โหลดภาพไปยัง imageview u สามารถแก้ปัญหานี้ได้อย่างง่ายดาย
Alireza Taghizadeh

5
ยินดีต้อนรับสู่ SO! แทนที่จะแสดงความคิดเห็นในโพสต์ของคุณเองคุณสามารถแก้ไขโพสต์ของคุณได้ หากความคิดเห็นของคุณควรจะอธิบายคำตอบแล้วทำไมไม่ใส่ไว้ในคำตอบล่ะ? โดยส่วนตัวฉันไม่เห็นว่าคำตอบ (ล่าช้า) ของคุณสำหรับคำถามเก่านี้เกี่ยวข้องกับคำถามอย่างไร ฉันขอแนะนำให้มุ่งเน้นไปที่การตอบคำถามก่อนซึ่งยังไม่มีคำตอบที่ยอมรับได้?
cfi

1
ฉันหาคำถามเกี่ยวกับหุ่นยนต์ไม่ได้ ฉันจะเห็นคำถามหุ่นยนต์ได้อย่างไร
Alireza Taghizadeh

3
โปรดอ่านหน้าความช่วยเหลือ นอกจากนี้ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเกี่ยวกับวิธีการทำงานของเว็บไซต์คุณสามารถใช้ห้องสนทนาสำหรับการสนทนาสดกับผู้ใช้รายอื่นและคุณสามารถถามคำถามเฉพาะเกี่ยวกับ Meta (ช่วยเหลือ -> Meta)
cfi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.