รูปภาพที่บันทึกไว้ใน sdcard จะไม่ปรากฏในแอป Gallery ของ Android


93

ฉันบันทึกภาพลงใน sdcard และไม่ปรากฏในแอปพลิเคชันคลังภาพจนกว่าฉันจะดึง sdcard ออกและส่งคืน

คุณมีความคิดว่าทำไมจึงเป็นเช่นนั้น?

ดูเหมือนว่าแอปพลิเคชันคลังภาพจะมีแคชบางส่วนที่ไม่ได้อัปเดตในการบันทึกไฟล์ ...

อันที่จริงผมยังต้องการที่จะเปิดภาพเพียงบันทึกไว้ในใบสมัคร Gallery และมีความสำเร็จใด ๆ กับที่
นี้คือคำถามของฉันเกี่ยวกับปัญหานี้


1
คำถามนี้ได้รับคำตอบทีละขั้นตอนในบทช่วยสอนนี้: stackoverflow.com/questions/30506301/…
Takermania

คำตอบ:


45

ระบบจะสแกนการ์ด SD เมื่อติดตั้งเพื่อค้นหาไฟล์รูปภาพใหม่ (และอื่น ๆ ) หากคุณกำลังเพิ่มไฟล์โดยใช้โปรแกรมคุณสามารถใช้คลาสนี้:

http://developer.android.com/reference/android/media/MediaScannerConnection.html


4
หมายเหตุด้านข้าง: แม้ว่าคำถามจะอ้างถึงการเพิ่มไฟล์ แต่ MediaScannerConnection ไม่ได้ให้โซลูชันสำหรับการลบไฟล์ - แม้ในขณะที่ขอให้สแกนโฟลเดอร์หลักของไฟล์ที่ถูกลบ
AlikElzin-kilaka

86

วิธีแก้ปัญหาที่ง่ายกว่าคือใช้วิธีscanFile ()สะดวกแบบคงที่:

File imageFile = ...
MediaScannerConnection.scanFile(this, new String[] { imageFile.getPath() }, new String[] { "image/jpeg" }, null);

thisกิจกรรมของคุณอยู่ที่ไหน(หรือบริบทใดก็ตาม) ประเภทละครใบ้จำเป็นต่อเมื่อคุณใช้นามสกุลไฟล์ที่ไม่ได้มาตรฐานและใช้nullสำหรับการเรียกกลับที่เป็นทางเลือก (ซึ่งเราไม่จำเป็นสำหรับกรณีง่ายๆเช่นนี้)


2
Spot on วิธีการออกอากาศที่ผู้อื่น (และ Google) ให้มาใช้งานได้น้อยมาก)
Chris Jenkins

2
สิ่งนี้ใช้ได้กับฉันใน Android เวอร์ชันก่อนหน้า ~ 4.0 แต่ตอนนี้ใน 4.3+ ดูเหมือนจะไม่ทำงาน รูปภาพไม่ปรากฏในแอปแกลเลอรี
hooby3dfx

สมบูรณ์แบบ! คุณสามารถรับบริบทด้วย: Android.App.Application.Context
เหยือก

ทำงานในขนมหวาน
Hitesh Sahu

66

คำตอบของฉันสำหรับคำถามเดิมและสำหรับคนอื่น ๆ ที่อาจมีปัญหานี้:

ฉันประสบปัญหาเดียวกันนี้รูปภาพในแอปของฉันที่ผู้คนบันทึกไว้ในการ์ด SD ไม่ปรากฏในแกลเลอรีทันที หลังจากการค้นหาบางครั้งฉันพบโค้ดหนึ่งบรรทัดนี้แทรกหลังจากรหัส 'บันทึกลงใน sdcard' ของฉันซึ่งแก้ไขปัญหา:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

เราจำเป็นต้องใช้เครื่องสแกนสื่อเพื่อให้สามารถใช้การถ่ายทอดนี้ได้หรือไม่ ฉันใช้วิธีอื่นเพื่อแสดงภาพในแกลเลอรีของฉัน เมื่อฉันใช้ sendBroadcast ด้านบนบนปุ่มบันทึกคลิกแกลเลอรีของฉันไม่ได้รับการอัปเดตด้วยภาพใหม่!
เปลี่ยน

4
มันเก่า แต่อาจช่วยใครบางคนได้ - เส้นทางที่เฉพาะเจาะจงมากขึ้น: sendBroadcast (Intent ใหม่ (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_PICTURES)))); วิธีนี้ (คำตอบนี้ไม่ใช่เฉพาะความคิดเห็นของฉัน) ใช้ไม่ได้กับโปรแกรมจำลอง ทดสอบบนอุปกรณ์จริง

