Android - गैलरी में छवि को बचाने


90

मेरे पास छवियों की गैलरी वाला एक ऐप है और मैं चाहता हूं कि उपयोगकर्ता इसे अपनी गैलरी में सहेज सकता है। मैंने एक एकल आवाज़ "सेव" के साथ एक विकल्प मेनू बनाया है जो यह अनुमति देता है लेकिन समस्या यह है ... मैं गैलरी में छवि कैसे बचा सकता हूं?

यह मेरा कोड है:

@Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle item selection
            switch (item.getItemId()) {
            case R.id.menuFinale:

                imgView.setDrawingCacheEnabled(true);
                Bitmap bitmap = imgView.getDrawingCache();
                File root = Environment.getExternalStorageDirectory();
                File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg");
                try 
                {
                    file.createNewFile();
                    FileOutputStream ostream = new FileOutputStream(file);
                    bitmap.compress(CompressFormat.JPEG, 100, ostream);
                    ostream.close();
                } 
                catch (Exception e) 
                {
                    e.printStackTrace();
                }



                return true;
            default:
                return super.onOptionsItemSelected(item);
            }
        }

मैं कोड के इस हिस्से के बारे में निश्चित नहीं हूं:

File root = Environment.getExternalStorageDirectory();
                File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg");

क्या गैलरी में सहेजना सही है? दुर्भाग्य से कोड काम नहीं करता है :(


क्या आपने इस मुद्दे को हल किया है? क्या आप मेरे साथ साझा कर सकते हैं
user3233280

मैं भी वही समस्या
खड़ी

आप में से उन लोगों के लिए जो अभी भी फ़ाइल सहेजने में समस्याएँ हैं, ऐसा इसलिए हो सकता है क्योंकि आपके url में ""? ",": ", और" - "जैसे गैरकानूनी वर्ण हैं और उन्हें काम करना चाहिए।" यह विदेशी उपकरणों और एंड्रॉइड एमुलेटर में एक सामान्य त्रुटि है। इसके बारे में यहाँ और देखें: stackoverflow.com/questions/11394616/…
ChallengeAccepted

स्वीकृत उत्तर 2019 में थोड़ा पुराना है। मैंने यहां एक अद्यतन उत्तर लिखा है: stackoverflow.com/questions/36624756/…
बाओ लेई

जवाबों:


168
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription);

पूर्व कोड गैलरी के अंत में छवि को जोड़ देगा। यदि आप तिथि को संशोधित करना चाहते हैं तो यह शुरुआत में या किसी अन्य मेटाडेटा पर दिखाई देता है, नीचे दिए गए कोड (SK, samkirton के Cortesy ) को देखें:

https://gist.github.com/samkirton/0242ba81d7ca00b475b9

/**
 * Android internals have been modified to store images in the media folder with 
 * the correct date meta data
 * @author samuelkirton
 */
public class CapturePhotoUtils {

    /**
     * A copy of the Android internals  insertImage method, this method populates the 
     * meta data with DATE_ADDED and DATE_TAKEN. This fixes a common problem where media 
     * that is inserted manually gets saved at the end of the gallery (because date is not populated).
     * @see android.provider.MediaStore.Images.Media#insertImage(ContentResolver, Bitmap, String, String)
     */
    public static final String insertImage(ContentResolver cr, 
            Bitmap source, 
            String title, 
            String description) {

        ContentValues values = new ContentValues();
        values.put(Images.Media.TITLE, title);
        values.put(Images.Media.DISPLAY_NAME, title);
        values.put(Images.Media.DESCRIPTION, description);
        values.put(Images.Media.MIME_TYPE, "image/jpeg");
        // Add the date meta data to ensure the image is added at the front of the gallery
        values.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
        values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());

        Uri url = null;
        String stringUrl = null;    /* value to be returned */

        try {
            url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

            if (source != null) {
                OutputStream imageOut = cr.openOutputStream(url);
                try {
                    source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
                } finally {
                    imageOut.close();
                }

                long id = ContentUris.parseId(url);
                // Wait until MINI_KIND thumbnail is generated.
                Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null);
                // This is for backward compatibility.
                storeThumbnail(cr, miniThumb, id, 50F, 50F,Images.Thumbnails.MICRO_KIND);
            } else {
                cr.delete(url, null, null);
                url = null;
            }
        } catch (Exception e) {
            if (url != null) {
                cr.delete(url, null, null);
                url = null;
            }
        }

        if (url != null) {
            stringUrl = url.toString();
        }

        return stringUrl;
    }

    /**
     * A copy of the Android internals StoreThumbnail method, it used with the insertImage to
     * populate the android.provider.MediaStore.Images.Media#insertImage with all the correct
     * meta data. The StoreThumbnail method is private so it must be duplicated here.
     * @see android.provider.MediaStore.Images.Media (StoreThumbnail private method)
     */
    private static final Bitmap storeThumbnail(
            ContentResolver cr,
            Bitmap source,
            long id,
            float width, 
            float height,
            int kind) {

        // create the matrix to scale it
        Matrix matrix = new Matrix();

        float scaleX = width / source.getWidth();
        float scaleY = height / source.getHeight();

        matrix.setScale(scaleX, scaleY);

        Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
            source.getWidth(),
            source.getHeight(), matrix,
            true
        );

        ContentValues values = new ContentValues(4);
        values.put(Images.Thumbnails.KIND,kind);
        values.put(Images.Thumbnails.IMAGE_ID,(int)id);
        values.put(Images.Thumbnails.HEIGHT,thumb.getHeight());
        values.put(Images.Thumbnails.WIDTH,thumb.getWidth());

        Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);

        try {
            OutputStream thumbOut = cr.openOutputStream(url);
            thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
            thumbOut.close();
            return thumb;
        } catch (FileNotFoundException ex) {
            return null;
        } catch (IOException ex) {
            return null;
        }
    }
}

