Zapisywanie i odczytywanie bitmap / obrazów z pamięci wewnętrznej w systemie Android

161

To, co chcę zrobić, to zapisać obraz w wewnętrznej pamięci telefonu (nie na karcie SD) .

Jak mogę to zrobić?

Mam obraz bezpośrednio z aparatu do widoku obrazu w mojej aplikacji, wszystko działa dobrze.

Teraz chcę zapisać ten obraz z widoku obrazu w pamięci wewnętrznej mojego urządzenia z Androidem, a także uzyskać do niego dostęp w razie potrzeby.

Czy ktoś może mi pomóc, jak to zrobić?

Jestem trochę nowy w Androidzie, więc proszę, byłbym wdzięczny za szczegółową procedurę.

Usama Zafar
źródło
Cześć, gdzie /data/data/yourapp/app_data/imageDirdokładnie się znajduje? stackoverflow.com/questions/40323126/…
Khalil Khalaf

Odpowiedzi:

344

Użyj poniższego kodu, aby zapisać obraz w katalogu wewnętrznym.

private String saveToInternalStorage(Bitmap bitmapImage){
        ContextWrapper cw = new ContextWrapper(getApplicationContext());
         // path to /data/data/yourapp/app_data/imageDir
        File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
        // Create imageDir
        File mypath=new File(directory,"profile.jpg");

        FileOutputStream fos = null;
        try {           
            fos = new FileOutputStream(mypath);
       // Use the compress method on the BitMap object to write image to the OutputStream
            bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
        } catch (Exception e) {
              e.printStackTrace();
        } finally {
            try {
              fos.close();
            } catch (IOException e) {
              e.printStackTrace();
            }
        } 
        return directory.getAbsolutePath();
    }

Wyjaśnienie:

1. Katalog zostanie utworzony pod podaną nazwą. Javadocs służy do informowania, gdzie dokładnie utworzy katalog.

2. Będziesz musiał podać nazwę obrazu, pod którą chcesz go zapisać.

Odczytać plik z pamięci wewnętrznej. Użyj poniższego kodu

private void loadImageFromStorage(String path)
{

    try {
        File f=new File(path, "profile.jpg");
        Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
            ImageView img=(ImageView)findViewById(R.id.imgPicker);
        img.setImageBitmap(b);
    } 
    catch (FileNotFoundException e) 
    {
        e.printStackTrace();
    }

}
Brijesh Thakur
źródło
Zauważyłem, że zamieściłeś pewne komentarze, czy możesz mi pokierować, co sugerują? Jak ta o ścieżce? Czy muszę wskazywać ścieżkę, czy coś?
Usama Zafar,
1
Jak mogę uzyskać dostęp do mojego obrazu z pamięci?
Usama Zafar,
Zredagowałem odpowiedź. Dostęp do obrazu z pamięci. Jak ustawiasz obraz do swojego obrazu? Uważam, że to nic innego jak Bitmap, ta sama instancja, którą możesz przekazać do funkcji.
Brijesh Thakur,
Dlaczego nie. Zobacz funkcję, zwraca ścieżkę pliku. którego możesz użyć, aby go odzyskać i pokazać w widoku obrazu. Wpisałem również kod, aby odzyskać obraz
Brijesh Thakur
4
Naprawdę powinieneś zamknąć strumień z bloku last, a nie z wnętrza bloku try.
Kenn Cal
72
/**
 * Created by Ilya Gazman on 3/6/2016.
 */
public class ImageSaver {

    private String directoryName = "images";
    private String fileName = "image.png";
    private Context context;
    private boolean external;

    public ImageSaver(Context context) {
        this.context = context;
    }

    public ImageSaver setFileName(String fileName) {
        this.fileName = fileName;
        return this;
    }

    public ImageSaver setExternal(boolean external) {
        this.external = external;
        return this;
    }

    public ImageSaver setDirectoryName(String directoryName) {
        this.directoryName = directoryName;
        return this;
    }

