2015-01-30 11 views
5

Ich versuche ein neues Bild in die Galerie einzufügen. Ich wähle ein bereits vorhandenes Bild durch eine Absicht und skaliere es dann und komprimiere es.Bild zu Media Gallery hinzufügen - Android

Dann speichere ich die resultierende Bitmap:

public static File compressAndSaveImage(Context ctx, Uri imageUri) throws FileNotFoundException { 
    File file = null; 

    if (imageUri != null) { 
     ContextWrapper cw = new ContextWrapper(ctx); 
     File directory = cw.getDir("imageDir", Context.MODE_PRIVATE); 
     file = new File(directory, imageUri.getLastPathSegment()); 
     System.out.println("storing to " + file); 

     InputStream input = ctx.getContentResolver().openInputStream(imageUri); 
     Bitmap b = ImageManager.resize(BitmapFactory.decodeStream(input), 
       ctx.getResources().getDimension(R.dimen.player_thumb_w), 
       ctx.getResources().getDimension(R.dimen.player_thumb_h)); 

     FileOutputStream fos = new FileOutputStream(file); 
     if (b.compress(Bitmap.CompressFormat.PNG, 100, fos)) { 
      System.out.println("Compression success");// bmp is your Bitmap instance 
     } 
     addPictureToGallery(ctx, file); 
    } 
    return file; 
} 

Aber wenn ich versuche, das Bild in die Galerie hinzufügen, bekomme ich keine Fehler, und das Bild wird nicht hinzugefügt. Ich habe versucht, beide Methoden unter:

private static void addPictureToGallery(Context ctx, File filepath) { 
//  Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
//  System.out.println("Publish: " + filepath.exists()); 
//  System.out.println("Publish: " + filepath.getAbsolutePath()); 
//  Uri contentUri = Uri.fromFile(filepath); 
//  mediaScanIntent.setData(contentUri); 
//  ctx.sendBroadcast(mediaScanIntent); 
    MediaScannerConnection.scanFile(
      ctx, 
      new String[]{filepath.getAbsolutePath()}, 
      null, 
      new MediaScannerConnection.OnScanCompletedListener() { 
       @Override 
       public void onScanCompleted(String path, Uri uri) { 
        Log.w("mydebug", "file " + path + " was scanned successfully: " + uri); 
       } 
      }); 
    } 
} 

Der Rückruf druckt die folgende Zeile:

file /data/data/test.myapps.appname/app_imageDir/6045564126748266738 was scanned successfully: content://media/external/file/7838 

Was bin ich?

Antwort

2

Ich würde dies als Kommentar hinzufügen, da ich keine Zeit habe, wirklich ins Detail zu gehen, aber es ist offensichtlich zu lang. Probieren Sie so etwas aus (ich verwende dies zum Speichern von Bitmaps in der Galerie). Als Anmerkung scheint es, dass Sie nichts anderes tun, als ein Bild zu scannen. Im Moment scheint es, dass Sie die Datei in Ihrem internen Speicher speichern, nicht in Ihrem Telefoninhalt (Galerie).

Angenommen wir dies von ActivityA.class ausgeführt werden, die Aktivität

/** 
* Will save our card (currently set as a bitmap) as a jpeg and save it into our devices 
* native photo gallery. Unfortunately, the default method for this will add the image to the bottom 
* of the gallery by default, that is no good. This more complex method that utilizes Android's 
* native methods will allow us to store the bitmap at the top of the gallery by setting it's 
* meta data to today's date. 
*/ 
public class SaveBitmapToDevice extends AsyncTask<Bitmap, Void, String>{ 

    private final ShareType type; 

    public SaveBitmapToDevice(ShareType type){ 
     this.type = type; 
    } 

    @Override 
    protected String doInBackground(Bitmap... cards) { 
     return insertImageIntoGallery(getContentResolver(), cards[0], getString(R.string.card_gallery_title), 
       getString(R.string.card_gallery_label)); 
    } 

    /** 
    * 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(android.content.ContentResolver, Bitmap, String, String). 
    * If the MediaStore not available, we will redirect the file to our alternative source, the SD card. 
    */ 
    public String insertImageIntoGallery(ContentResolver cr, Bitmap source, String title, String description) { 

     ContentValues values = new ContentValues(); 
     values.put(MediaStore.Images.Media.TITLE, title); 
     values.put(MediaStore.Images.Media.DISPLAY_NAME, title); 
     values.put(MediaStore.Images.Media.DESCRIPTION, description); 
     values.put(MediaStore.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(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()); 
     values.put(MediaStore.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 = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MINI_KIND, null); 
       // This is for backward compatibility. 
       storeThumbnail(cr, miniThumb, id, 50F, 50F, MediaStore.Images.Thumbnails.MICRO_KIND); 
      } else { 
       cr.delete(url, null, null); 
       return storeToAlternateSd(source, title); 
       // url = null; 
      } 
     } catch (Exception e) { 
      if (url != null) { 
       cr.delete(url, null, null); 
       return storeToAlternateSd(source, title); 
       // url = null; 
      } 
     } 

     savedOnSD = false; 
     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 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(MediaStore.Images.Thumbnails.KIND,kind); 
     values.put(MediaStore.Images.Thumbnails.IMAGE_ID,(int)id); 
     values.put(MediaStore.Images.Thumbnails.HEIGHT,thumb.getHeight()); 
     values.put(MediaStore.Images.Thumbnails.WIDTH,thumb.getWidth()); 