22
यह छवि को बचाता है, लेकिन गैलरी के अंत में जब आप कैमरे के साथ एक तस्वीर लेते हैं तो यह शीर्ष पर बचाता है। मैं गैलरी के शीर्ष पर छवि को कैसे सहेज सकता हूं?
eric.itzhak

19
ध्यान दें कि आपको अपने manifext.xml में <उपयोग-अनुमति Android: name = "android.permission.WRITE_EXTERNAL_STORAGE" /> भी जोड़ना होगा।
काइल क्लेग

3
चित्र गैलरी के शीर्ष पर सहेजे नहीं जाते हैं क्योंकि आंतरिक रूप से सम्मिलन में कोई दिनांक मेटा डेटा नहीं जोड़ा जाता है। कृपया इस GIST को देखें: gist.github.com/0242ba81d7ca00b475b9.it, यह InsertImage विधि की एक सटीक प्रति है, लेकिन यह गैलरी के सामने छवि को जोड़ने के लिए तारीख मेटा तिथि को जोड़ता है।
एस-के '

1
@ S-K'I उस URL तक नहीं पहुँच सकता। कृपया इसे अपडेट करें और मैं अपना उत्तर अपडेट कर दूंगा, इसलिए इसमें दोनों विकल्प हैं। चीयर्स
sfratini

6
यहां ऊपर उल्लेखित सही GIST लिंक दिया गया है ( .gitअंत में हटाने की आवश्यकता है )
minipif

47

दरअसल, आप किसी भी स्थान पर तस्वीर को बचा सकते हैं। यदि आप किसी सार्वजनिक स्थान पर सहेजना चाहते हैं, तो कोई अन्य एप्लिकेशन इस कोड का उपयोग कर सकता है:

storageDir = new File(
    Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES
    ), 
    getAlbumName()
);

चित्र एल्बम पर नहीं जाता है। ऐसा करने के लिए, आपको एक स्कैन कॉल करना होगा:

private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

आप https://developer.android.com/training/camera/photobasics.html#TaskGallery पर अधिक जानकारी प्राप्त कर सकते हैं


1
यह एक अच्छा सरल उपाय है क्योंकि हमें संपूर्ण कार्यान्वयन को बदलने की आवश्यकता नहीं है और हम ऐप्स के लिए एक कस्टम फ़ोल्डर बना सकते हैं।
ह्यूगो ग्रेसे

2
प्रसारण को भेजना संसाधन की बर्बादी हो सकती है जब आप केवल एक फ़ाइल को स्कैन कर सकते हैं: stackoverflow.com/a/5814533/43051
जेरी रेयनॉड

आप वास्तव में बिटमैप पास कहाँ करते हैं?
डैनियल रेहानियान

20

मैंने मार्शमैलो और लॉलीपॉप पर इस काम को करने के लिए बहुत सी चीजों की कोशिश की है। अंत में मैंने सहेजे गए चित्र को DCIM फ़ोल्डर में ले जाना समाप्त कर दिया (नए Google फोटो ऐप स्कैन चित्र केवल तभी यदि वे इस फ़ोल्डर के अंदर हैं जाहिरा तौर पर)

public static File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
         .format(System.currentTimeInMillis());
    File storageDir = new File(Environment
         .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/Camera/");
    if (!storageDir.exists())
        storageDir.mkdirs();
    File image = File.createTempFile(
            timeStamp,                   /* prefix */
            ".jpeg",                     /* suffix */
            storageDir                   /* directory */
    );
    return image;
}

और फिर फ़ाइलों को स्कैन करने के लिए मानक कोड जिसे आप Google डेवलपर्स साइट में भी पा सकते हैं ।

public static void addPicToGallery(Context context, String photoPath) {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(photoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    context.sendBroadcast(mediaScanIntent);
}

कृपया याद रखें कि यह फ़ोल्डर दुनिया में हर डिवाइस में मौजूद नहीं हो सकता है और मार्शमैलो (एपीआई 23) से शुरू होकर, आपको उपयोगकर्ता को WRITE_EXTERNAL_STORAGE की अनुमति का अनुरोध करने की आवश्यकता है।


1
Google फ़ोटो से संबंधित जानकारी के लिए धन्यवाद।
जेरेमी रेनॉड

1
यह एक और एकमात्र समाधान है जो अच्छी तरह से समझाता है। किसी और ने उस फ़ाइल का उल्लेख DCIM फ़ोल्डर में नहीं किया होगा। धन्यवाद!!!
प्रेड्रैग मनोज्लोविक

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)मेरे लिए चाल चली। धन्यवाद!
साल्टेंडपीपर