ฉันเชื่อว่าคำตอบที่ได้รับการยอมรับเสนอวิธีที่ถูกต้องในการทำ แต่ถ้าคุณพยายามสนับสนุน API <= 7 นี่เป็นทางเลือกที่ดี
Amr Mostafa

คำตอบของคุณมีประโยชน์สำหรับอุปกรณ์อื่น ๆ มันไม่ทำงานบน HTC เมื่อฉันพยายามสแกนโฟลเดอร์แอปพลิเคชันของฉัน มันไม่แสดงรูปภาพที่เพิ่มใหม่
MobileEvangelist

6
ดูเหมือนว่าจะไม่รองรับ Android 4.4 ขึ้นไปอีกต่อไป ข้อยกเว้นการอนุญาตจะถูกโยนทิ้งในกรณีนี้
rsp1984

13

นอกจากนี้คุณยังสามารถเพิ่มรูปภาพลงในแกลเลอรีสื่อโดยเจตนาดูโค้ดตัวอย่างเพื่อดูวิธีการทำ:

ContentValues image = new ContentValues();

image.put(Images.Media.TITLE, imageTitle);
image.put(Images.Media.DISPLAY_NAME, imageDisplayName);
image.put(Images.Media.DESCRIPTION, imageDescription);
image.put(Images.Media.DATE_ADDED, dateTaken);
image.put(Images.Media.DATE_TAKEN, dateTaken);
image.put(Images.Media.DATE_MODIFIED, dateTaken);
image.put(Images.Media.MIME_TYPE, "image/png");
image.put(Images.Media.ORIENTATION, 0);

 File parent = imageFile.getParentFile();
 String path = parent.toString().toLowerCase();
 String name = parent.getName().toLowerCase();
 image.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
 image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
 image.put(Images.Media.SIZE, imageFile.length());

 image.put(Images.Media.DATA, imageFile.getAbsolutePath());

 Uri result = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);

สวัสดี. วิธีนี้เป็นการเพิ่มรูปภาพไปยัง MediaStore ฉันได้ยืนยันโดยการตรวจสอบสิ่งที่ส่งคืนUriแต่ปัญหาคือรูปภาพที่แทรกไม่แสดงในแกลเลอรี ฉันได้ตรวจสอบทั้งในตอนต้นและตอนท้ายของแกลเลอรี คุณช่วยแนะนำวิธีการใด ๆ เพื่อให้ภาพที่แทรกปรากฏในแกลเลอรีทันทีได้ไหม
Shajeel Afzal

12

การรีเฟรชแกลเลอรีรวมถึง Android KITKAT

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
}
else
{
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}

รหัสที่อยู่ในเงื่อนไขแรกคำสั่ง "IF" ที่เป็นสีขาวใช้ได้ดีสำหรับฉันใน KitKat (Android 4.4.4, API 19)
Alex

8

นี่คือรหัสสำหรับ MediaScannerConnection:

MyMediaConnectorClient client = new MyMediaConnectorClient(newfile);
MediaScannerConnection scanner = new MediaScannerConnection(context, client);
client.setScanner(scanner);
scanner.connect();

newfile เป็นวัตถุไฟล์ของไฟล์ใหม่ / ที่บันทึกไว้ของคุณ


2
ขอบคุณสำหรับคำตอบ. อันที่จริงฉันทำโปรเจ็กต์นี้เสร็จไปนานแล้ว ... ฉันจำไม่ได้ด้วยซ้ำว่าวิธีแก้ปัญหาที่ฉันใช้คืออะไร ผู้ใช้รายอื่นอาจพบว่าโซลูชันของคุณมีประโยชน์หากคุณให้การใช้งานMyMediaConnectorClient...
Michael Kessler

ใช่ - ฉันกำลังปวดหัวกับเรื่องนี้ในขณะนี้ กรุณาโพสต์ขึ้น :)
สตีฟ

ใช่ฉันไม่ชัดเจนจริงๆว่าโฟลว์ควรเป็นอย่างไร - แก้ไขฉันผิดฉันสามารถใช้ MediaScannerConnection เพื่ออัปเดตข้อมูล SDCAARD ดังนั้นฉันจึงถ่ายภาพด้วยกล้องและส่งไฟล์ใหม่ไปยัง MSC และตอนนี้ฉันสามารถเข้าถึงไฟล์ได้ ด้วยไคลเอนต์สแกนเนอร์การเชื่อมต่อ?
Steve