     Uri url = cr.insert(MediaStore.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) { 
      Log.e("IMAGE_COMPRESSION_ERROR", "File not found"); 
      ex.printStackTrace(); 
      return null; 
     } catch (IOException ex) { 
      Log.e("IMAGE_COMPRESSION_ERROR", "IO Exception"); 
      ex.printStackTrace(); 
      return null; 
     } 
    } 

    /** 
    * If we have issues saving into our MediaStore, save it directly to our SD card. We can then interact with this file 
    * directly, opposed to pulling from the MediaStore. Again, this is a backup method if things don't work out as we 
    * would expect (seeing as most devices will have a MediaStore). 
    * 
    * @param src 
    * @param title 
    * @return - the file's path 
    */ 
    private String storeToAlternateSd(Bitmap src, String title){ 
     if(src == null) 
      return null; 

     File sdCardDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "My Cards"); 
     if(!sdCardDirectory.exists()) 
      sdCardDirectory.mkdir(); 

     SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy - (hh.mm.a)", Locale.US); 
     File image = new File(sdCardDirectory, title + " -- [" + sdf.format(new Date()) + "].jpg"); 
     try { 
      FileOutputStream imageOut = new FileOutputStream(image); 
      src.compress(Bitmap.CompressFormat.JPEG, 100, imageOut); 
      imageOut.close(); 
      savedOnSD = true; 
      return image.getAbsolutePath(); 
     } catch (FileNotFoundException ex) { 
      ex.printStackTrace(); 
      return null; 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 

    @Override 
    public void onPostExecute(String url){ 
     if(url != null){ 
      Intent intent = new Intent(); 
      intent.setAction(Intent.ACTION_VIEW); 
      if(savedOnSD){ 
       File file = new File(url); 
       if(file.exists()) 
        intent.setDataAndType(Uri.fromFile(file), "image/jpeg"); 
       else 
        return; 
      } 
      else 
       intent.setDataAndType(Uri.parse(url), "image/jpeg"); 

      ActivityA.this.startActivity(intent); 
     } 
     else 
      Toast.makeText(ActivityA.this, getString(R.string.error_compressing), Toast.LENGTH_SHORT).show(); 
    } 

} 
+0

Vielen Dank für ein hilfreiches Stück Code. Kann aber nicht herausfinden, was "imageUrl" am Ende ist ... – rommex

+0

Mehr als willkommen.Es sollte nur URL sein.Erarbeitet die Antwort.Schauen Sie sich die Antwort von paramkmiakos unten, es scheint eine endgültige Lösung zu sein. – zgc7009

7

Thanks @ zgc7009, setzen Sie mich auf dem richtigen Weg erstreckt. Ich habe etwas von deinem Code benutzt, und das ist das Endergebnis für alle anderen, die es lösen wollen.

Das Problem bestand tatsächlich darin, dass ich das Bild im lokalen Speicher meiner Anwendung speicherte.

File storedImagePath = generateImagePath("player", "png"); 
if (!compressAndSaveImage(storedImagePath, bitmap)) { 
    return null; 
} 
Uri url = addImageToGallery(context.getContentResolver(), "png", storedImagePath); 

Wo die drei verwendeten Methoden sind:

Pfad generieren

private static File getImagesDirectory() { 
    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + IMAGE_DIR);//Environment.getExternalStorageDirectory() 
    if (!file.mkdirs() && !file.isDirectory()) { 
     Log.e("mkdir", "Directory not created"); 
    } 
    return file; 
} 

public static File generateImagePath(String title, String imgType) { 
    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy-hh-mm-ss"); 
    return new File(getImagesDirectory(), title + "_" + sdf.format(new Date()) + "." + imgType); 
} 

komprimieren und speichern

public boolean compressAndSaveImage(File file, Bitmap bitmap) { 
    boolean result = false; 
    try { 
     FileOutputStream fos = new FileOutputStream(file); 
     if (result = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)) { 
      Log.w("image manager", "Compression success"); 
     } 
     fos.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return result; 
} 

Um Galle hinzufügen ry

public Uri addImageToGallery(ContentResolver cr, String imgType, File filepath) { 
    ContentValues values = new ContentValues(); 
    values.put(MediaStore.Images.Media.TITLE, "player"); 
    values.put(MediaStore.Images.Media.DISPLAY_NAME, "player"); 
    values.put(MediaStore.Images.Media.DESCRIPTION, ""); 
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/" + imgType); 
    values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()); 
    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); 
    values.put(MediaStore.Images.Media.DATA, filepath.toString()); 

    return cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 
} 
0

Sie auch Mediastore statische Methoden ...

public String addImageToGallery(ContentResolver cr, File filepath) { 
    try { 
     retrun MediaStore.Images.Media.insertImage(cr, filepath.toString(), 
                filepath.getName(), "Image Description"); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 
} 

Die String kehrte von insertImage ist der gleiche wie der Aufruf von toString() auf dem Uri Objekt in der akzeptierte Antwort benutzen konnten.

Ich weiß, das ist ein älterer Beitrag, aber ich hoffe, dass dies anderen helfen kann, die ihren Weg noch hier finden.

Verwandte Themen