2011-12-19 45 views
61

Ho un'app con una galleria di immagini e voglio che l'utente possa salvarla nella sua galleria. Ho creato un menu di opzioni con una sola voce "salva" per consentire che ma il problema è ... come posso salvare l'immagine nella galleria?android - salva l'immagine nella galleria

questo è il mio codice:

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

non sono sicuro di questa parte di codice:

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

è corretto per salvare nella galleria? purtroppo il codice non funziona :(

+0

hai risolto questo problema? puoi per favore condividere con me – user3233280

+0

ho anche lo stesso problema http://stackoverflow.com/questions/21951558/failed-to-save-image-from-app-assets-folder-to-gallery-folder-in-android/21951643? Noredirect = 1 # 21951643 – user3233280

+0

Per quelli di voi che stanno ancora avendo problemi a salvare il file, potrebbe essere perché il vostro url contiene caratteri illegali come "?", ":" E "-" Rimuovere quelli e dovrebbe lavoro. Questo è un errore comune nei dispositivi esterni e negli emulatori Android. Vedi di più qui: http://stackoverflow.com/questions/11394616/java-io-ioexception-open-failed-einval-invalid-argument-when-saving-a-image – ChallengeAccepted

risposta

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

Il codice precedente aggiungerà l'immagine alla fine della galleria.Se si desidera modificare la data in modo che appaia all'inizio o qualsiasi altro metadata, vedere il codice seguente (Cortesy of SK, samkirton):

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

Questo salva l'immagine, ma alla fine della galleria anche se quando si scatta una foto con la fotocamera si salva in alto. Come posso salvare l'immagine nella parte superiore della galleria? –

+25

Le persone dovrebbero sempre spiegare il motivo del loro downvote – sfratini

+15

Si noti che è necessario aggiungere anche al file manifest.xml. –

9

Secondo this course, il modo corretto per farlo è:.

Environment.getExternalStoragePublicDirectory(
     Environment.DIRECTORY_PICTURES 
    ) 

thios vi darà il percorso principale per la directory galleria

+0

ho provato questo nuovo codice ma si è schiantato java.lang.NoSuchFieldError: android.os.Environment.DIRECTORY_PICTURES –

+0

@Christian: questo codice funziona solo per Android> = 2.2 –

+0

ok grazie, quindi non c'è modo di mettere un'immagine nella galleria con Android <2.2? –

38

In realtà, è possibile salvare ti immagini in qualsiasi luogo. Se si desidera salvare in uno spazio pubblico, in modo che qualsiasi altra applicazione può accedere, utilizzare questo codice:

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

L'immagine non va all'album. Per fare questo, è necessario chiamare una scansione:

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

che si possono trovare maggiori informazioni a https://developer.android.com/training/camera/photobasics.html#TaskGallery

+0

Questa è una buona soluzione semplice dato che non è necessario modificare l'intera implementazione e che possiamo creare una cartella personalizzata per le app. –

+1

L'invio di una trasmissione può essere uno spreco di risorse quando è possibile eseguire la scansione di un solo file: http://stackoverflow.com/a/5814533/43051. –

+0

Questa è la soluzione migliore, grazie signore! –

8
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); 
} 
+1

ha funzionato perfettamente per me. – KNU

8

Ho provato un sacco di cose da lasciare che questo lavoro su Marshmallow e Lollipop. Finalmente ho finito per spostare l'immagine salvata nella cartella DCIM (immagini di scansione nuovo Google Foto app solo se sono all'interno di questa cartella a quanto pare)

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

E poi il codice standard per la scansione dei file che si possono trovare nel Google Developers site too.

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

Si ricorda che questa cartella non poteva essere presente in tutti i dispositivi in ​​tutto il mondo e che a partire da Marshmallow (API 23), è necessario richiedere il permesso di WRITE_EXTERNAL_STORAGE per l'utente.

+1

Grazie per le informazioni su Google Foto. –

+1

Questa è l'unica soluzione che spiega bene. Nessun altro ha menzionato che il file deve essere nella cartella DCIM. Grazie !!! –

+0

'Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DCIM)' ha fatto il trucco per me. Grazie! – saltandpepper

1

vengo qui con lo stesso dubbio ma per Xamarin per Android, ho usato la risposta Sigrist per fare questo metodo dopo aver salvare il mio file:

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

e risolto il mio problema, Thx Sigrist. L'ho messo qui perché non ho trovato un answare su questo per Xamarin e spero che possa aiutare le altre persone.

1

Nel mio caso le soluzioni di cui sopra non ha funzionato ho dovuto effettuare le seguenti operazioni:

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

è davvero bello sapere di questa opzione, ma sfortunatamente non funziona su alcuni dispositivi con Android 6, quindi la definizione di "ContentProvider" è preferibile – user5599807

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

Questo codice è nel codice onCreate method.This è per la creazione di una directory di APP_NAME. Ora, questa directory è accessibile tramite l'app di gestione file predefinita in Android. Usa questa stringa filePath dove richiesto per impostare la cartella di destinazione. Sono sicuro che questo metodo funziona anche su Android 7 perché ho provato su di esso. Quindi, può funzionare anche su altre versioni di Android.

1

È possibile creare una directory all'interno della cartella della fotocamera e salvare. E scansione una volta completata. Mostrerà istantaneamente la tua immagine nella galleria. Saluti!!

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