Mam aplikację z galerią obrazów i chcę, aby użytkownik mógł ją zapisać w swojej własnej galerii. Stworzyłem menu opcji z pojedynczym "zapisz" głosem, aby to umożliwić, ale problem polega na… jak mogę zapisać obraz w galerii?
to jest mój kod:
@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);
}
}
nie jestem pewien tej części kodu:
File root = Environment.getExternalStorageDirectory();
File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg");
czy zapisywanie w galerii jest poprawne? niestety kod nie działa :(
android
imageview
gallery
save-image
Christian Giupponi
źródło
źródło
Odpowiedzi:
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription);
Poprzedni kod doda obraz na końcu galerii. Jeśli chcesz zmodyfikować datę tak, aby pojawiała się na początku, lub inne metadane, zobacz poniższy kod (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; } } }
źródło
.git
na końcu)Właściwie możesz zapisać swoje zdjęcie w dowolnym miejscu. Jeśli chcesz zapisać w przestrzeni publicznej, aby każda inna aplikacja miała do niej dostęp, użyj tego kodu:
storageDir = new File( Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES ), getAlbumName() );
Zdjęcie nie trafia do albumu. Aby to zrobić, musisz wywołać skanowanie:
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); }
Więcej informacji można znaleźć na https://developer.android.com/training/camera/photobasics.html#TaskGallery
źródło
Environment.getExternalStoragePublicDirectory
iIntent.ACTION_MEDIA_SCANNER_SCAN_FILE
są teraz przestarzałe ...Próbowałem wielu rzeczy, aby to zadziałało na Marshmallow i Lollipop. W końcu przeniosłem zapisane zdjęcie do folderu DCIM (nowa aplikacja Google Photo skanuje obrazy tylko wtedy, gdy najwyraźniej znajdują się w tym folderze)
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; }
A następnie standardowy kod do skanowania plików, który można znaleźć również w witrynie Google Developers .
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); }
Pamiętaj, że ten folder nie może być obecny na każdym urządzeniu na świecie i zaczynając od Marshmallow (API 23), musisz poprosić użytkownika o pozwolenie na WRITE_EXTERNAL_STORAGE.
źródło
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
załatwił sprawę dla mnie. Dzięki!getExternalStoragePublicDirectory()
jest teraz przestarzały w API 29. Należy użyć MediaStoreZgodnie z tym kursem , prawidłowym sposobem na to jest:
Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES )
W ten sposób uzyskasz ścieżkę główną do katalogu galerii.
źródło
Environment.getExternalStoragePublicDirectory
jest już przestarzały ...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); }
źródło
Możesz utworzyć katalog w folderze aparatu i zapisać obraz. Następnie możesz po prostu wykonać skanowanie. Natychmiast pokaże Twoje zdjęcie w galerii.
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);
źródło
Przychodzę tutaj z tymi samymi wątpliwościami, ale w przypadku Xamarin na Androida użyłem odpowiedzi Sigrist, aby wykonać tę metodę po zapisaniu mojego pliku:
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); }
i to rozwiązało mój problem, Thx Sigrist. Umieściłem to tutaj, ponieważ nie znalazłem oprogramowania answare na ten temat dla Xamarin i mam nadzieję, że może to pomóc innym ludziom.
źródło
W moim przypadku powyższe rozwiązania nie zadziałały musiałem wykonać następujące czynności:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));
źródło
ContentProvider
Androidem 6, więc preferowane rozwiązanieString filePath="/storage/emulated/0/DCIM"+app_name; File dir=new File(filePath); if(!dir.exists()){ dir.mkdir(); }
Ten kod znajduje się w metodzie onCreate. Ten kod służy do tworzenia katalogu nazwa_aplikacji. Teraz do tego katalogu można uzyskać dostęp za pomocą domyślnej aplikacji do zarządzania plikami w systemie Android. Użyj tego ciągu filePath wszędzie tam, gdzie jest to wymagane do ustawienia folderu docelowego. Jestem pewien, że ta metoda działa również na Androidzie 7, ponieważ testowałem na niej, więc może działać również na innych wersjach Androida.
źródło