    public void save(Bitmap bitmapImage) {
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(createFile());
            bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @NonNull
    private File createFile() {
        File directory;
        if(external){
            directory = getAlbumStorageDir(directoryName);
        }
        else {
            directory = context.getDir(directoryName, Context.MODE_PRIVATE);
        }
        if(!directory.exists() && !directory.mkdirs()){
            Log.e("ImageSaver","Error creating directory " + directory);
        }

        return new File(directory, fileName);
    }

    private File getAlbumStorageDir(String albumName) {
        return new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), albumName);
    }

    public static boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state);
    }

    public static boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state) ||
                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
    }

    public Bitmap load() {
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(createFile());
            return BitmapFactory.decodeStream(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

Stosowanie

  • Zapisać:

    new ImageSaver(context).
            setFileName("myImage.png").
            setDirectoryName("images").
            save(bitmap);
  • Załadować:

    Bitmap bitmap = new ImageSaver(context).
            setFileName("myImage.png").
            setDirectoryName("images").
            load();

Edytować:

Dodano ImageSaver.setExternal(boolean)obsługę zapisywania w pamięci zewnętrznej na podstawie przykładu Google .

Ilya Gazman
źródło
13
Oto kolejna przydatna metoda do umieszczenia na zajęciach:public boolean deleteFile(){ File file = createFile(); return file.delete(); }
Mikro
kiedy chcę udostępnić zapisany obraz, zwraca „Katalog nie został utworzony” i obraz jest uszkodzony. możesz mi pomóc?
A. N
czy mógłbyś dodać oświadczenie o licencji, na której ten kod jest dostępny, aby umożliwić włączenie go do projektu?
Don Park
2
@DonPark Nie ma potrzeby, każdy kod na stackoverflowis jest objęty licencją stackoverflow, możesz go używać bez obaw :)
Ilya Gazman
Próbuję to wykorzystać, ale napotykam na problemy. Jakaś pomoc dotycząca tego pytania, które zamieściłem? stackoverflow.com/questions/51276641/cannot-find-image-stored @IlyaGazman
Lion789
28

Dzisiaj przyszło mi do głowy to pytanie i tak to robię. Po prostu wywołaj tę funkcję z wymaganymi parametrami

public void saveImage(Context context, Bitmap bitmap, String name, String extension){
    name = name + "." + extension;
    FileOutputStream fileOutputStream;
    try {
        fileOutputStream = context.openFileOutput(name, Context.MODE_PRIVATE);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream);
        fileOutputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Podobnie, aby przeczytać to samo, użyj tego

public Bitmap loadImageBitmap(Context context,String name,String extension){
    name = name + "." + extension
    FileInputStream fileInputStream
    Bitmap bitmap = null;
    try{
        fileInputStream = context.openFileInput(name);
        bitmap = BitmapFactory.decodeStream(fileInputStream);
        fileInputStream.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
     return bitmap;
}
Anurag
źródło
Jak przekazać argument bdo funkcji saveImage. Umieściłem obrazy na moim urządzeniu z Androidem, ale nie mogę znaleźć ich ścieżki. Jeśli nie mogę znaleźć ich ścieżki, nie mogę przekazać ich jako argumentów do funkcji saveImage.
Autonomiczny
Mam to zdjęcie na urządzeniu. Widzę to za pomocą aplikacji eksploratora plików, a także powłoki adb, ale nie byłem w stanie uzyskać programowego adresu. Pomyślałem więc, że napiszę to za pomocą kodu, a następnie ponownie przeczytam. Czytanie jest moim ostatecznym celem, ale zawsze otrzymuję, nilgdy próbuję przeczytać to zdjęcie.
Autonomiczny
1
ok, więc kiedy mówisz, że piszesz to ponownie, przypuszczam, że masz dane obrazu w postaci mapy bitowej lub surowych danych w postaci tablicy bajtów. Jeśli masz mapę bitową, możesz bezpośrednio wykorzystać powyższe funkcje. Jeśli masz go w postaci tablicy bajtów, użyj tego, aby przekonwertować go na mapę bitową Bitmap bitmap = BitmapFactory.decodeByteArray (bitmapdata, 0, bitmapdata .length); Lub nawet jeśli jest w jakiejkolwiek innej formie, po prostu przekonwertuj go na bitmapę i użyj powyższych funkcji.
Anurag
„Edytowałem odpowiedź” z rozszerzeniem, w moim przypadku pojawiły się problemy, więc w końcu stwierdziłem, że rozszerzenie powinno być dodane jako parametr.
Naveed Ahmad
Dzięki za edycję, założyłem, że rozszerzenie będzie częścią samej nazwy.
Anurag
6

Dla użytkowników Kotlin stworzyłem ImageStorageManagerklasę, która z łatwością obsłuży zapisywanie, pobieranie i usuwanie akcji dla obrazów:

class ImageStorageManager {
    companion object {
        fun saveToInternalStorage(context: Context, bitmapImage: Bitmap, imageFileName: String): String {
            context.openFileOutput(imageFileName, Context.MODE_PRIVATE).use { fos ->
                bitmapImage.compress(Bitmap.CompressFormat.PNG, 25, fos)
            }
            return context.filesDir.absolutePath
        }

        fun getImageFromInternalStorage(context: Context, imageFileName: String): Bitmap? {
            val directory = context.filesDir
            val file = File(directory, imageFileName)
            return BitmapFactory.decodeStream(FileInputStream(file))
        }

        fun deleteImageFromInternalStorage(context: Context, imageFileName: String): Boolean {
            val dir = context.filesDir
            val file = File(dir, imageFileName)
            return file.delete()
        }
    }
}

Przeczytaj więcej tutaj

Amiraslan
źródło
Czy musisz użyć bezwzględnej ścieżki otrzymanej z saveToInternalStorage (), aby ją pobrać za pomocą getImageFromInternalStorage (), czy po prostu nazwę pliku?
Leo Droidcoder
1
Wystarczy imageFileName, żeby go odzyskać
Amiraslan,
Człowieku, zmarnowałem na to 10 godzin
Pb Studies
0
    public static String saveImage(String folderName, String imageName, RelativeLayout layoutCollage) {
        String selectedOutputPath = "";
        if (isSDCARDMounted()) {
            File mediaStorageDir = new File(
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), folderName);
            // Create a storage directory if it does not exist
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    Log.d("PhotoEditorSDK", "Failed to create directory");
                }
            }
            // Create a media file name
            selectedOutputPath = mediaStorageDir.getPath() + File.separator + imageName;
            Log.d("PhotoEditorSDK", "selected camera path " + selectedOutputPath);
            File file = new File(selectedOutputPath);
            try {
                FileOutputStream out = new FileOutputStream(file);
                if (layoutCollage != null) {
                    layoutCollage.setDrawingCacheEnabled(true);
                    layoutCollage.getDrawingCache().compress(Bitmap.CompressFormat.JPEG, 80, out);
                }
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return selectedOutputPath;
    }



private static boolean isSDCARDMounted() {
        String status = Environment.getExternalStorageState();
        return status.equals(Environment.MEDIA_MOUNTED);
    }
Anil Singhania
źródło
pytanie dotyczy pamięci wewnętrznej.
Denny Kurniawan
0

// pobieranie wielu obrazów

 File folPath = new File(getIntent().getStringExtra("folder_path"));
 File[] imagep = folPath.listFiles();

 for (int i = 0; i < imagep.length ; i++) {
     imageModelList.add(new ImageModel(imagep[i].getAbsolutePath(), Uri.parse(imagep[i].getAbsolutePath())));
 }
 imagesAdapter.notifyDataSetChanged();
Poznaj Bhavsara
źródło