ขั้นตอนคือ: คุณถ่ายภาพบันทึกลงใน sdcard ของคุณจากนั้นทำการอัปเดตสแกนเนอร์เพื่อให้ระบบไฟล์ได้รับการอัปเดตเพื่อดูรูปภาพที่คุณบันทึกไว้ในแกลเลอรีอุปกรณ์ หากคุณไม่ทำเช่นนั้นกับสแกนเนอร์คุณจะเห็นรูปภาพของคุณหลังจากรีสตาร์ทอุปกรณ์ถัดไปในแกลเลอรี
3dmg


6

ให้กิจกรรมของคุณใช้ 'MediaScannerConnectionClient' และเพิ่มสิ่งนี้ในกิจกรรมของคุณ:

private void startScan() 
{ 
    if(conn!=null) conn.disconnect();  
    conn = new MediaScannerConnection(YourActivity.this,YourActivity.this); 
    conn.connect(); 
} 

@Override 
public void onMediaScannerConnected() { 
    try{
        conn.scanFile(yourImagePath, "image/*");
       } catch (java.lang.IllegalStateException e){
       }
}

@Override 
public void onScanCompleted(String path, Uri uri) { 
    conn.disconnect(); 
} 

ไฮ! จะเกิดอะไรขึ้นถ้าเรารู้จักUriภาพตัวอย่างเช่นcontent://media/external/images/media/1231778
Shajeel Afzal


4
 File folderGIF = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/newgif2");    //path where gif will be stored
success = folderGIF.mkdir();    //make directory
 String finalPath = folderGIF + "/test1.gif";  //path of file
.....
/* changes in gallery app if any changes in done*/
 MediaScannerConnection.scanFile(this,
                    new String[]{finalPath}, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.i("ExternalStorage", "Scanned " + path + ":");
                            Log.i("ExternalStorage", "-> uri=" + uri);
                        }
                    });

ฉันต้องการบันทึกไฟล์ gif แบบเคลื่อนไหวซึ่งอยู่ในที่จัดเก็บข้อมูลภายนอกและฉันมีพา ธ คือ / storage / emulated / 0 / Android / data / <PackageName> / files / <FolderName> /xyz.gif ตอนนี้ฉันต้องการบันทึก / คัดลอกไฟล์นี้ไปยังแกลเลอรีรูปภาพและแสดงที่นั่น วิธีการทำ
Zia Ur Rahman

3