2
getExternalStoragePublicDirectory()अब एपीआई 29 पर पदावनत किया गया है। मीडियास्टोर का उपयोग करने की आवश्यकता है
रिगैग्रो

@riggaroo हां आप सही हैं रेबेका, मैं जवाब ASAP
MatPag

12

इस कोर्स के अनुसार , ऐसा करने का सही तरीका है:

Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES
    )

यह आपको गैलरी निर्देशिका के लिए रूट पथ देगा।


मैं इस नए कोड की कोशिश की, लेकिन यह java.lang.NoSuchFieldError दुर्घटनाग्रस्त हो गया: android.os.Environment.DIRECTORY_PICTURES
क्रिश्चियन Giupponi

ठीक है धन्यवाद, इसलिए एंड्रॉइड <2.2 के साथ गैलरी पर एक छवि डालने का कोई तरीका नहीं है?
क्रिश्चियन गिउपोनी

बिल्कुल सही - सीधे Android डेवलपर वेबसाइट का लिंक। यह काम किया और एक सरल उपाय था।
फिल

1
अच्छा जवाब है, लेकिन यहां अन्य जवाबों से "GalleryAddPic" पद्धति को जोड़ना बेहतर होगा, क्योंकि आप आमतौर पर गैलरी ऐप को नई तस्वीरों को नोटिस करना चाहेंगे।
एंड्रयू कोस्टर

11
private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

6

आप कैमरा फ़ोल्डर के अंदर एक निर्देशिका बना सकते हैं और छवि को बचा सकते हैं। उसके बाद, आप बस अपना स्कैन कर सकते हैं। यह तुरंत गैलरी में आपकी छवि दिखाएगा।

String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()+ "/Camera/Your_Directory_Name";
File myDir = new File(root);
myDir.mkdirs();
String fname = "Image-" + image_name + ".png";
File file = new File(myDir, fname);
System.out.println(file.getAbsolutePath());
if (file.exists()) file.delete();
    Log.i("LOAD", root + fname);
    try {
        FileOutputStream out = new FileOutputStream(file);
        finalBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
        out.flush();
        out.close();
    } catch (Exception e) {
       e.printStackTrace();
    }

MediaScannerConnection.scanFile(context, new String[]{file.getPath()}, new String[]{"image/jpeg"}, null);

इस मापदंड में यह सबसे अच्छा उत्तर है
नूर हुसैन

1

मैं यहाँ एक ही संदेह के साथ आता हूं लेकिन एंड्रॉइड के लिए ज़मारिन के लिए, मैंने अपनी फ़ाइल को सहेजने के बाद इस पद्धति को करने के लिए सिग्रीस्ट उत्तर का उपयोग किया है:

private void UpdateGallery()
{
    Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
    Java.IO.File file = new Java.IO.File(_path);
    Android.Net.Uri contentUri = Android.Net.Uri.FromFile(file);
    mediaScanIntent.SetData(contentUri);
    Application.Context.SendBroadcast(mediaScanIntent);
} 

और इसने मेरी समस्या हल कर दी, Thx Sigrist। मैं इसे यहाँ डाल दिया क्योंकि मैं Xamarin के लिए इस बारे में एक खबरदार नहीं मिला और मुझे उम्मीद है कि यह अन्य लोगों की मदद कर सकता है।


1

मेरे मामले में ऊपर दिए गए समाधानों ने काम नहीं किया मुझे निम्नलिखित कार्य करने थे:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));

इसकी की वास्तव में अच्छा इस विकल्प के बारे में पता करने के लिए, लेकिन दुर्भाग्य से एंड्रॉयड 6 के साथ कुछ उपकरणों पर नहीं काम करता है, इसलिए ContentProviderबेहतर solytion
सिआर्ही

0
 String filePath="/storage/emulated/0/DCIM"+app_name;
    File dir=new File(filePath);
    if(!dir.exists()){
        dir.mkdir();
    }

यह कोड onCreate मेथड में है। यह कोड app_name की डायरेक्टरी बनाने के लिए है। अब, इस निर्देशिका को एंड्रॉइड में डिफ़ॉल्ट फ़ाइल प्रबंधक ऐप का उपयोग करके एक्सेस किया जा सकता है। अपने गंतव्य फ़ोल्डर को सेट करने के लिए जहाँ भी आवश्यक हो, इस स्ट्रिंग फ़ाइलपैथ का उपयोग करें। मुझे यकीन है कि यह विधि एंड्रॉइड 7 पर भी काम करती है क्योंकि मैंने इस पर परीक्षण किया था। हेंस, यह एंड्रॉइड के अन्य संस्करणों पर भी काम कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.