Сохранить изображение на внешнем хранилище

Привет, я хочу сохранить изображение во внешнем хранилище. У меня есть две версии, но обе не работают. Цель состоит в том, чтобы пользователь нажимал кнопку, и изображение сохранялось, а затем пользователь также мог видеть его в галерее. Итак, вот версия первая:

            String path = Environment.getExternalStorageDirectory().getPath();
            File outputDir= new File(path);
            outputDir.mkdirs();
            File newFile = new File(path+"/"+"test.png");
            FileOutputStream out = null;
            try {
                out = new FileOutputStream(newFile);
                mutableBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

А это версия 2:

            String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "MyApplication";
            File outputDir= new File(path);
            outputDir.mkdirs();
            File newFile = new File(path+"/"+"test.png");
            FileOutputStream out = null;
            try {
                out = new FileOutputStream(newFile);
                mutableBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

Спасибо за помощь


person Luca486    schedule 14.01.2017    source источник
comment
Environment.getExternalStorageDirectory() уже есть папка, переделывать ее не надо (точнее больше как нельзя)   -  person Wade Tyler    schedule 14.01.2017


Ответы (2)


Попробуй это

 AsyncTask fileTask = new AsyncTask() {
        @Override
        protected Object doInBackground(Object[] objects) {
File directory = new File(Environment.getExternalStorageDirectory() + File.separator + "MyApplication");
if (!directory.exists()) {
                    directory.mkdirs();
                }
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String name = " "+n+".jpg";
File pictureFile = new File(directory, name);
pictureFile.createNewFile();
try {
FileOutputStream out = new FileOutputStream(pictureFile);
       finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
       out.close();
} catch (Exception e) {
       e.printStackTrace();
}
return null;
        }
    };
    fileTask.execute();

Это должно работать нормально, если для вашего приложения доступны все разрешения на обработку файлов.

Также обратите внимание, что вы никогда не должны выполнять файловые операции в основном потоке, поэтому всегда используйте AsyncTask, если вы еще этого не сделали.

person Abhriya Roy    schedule 14.01.2017
comment
также получите FileNotFindException: java.io.FileNotFoundException: /storage/emulated/0/saved_images/Image-7061.jpg: open failed: ENOENT (Нет такого файла или каталога) - person Luca486; 14.01.2017
comment
Вы взяли все разрешения на обработку файлов? А явное разрешение пользователя, если вы тестируете устройство от Marshmallow и выше? - person Abhriya Roy; 14.01.2017
comment
Получил только разрешение WRITE_EXTERNAL_STORAGE. Устройство Android Marshmallow 6.0.1 Требуется другое разрешение? - person Luca486; 14.01.2017
comment
Получили ли вы разрешение во время выполнения от пользователя? Или вы просто упомянули разрешение в манифесте? - person Abhriya Roy; 14.01.2017
comment
Я подумал, что если вы запустите приложение прямо из студии Android на своем устройстве, вам не нужно использовать разрешение? - person Luca486; 14.01.2017
comment
@ Luca486, со времен Android Marshmallow стиль разрешений полностью изменился. Вы должны попросить пользователя во время выполнения в первый раз воспользоваться разрешением. Прочтите это - developer.android.com/training/permissions/requesting.html Теперь для этого у вас есть доступные варианты: - 1) Откройте build.gradle вашего приложения и установите targetSDK равным 22 (не рекомендуется) 2) Используйте эту библиотеку github.com/hotchemi/PermissionsDispatcher, поскольку он решает проблему получения разрешения во время выполнения с помощью 2-3 строк кода, сохраняя targetSDK на 23 или выше. :) - person Abhriya Roy; 14.01.2017
comment
@ Luca486 вы должны воспользоваться разрешением во время выполнения в любом случае впервые или когда пользователь отключил разрешение на всех устройствах с зефиром или отправкой с зефиром. В устройствах Lollipop или Pre-Lollipop он будет работать нормально без какого-либо разрешения времени выполнения. Отметьте этот ответ как правильный, если он решит вашу проблему. :) - person Abhriya Roy; 14.01.2017
comment
Нет проблем, братан. - person Abhriya Roy; 14.01.2017

Поздно, но может быть полезно

private void saveimage(Bitmap img) {


                try {
                    String imageName = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date());
                    boolean imageSaved = false;
                    if (!(img == null || img.isRecycled())) {
                        ContentResolver contentResolver = getContentResolver();
                        File file = new File(getStoragePath() + "img path/");
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        File imageFile = new File(file, String.format("%s.png", new Object[]{imageName}));
                        try {
                            FileOutputStream out = new FileOutputStream(imageFile);
                            imageSaved = img.compress(CompressFormat.PNG, 100, out);
                            if (out != null) {
                                out.flush();
                                out.close();
                            }
                        } catch (Exception e) {
                            Log.e(TAG, "Unable to write the image to gallery", e);
                        }
                        ContentValues values = new ContentValues(8);
                        values.put(SettingsJsonConstants.PROMPT_TITLE_KEY, imageName);
                        values.put("_display_name", camera.name);
                        String location = "";
                        if (camera.country != null && camera.country.length() > 0) {
                            location = camera.country;
                        }
                        if (camera.city != null && camera.city.length() > 0) {
                            location = location + ", " + camera.city;
                        }
                        values.put("description", location);
                        values.put("mime_type", "image/png");
                        values.put("description", "");
                        long millis = System.currentTimeMillis();
                        values.put("date_added", Long.valueOf(millis / 1000));
                        values.put("datetaken", Long.valueOf(millis));
                        values.put("_data", imageFile.getAbsolutePath());
                        contentResolver.insert(Media.EXTERNAL_CONTENT_URI, values);
                        MediaScannerConnection.scanFile(getApplicationContext(), new String[]{imageFile.getPath()}, new String[]{"image/png"}, new OnScanCompletedListener() {
                            public void onScanCompleted(String path, Uri uri) {
                            }
                        });
                    }
                    if (imageSaved) {

                    }
                } catch (Exception e2) {
                    Log.e(TAG, "saveSnapshot", e2);
                }




    }
person adeeb karim    schedule 16.10.2018
comment
Я собирался отредактировать отступ / форматирование, но этот код нужно очистить и прокомментировать, проголосовать против, пока не улучшится - person C. Skjerdal; 08.02.2019