ที่นี่ฉันกำลังแชร์รหัสที่สามารถโหลดรูปภาพในรูปแบบของบิตแมปและบันทึกภาพนั้นในแกลเลอรี sdcard ในโฟลเดอร์ชื่อแอป คุณควรทำตามขั้นตอนเหล่านี้

  1. ดาวน์โหลด Image Bitmap ก่อน



     private Bitmap loadBitmap(String url) {
        try {
            InputStream in = new java.net.URL(url).openStream();
            return BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
       }


  1. โปรดให้สิทธิ์ต่อไปนี้ในไฟล์ AndroidManifest.xml ของคุณ


    uses-permission android:name="android.permission.INTERNET" 
    uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"


  1. นี่คือโค้ดทั้งหมดที่เขียนใน Activty ซึ่งเราต้องการดำเนินการนี้



     void saveMyImage(String appName, String imageUrl, String imageName) {

            Bitmap bmImg = loadBitmap(imageUrl);
            File filename;
            try {
                String path1 = android.os.Environment.getExternalStorageDirectory()
                        .toString();
                File file = new File(path1 + "/" + appName);
                if (!file.exists())
                    file.mkdirs();
                filename = new File(file.getAbsolutePath() + "/" + imageName
                        + ".jpg");
                FileOutputStream out = new FileOutputStream(filename);
                bmImg.compress(Bitmap.CompressFormat.JPEG, 90, out);
                out.flush();
                out.close();
                ContentValues image = new ContentValues();
                image.put(Images.Media.TITLE, appName);
                image.put(Images.Media.DISPLAY_NAME, imageName);
                image.put(Images.Media.DESCRIPTION, "App Image");
                image.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
                image.put(Images.Media.MIME_TYPE, "image/jpg");
                image.put(Images.Media.ORIENTATION, 0);
                File parent = filename.getParentFile();
                image.put(Images.ImageColumns.BUCKET_ID, parent.toString()
                        .toLowerCase().hashCode());
                image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, parent.getName()
                        .toLowerCase());
                image.put(Images.Media.SIZE, filename.length());
                image.put(Images.Media.DATA, filename.getAbsolutePath());
                Uri result = getContentResolver().insert(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
                Toast.makeText(getApplicationContext(),
                        "File is Saved in  " + filename, Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }


  1. หวังว่าจะสามารถแก้ปัญหาทั้งหมดของคุณได้

3
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

ดูเหมือนจะไม่ทำงานกับ KITKAT มันแสดงข้อยกเว้นการปฏิเสธการอนุญาตและทำให้แอปล่ม สำหรับสิ่งนี้ฉันได้ทำสิ่งต่อไปนี้

String path = mediaStorageDir.getPath() + File.separator
                    + "IMG_Some_name.jpg";
CameraActivity.this.sendBroadcast(new Intent(
                             Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri
                            .parse("file://" + path)));

หวังว่าจะช่วยได้


2

ใช้สิ่งนี้หลังจากบันทึกภาพ

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

3
วิธีนี้ใช้ได้ผล แต่ไม่ใช่ทางออกที่ดีที่สุด คุณกำลังหลอกให้ระบบคิดว่าการ์ด SD จะถูกติดตั้ง (ใหม่) และอาจบังคับให้สแกนการ์ด SD ใหม่ทั้งหมด MediaScanner.scanFile (.. ) เป็นทางออกที่ดีที่สุดเมื่อตอนนี้คุณมีไฟล์ที่คุณต้องการเพิ่ม
pocmo

1
ค้นหาภาพทั้งหมดนี้ และเกี่ยวข้องกับการประมวลผลข้อมูลจำนวนมากที่ไม่จำเป็นซึ่งอาจไม่เกี่ยวข้องเมื่อเรามีเพียงภาพเดียวที่จะแสดงในแกลเลอรี
Rahul Rastogi

2

รหัสของฉันสำหรับ MyMediaConnectorClient:

public class MyMediaConnectorClient implements MediaScannerConnectionClient {

    String _fisier;
    MediaScannerConnection MEDIA_SCANNER_CONNECTION;

    public MyMediaConnectorClient(String nume) {
        _fisier = nume;
    }

    public void setScanner(MediaScannerConnection msc){
        MEDIA_SCANNER_CONNECTION = msc;
    }

    @Override
    public void onMediaScannerConnected() {
        MEDIA_SCANNER_CONNECTION.scanFile(_fisier, null);
    }

    @Override
    public void onScanCompleted(String path, Uri uri) {
        if(path.equals(_fisier))
            MEDIA_SCANNER_CONNECTION.disconnect();
    }
}

0

คุณต้องให้สิทธิ์แก่แอปคลังภาพ เพียงแค่กดไอคอนแอปแกลเลอรีในหน้าจอหลักค้างไว้แล้วแตะ 'ข้อมูลแอป' ที่ปรากฏขึ้นที่ด้านบนของหน้าจอ การทำเช่นนี้จะแสดงการตั้งค่าแอปแกลเลอรี ตอนนี้ไปที่แท็บสิทธิ์และเปิดใช้งานที่เก็บข้อมูลการอนุญาตกล้องโดยการสลับ ไปที่แอปแกลเลอรีดั้งเดิมของคุณแล้วคุณจะได้รับภาพที่บันทึกไว้


0

วิธีนี้จะช่วยแก้ปัญหาของคุณได้หากรูปภาพของคุณในแกลเลอรีไม่ปรากฏขึ้นแทนที่จะแสดงบิตแมปประเภท 404 ใน midle โปรดเพิ่มแท็กที่อยู่ในรหัสของฉันด้วยรูปภาพของคุณเนื่องจากต้องมีข้อมูลเมตาเพื่อแสดงภาพในแกลเลอรี

      String resultPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES)+ 
      getString(R.string.directory) + System.currentTimeMillis() + ".jpg";

       new File(resultPath).getParentFile().mkdir();

        try {
            OutputStream fileOutputStream = new FileOutputStream(resultPath);
            savedBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
        savedBitmap.recycle();

        File file = new File(resultPath);
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "Photo");
        values.put(MediaStore.Images.Media.DESCRIPTION, "Edited");
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis ());
        values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
        values.put(MediaStore.Images.ImageColumns.BUCKET_ID, file.toString().toLowerCase(Locale.US).hashCode());
        values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, file.getName().toLowerCase(Locale.US));
        values.put("_data", resultPath);

        ContentResolver cr = getContentResolver();
        cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);




        return  resultPath;

0

ลองใช้อันนี้มันจะถ่ายทอดเกี่ยวกับภาพใหม่ที่สร้างขึ้นเพื่อให้มองเห็นภาพของคุณได้ ภายในแกลเลอรี photoFileแทนที่ด้วยพา ธ ไฟล์จริงของรูปภาพที่สร้างขึ้นใหม่

private void galleryAddPicBroadCast() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(photoFile);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.