Android studio сохранить как картинку
Перейти к содержимому

Android studio сохранить как картинку

  • автор:

ImageView

Компонент ImageView предназначен для отображения изображений. Находится в разделе Widgets.

Для загрузки изображения в XML-файле используется атрибут android:src, в последнее время чаще используется атрибут app:srcCompat.

ImageView является базовым элементом-контейнером для использования графики. Можно загружать изображения из разных источников, например, из ресурсов программы, контент-провайдеров. В классе ImageView существует несколько методов для загрузки изображений:

  • setImageResource(int resId) — загружает изображение по идентификатору ресурса
  • setImageBitmap(Bitmap bitmap) — загружает растровое изображение
  • setImageDrawable(Drawable drawable) — загружает готовое изображение
  • setImageURI(Uri uri) — загружает изображение по его URI

Метод setImageResource()

Сначала нужно получить ссылку на ImageView, а затем используется идентификатор изображения из ресурсов:

 ImageView imageView = findViewById(R.id.imageView); imageView.setImageResource(R.drawable.cat); 

Метод setImageBitmap()

Используется класс BitmapFactory для чтения ресурса изображения в объект Bitmap, а затем в ImageView указывается полученный Bitmap. Могут быть и другие варианты.

 ImageView imageView = findViewById(R.id.imageView); imageView.setImageBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.cat)); // Kotlin val bitmap: Bitmap = (ResourcesCompat.getDrawable( resources,R.drawable.sleepbedcat,null) as BitmapDrawable).bitmap imageView.setImageBitmap(bitmap) 

Метод setImageDrawable()

Если у вас есть готовое изображение, например, на SD-карте, то его можно использовать в качестве объекта Drawable.

 ImageView imageView = findViewById(R.id.imageView); // плохой код, только для демонстрации imageView.setImageDrawable(Drawable.createFromPath("/mnt/sdcard/cat.jpg")); 

Drawable можно получить и из ресурсов, хотя такой код выглядит избыточным, если можно сразу вызвать setImageResource().

 // Kotlin val imageView: ImageView = findViewById(R.id.imageView) imageView.setImageDrawable( ContextCompat.getDrawable(this, R.drawable.cat) ) 

Метод setImageURI()

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

 ImageView imageView = findViewById(R.id.imageView); imageView.setImageURI(URI.parse("file://mnt/sdcard/cat.jpg")); 

Загружаем Drawable через URI.

 // Kotlin val imageView: ImageView = findViewById(R.id.imageView) val button: Button = findViewById(R.id.button) button.setOnClickListener < val uri: Uri = Uri.parse("android.resource://$packageName/$") // remove previous image uri cache imageView.setImageURI(null) // set image view image from uri imageView.setImageURI(uri) // show the uri in text view textView.text = uri.toString() > 

Другие методы

Также вам часто придется использовать методы, связанные с размерами и масштабированием: setMaxHeight(), setMaxWidth(), getMinimunHeight(), getMinimunWidth(), getScaleType(), setScaleType().

Масштабирование через свойство Scale Type

Для масштабирования картинки в ImageView есть свойство Scale Type и соответствующий ему атрибут android:scaleType и перечисление ImageView.ScaleType.

  • CENTER
  • CENTER_CROP
  • CENTER_INSIDE
  • FIT_CENTER
  • FIT_START
  • FIT_END
  • FIT_XY
  • MATRIX

Чтобы увидеть разницу между разными режимами, желательно использовать большую картинку, превосходящую по ширине экрана устройства. Допустим, у нас есть простенькая разметка:

Для наглядности я задал красный цвет для фона ImageView.

Режим android:scaleType=»center» выводит картинку в центре без масштабирования. Если у вас будет картинка большего размера, то края могут быть обрезаны.

center

Режим android:scaleType=»centerCrop» также размещает картинку в центре, но учитывает ширину или высоту контейнера. Режим попытается сделать так, чтобы ширина (или высота) картинки совпала с шириной (или высотой) контейнера, а остальное обрезается.

centerCrop

Режим android:scaleType=»centerInside» масштабирует картинку, сохраняя пропорции. Можно увидеть задний фон контейнера, если его размеры отличаются от размера картинки.

centerInside

Режим android:scaleType=»fitCenter» (по умолчанию) похож на предыдущий, но может не сохранять пропорции.

Если выбрать режим android:scaleType=»fitStart», то картинка прижимается к левому верхнему углу и таким образом заполняет верхнюю половину контейнера.

fitStart

Значение android:scaleType=»fitEnd» сместит картинку в нижнюю часть контейнера.

Режим android:scaleType=»fitXY» растягивает/сжимает картинку, чтобы подогнать её к контейнеру. Может получиться вытянутая картинка, поэтому будьте осторожны.

Последний атрибут android:scaleType=»matrix» вывел картинку без изменений в левом верхнем углу с обрезанными краями.

Атрибут android:adjustViewBounds=»true»

При использовании атрибута scaleType=»fitCenter» из предыдущего примера Android вычисляет размеры самой картинки, игнорируя размеры ImageView. В этом случае ваша разметка может «поехать». Атрибут adjustViewBounds заставляет картинку подчиниться размеру компонента-контейнера. В некоторых случаях это может не сработать, например, если у ImageView установлен атрибут layout_width=»0dip». В таком случае поместите ImageView в RelativeLayout или FrameLayout и используйте значение 0dip для этих контейнеров.

Загрузка изображения из галереи

Предположим, у вас есть на экране компонент ImageView, и вы хотите загрузить в него какое-нибудь изображение из галереи по нажатию кнопки:

 static final int GALLERY_REQUEST = 1; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); startActivityForResult(photoPickerIntent, GALLERY_REQUEST); >>); > @Override protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) < super.onActivityResult(requestCode, resultCode, imageReturnedIntent); Bitmap bitmap = null; ImageView imageView = (ImageView) findViewById(R.id.imageView); switch(requestCode) < case GALLERY_REQUEST: if(resultCode == RESULT_OK)< Uri selectedImage = imageReturnedIntent.getData(); try < bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage); >catch (IOException e) < e.printStackTrace(); >imageView.setImageBitmap(bitmap); > > > 

Намерение ACTION_PICK вызывает отображение галереи всех изображений, хранящихся на телефоне, позволяя выбрать одно изображение. При этом возвращается адрес URI, определяющий местоположение выбранного изображения. Для его получения используется метод getData(). Далее для преобразования URI-адреса в соответствующий экземпляр класса Bitmap используется специальный метод Media.getBitmap(). И у нас появляется возможность установить изображение в ImageView при помощи setImageBitmap().

На самом деле можно поступить ещё проще и использовать метод setImageURI.

 Uri selectedImage = imageReturnedIntent.getData(); imageView.setImageURI(selectedImage); 

Сравните с предыдущим примером — чувствуете разницу? Тем не менее, приходится часто наблюдать подобный избыточный код во многих проектах. Это связано с тем, что метод порой кэширует адрес и не происходит изменений. Рекомендуется использовать инструкцию setImageURI(null) для сброса кэша и повторный вызов метода с нужным Uri.

В последних версиях системных эмуляторов два примера не работают. Проверяйте на реальных устройствах.

Получить размеры ImageView — будьте осторожны

У элемента ImageView есть два метода getWidth() и getHeight(), позволяющие получить его ширину и высоту. Но если вы попробуете вызвать указанные методы сразу в методе onCreate(), то они возвратят нулевые значения. Можно добавить кнопку и вызвать данные методы через нажатие, тогда будут получены правильные результаты. Либо использовать другой метод активности, который наступает позже.

 @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ImageView imageView = findViewById(R.id.imageView); final TextView infoTextView = findViewById(R.id.textView); // пробуем получить размеры ImageView сразу при загрузке. Вернёт нулевые значения infoTextView.setText("Размеры ImageView: " + String.valueOf(imageView.getWidth()) + " : " + String.valueOf(imageView.getHeight())); Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < // этот же код вызывается при нажатии кнопки. Теперь всё правильно infoTextView.setText("Размеры ImageView: " + String.valueOf(imageView.getWidth()) + " : " + String.valueOf(imageView.getHeight())); >>); > 

Копирование изображений между ImageView

Если вам надо скопировать изображение из одного ImageView в другой, то можно получить объект Drawable через метод getDrawable() и присвоить ему второму компоненту.

 ImageView ivSource = findViewById(R.id.sourceImageView); // 1-й компонент с какой-то картинкой ImageView ivTarget = findViewById(R.id.targetImageView); // 2-й компонент без картинки Drawable drawable = ivSource.getDrawable(); // получим картинку у первого компонента ivTarget.setImageDrawable(drawable); // присвоим второму 

Примеры

В моих статьях можно найти примеры использования ImageView.

Библиотеки

CustomShapeImageView — позволяет создавать рамки разных форм.

MikeOrtiz/TouchImageView — расширенный вариант ImageView, который поддерживает касания экрана и масштабирование.

CircleImageView — компонент для создания круглых аватаров. Другая библиотека с похожим названием Pkmmte/CircularImageView. И ещё одна библиотека vinc3m1/RoundedImageView, позволяющая создавать не только круглые изображения, но и овальные и прямоугольные с закруглёнными углами. Сравнивайте. А также упрощённый компонент pavlospt/CircleView, который позволяет создавать круглый элемент с заголовком и подзаголовком.

Работа с изображениями

Одним из наиболее распространенных источников ресурсов являются файлы изображений. Android поддерживает следующие форматы файлов: .png (предпочтителен), .jpg (приемлем), .gif (нежелателен). Для графических файлов в проекте уже по умолчанию создана папка res/drawable . По умолчанию она уже содержит ряд файлов — пару файлов иконок:

Работа с изображениями в Android

При добавлении графических файлов в эту папку для каждого из них Android создает ресурс Drawable . После этого мы можем обратиться к ресурсу следующим образом в коде Java:

R.drawable.имя_файла
@[имя_пакета:]drawable/имя_файла

Например, добавим в проект в папку res/drawable какой-нибудь файл изображения. Для этого скопируем на жестком диске какой-нибудь файл с расширением png или jpg и вставим его в папку res/drawable (для копирования в проект используется простой Copy-Paste)

Далее нам будет предложено выбрать папку — drawable или drawable-24 . Для добавления обычных файлов изображений выберем drawable :

Добавление изображений в папку drawable Android Studio

Здесь сразу стоит учесть, что файл изображения будет добавляться в приложение, тем самым увеличивая его размер. Кроме того, большие изображения отрицательно влияют на производительность. Поэтому лучше использовать небольшие и оптимизрованные (сжатые) графические файлы. Хотя, также стоит отметить, что все файлы изображений, которые добавляются в эту папку, могут автоматически оптимизироваться с помощью утилиты aapt во время построения проекта. Это позволяет уменьшить размер файла без потери качества.

При копировании файла нам будет предложено установить для него новое имя.

Ресурсы drawable в Android и Java

Можно изменить название файла, а можно оставить так как есть. В моем случае файл называется dubi2.png . И затем нажмем на кнопку Refactor. И после этого в папку drawable будет добавлен выбранный нами файл изображения.

Добавление изображений в Android Studio

Для работы с изображениями в Android можно использовать различные элементы, но непосредственно для вывода изображений предназначен ImageView . Поэтому изменим файл activity_main.xml следующим образом:

В данном случае для отображения файла в ImageView у элемента устанавливается атрибут android:src . В его значении указывается имя графического ресурса, которое совпадает с именем файла без расширения. И после этого уже в Preview или в режиме дизайнере в Android Studio можно будет увидеть применение изображения, либо при запуске приложения:

ImageView и drawable в Android Studio и Java

Если бы мы создавали ImageView в коде java и из кода применяли бы ресурс, то activity могла бы выглядеть так:

package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import android.os.Bundle; import android.widget.ImageView; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); ConstraintLayout constraintLayout = new ConstraintLayout(this); ImageView imageView = new ImageView(this); // применяем ресурс imageView.setImageResource(R.drawable.dubi2); ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams (ConstraintLayout.LayoutParams.WRAP_CONTENT , ConstraintLayout.LayoutParams.WRAP_CONTENT); layoutParams.leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID; layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; imageView.setLayoutParams(layoutParams); constraintLayout.addView(imageView); setContentView(constraintLayout); >>

В данном случае ресурс drawable напрямую передается в метод imageView.setImageResource() , и таким образом устанавливается изображение. В результате мы получим тот же результат.

imageView.setImageResource(R.drawable.dubi2);

Однако может возникнуть необходимость как-то обработать ресурс перед использованием или использовать его в других сценариях. В этом случае мы можем сначала получить его как объект Drawable и затем использовать для наших задач:

package com.example.viewapp; import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.res.ResourcesCompat; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.widget.ImageView; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); ConstraintLayout constraintLayout = new ConstraintLayout(this); ImageView imageView = new ImageView(this); Resources res = getResources(); Drawable drawable = ResourcesCompat.getDrawable(res, R.drawable.dubi2, null); // применяем ресурс imageView.setImageDrawable(drawable); ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams (ConstraintLayout.LayoutParams.WRAP_CONTENT , ConstraintLayout.LayoutParams.WRAP_CONTENT); layoutParams.leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID; layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; imageView.setLayoutParams(layoutParams); constraintLayout.addView(imageView); setContentView(constraintLayout); >>

Для получения ресурса применяется метод ResourcesCompat.getDrawable() , в который передается объект Resources, идентификатор ресурса и тема. В данном случае тема нам не важна, поэтому для нее передаем значение null. Возвращается ресурс в виде объекта Drawable :

Drawable drawable = ResourcesCompat.getDrawable(res, R.drawable.dubi2, null);

Затем, например, можно также передать ресурс объекту ImageView через его метод setImageDrawable()

imageView.setImageDrawable(drawable);

Пишем функцию сохранения картинок на SD-карту

В процессе написания приложения для андроида у меня возникла задача сохранять произвольное изображение в файл на флешке. В этой статье я опишу, как я решил эту проблему, какие трудности встретились мне в процессе, и как они были решены. Хотелось бы отдельно отметить, что я .NET программист, судьба занесла меня в Java-мир только из-за необходимости создания небольших по размеру (поэтому monodroid сразу нет) и довольно простых с точки зрения интерфейса андроид-приложений. Это означает, что я тоже только учусь, а значит буду рад любым советом и замечаниям профессионалов.

Итак, предположим, что у нас есть ImageView, в котором содержится картинка, необходимая нам в виде файла. Первый же вопрос — куда сохранять эту картинку?

Самый правильный и гуглом одобренный подход будет сохранять картинку в папку кэша специально выделенную для вашей аппликации.
Получить абсолютный путь к ней можно вызовом функции:

context.getCacheDir(); 

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

Есть у данного решения и минусы. Самый главный — папка кэша приложения содержится во внутренней памяти устройства, которой вечно не хватает. Рекомендуется сохранять там лишь временные и не очень большие файлы, сохранение большого количества тяжелых картинок здесь нежелательно.

Лучше воспользоваться папкой кэша приложения на SD-карте, путь к которой можно получить функцией:

context.getExternalCacheDir(); 

Данная папка тоже будет очищена при деинсталляции приложения, но ее размер не отслеживается системой, поэтому перед сохранением туда файлов, ее состояние желательно проверять командой:

Environment.getExternalStorageState(); 

В моем случае по совокупности разных факторов оба стандартных решения показались мне неоптимальными, поэтому я просто сохраняю файлы в корне SD-карты, путь туда можно получить функцией:

Environment.getExternalStorageDirectory(); 

Теперь о самой процедуре сохранения, ее код приведен ниже.

ImageView iv; // ImageView, содержащий изображение, которое нужно сохранить String folderToSave = Environment.getExternalStorageDirectory().toString(); // папка куда сохранять, в данном случае - корень SD-карты private String SavePicture(ImageView iv, String folderToSave) < OutputStream fOut = null; Time time = new Time(); time.setToNow(); try < File file = new File(folderToSave, Integer.toString(time.year) + Integer.toString(time.month) + Integer.toString(time.monthDay) + Integer.toString(time.hour) + Integer.toString(time.minute) + Integer.toString(time.second) +".jpg"); // создать уникальное имя для файла основываясь на дате сохранения fOut = new FileOutputStream(file); Bitmap bitmap = (BitmapDrawable) iv.getDrawable().getBitmap(); bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut); // сохранять картинку в jpeg-формате с 85% сжатия. fOut.flush(); fOut.close(); MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName()); // регистрация в фотоальбоме >catch (Exception e) // здесь необходим блок отслеживания реальных ошибок и исключений, общий Exception приведен в качестве примера < return e.getMessage(); >return ""; > 

Несколько пояснений по коду.

File file = new File(folderToSave, Integer.toString(time.year) + Integer.toString(time.month+1) + Integer.toString(time.monthDay) + Integer.toString(time.hour) + Integer.toString(time.minute) + Integer.toString(time.second) +".jpg"); 

Не очень изящное, но простое как карандаш и реально работающее решение получить уникальное имя для файла в формате удобном для сортировки — «2011 11 17 20 31 49.jpg»
Здесь всего одна маленькая хитрость. Обратили внимание на time.month+1?
Дело в том, что Java считает месяцы с нуля, и ноябрь получается 10м, а не 11м, как все привыкли, месяцем. Непорядок.

bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut); 

Тут тоже все самоочевидно, споры могут возникнуть лишь о процентах сжатия. Мне кажется, что 85% оптимальный вариант, но у каждого может быть свое мнение и свои условия задачи.

MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName()); 

Интересный финт, о котором многие забывают. Не все андроид-пользователи продвинуты настолько, чтобы отыскать сохраненные вами файлы, даже если вы им показали путь файловой системы. Но вот про приложение «Фотоальбом» знают точно все (это там, где только что снятые фоточки можно посмотреть). Добавьте вышеупомянутую строчку в ваш код, и картинка не только сохранится в нужную директорию, но еще и зарегистрируется в фотоальбоме, и пользователь всегда ее отыщет ее без всяких проблем.

Кстати, приведенная функция взята из реального работающего приложения Random Pictures, которое показывает случайные картинки из Интернета, а в платной версии программы — имеет возможность сохранения любой картинки к себе на флешку.

Бесплатная версия Random Picture Free на андроид маркете Random Pictures Free

Описанная функция сохранения файла работает только в платной версии. Ее цена — 45 рублей, но для хабражителей — конечно же выкладывается бесплатно. (Хорошая традиция, надо сказать!) Ссылка от автора в комментариях.

Сохранение файлов

Android использует файловую систему, похожую на систему на основе дисковых файловых систем на других платформах. Этот урок описывает, как работать с файловой системой Android, чтобы читать и записывать файлы, используя File API.

File объект подходит для чтения или записи больших объемов данных с начала до конца, не пропуская ничего вокруг. Например, это хорошо подходит для файлов изображений или для обмена чем-нибудь по сети.

Этот урок показывает, как выполнять основные задачи связанные с файлами в вашем приложении. Урок предполагает, что вы знакомы с основами файловой системы Linux и стандартным API файлового ввода/вывода в java.io .

Выберите внутреннее или внешнее хранилище

Все Android устройства имеют две области хранения файлов: “внутреннее” и “внешнее” хранилище. Эти названия пришли из первых дней Android, когда предлагалось, что большинство устройств предоставляют встроенную постоянную неизменную память (внутреннее хранилище), а также съемный носитель, такое как микро SD карта(внешнее хранилище). Некоторые устройства делят места постоянного хранения на “внутренние” и “внешние” разделы, т.е. даже без съемного носителя, всегда есть два хранилища, и поведение API для внешнего хранилища такое же, не зависимо от того, является ли оно съемным или нет. Следующие списки обобщают факты о каждом хранилище.

Внутреннее хранилище:

  • Всегда доступно.
  • Файлы, сохраненные здесь, по умолчанию, доступны лишь вашему приложению.
  • Когда пользователь удаляет ваше приложение, система удаляет все файлы вашего приложения из внутренней памяти.

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

Внешнее хранилище:

  • Не всегда доступно, так как пользователь может смонтировать внешний накопитель в качестве USB хранилища, и в некоторых случаях вынуть его из устройства.
  • Чтение разрешено всем, поэтому файлы, сохраненные здесь, можно прочитать без вашего контроля.
  • Когда пользователь удаляет ваше приложение, система удаляет файлы вашего приложения отсюда, только если вы сохраните их в каталоге из getExternalFilesDir() .

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

Полезный совет: Хотя приложения устанавливаются во внутреннее хранилище по умолчанию, можно указать android:installLocation атрибут в манифесте, чтобы ваше приложение могло быть установлено на внешний накопитель. Пользователи ценят эту опцию, когда размер APK очень большой, и у них есть внешнее пространство для хранения, превышающее внутреннюю память. Для получения дополнительной информации, см. Путь установки приложения.

Получите разрешения для внешних накопителей

Для записи на внешний накопитель, вы должны запросить WRITE_EXTERNAL_STORAGE разрешение в вашем файле манифеста:

Внимание: В настоящее время, все приложения имеют возможность читать с внешних накопителей без специального разрешения. Тем не менее, это изменится в будущем релизе. Если ваше приложение должно прочитать внешний накопитель (но не писать в него), то вам нужно будет объявить READ_EXTERNAL_STORAGE разрешение. Чтобы убедиться, что ваше приложение продолжало работать, как и ожидалось, вы должны объявить это разрешение сейчас, прежде чем изменения вступят в силу.

Однако, если ваше приложение использует WRITE_EXTERNAL_STORAGE разрешение, то также неявно имеет разрешение на чтение внешнего хранилища.

Вам не нужно никаких разрешений для сохранения файлов во внутреннее хранилище. Ваше приложение всегда имеет разрешение на чтение и запись файлов в каталоге внутреннего хранилища.

Сохраните файл во внутреннем хранилище

При сохранении файла во внутреннее хранилище, вы можете запросить соответствующий каталог, в виде объекта File , вызвав один из двух методов:

getFilesDir() Возвращает File представляющий собой внутренний каталог вашего приложения. getCacheDir() Возвращает File представляющий собой внутренний каталог для временных файлов кэша вашего приложения. Будьте уверены, удалять файлы по одному больше не нужено, и реализуйте разумный предел размера объема памяти, который вы будете использовать в какой-либо момент времени, например, 1 Мб. Если в системе возникает нехватка места, она может удалить ваши файлы кэша без предупреждения.

Чтобы создать новый файл в одном из этих каталогов, вы можете использовать File() конструктор, передав File предоставленный одним из выше указанных методов, который указывает на ваш внутренний каталог. Например:

File file = new File(context.getFilesDir(), filename);

В качестве альтернативы, вы можете вызвать openFileOutput() для получения FileOutputStream , который пишет в файл в вашем внутреннем каталоге. Например, вот как записать текст в файл:

String filename = «myfile»; String string = «Hello world!»; FileOutputStream outputStream; try < outputStream = openFileOutput(filename, Context.MODE_PRIVATE); outputStream.write(string.getBytes()); outputStream.close(); >catch (Exception e)

Или, если вам нужно кэшировать некоторые файлы, то следует использовать createTempFile() . Например, следующий метод извлекает имя файла из URL и создает файл с таким же именем во внутренней каталоге кэша вашего приложения:

public File getTempFile(Context context, String url) < File file; try < String fileName = Uri.parse(url).getLastPathSegment(); file = File.createTempFile(fileName, null, context.getCacheDir()); catch (IOException e) < // Error while creating file >return file; >

Примечание: Каталог внутреннего хранилища вашего приложения использует имя пакета вашего приложения, располагаясь в специальном месте файловой системы Android. Технически, другое приложение может читать ваши внутренние файлы, если вы установите для файла режим доступа на чтение. Тем не менее, другие приложения также должны знать ваше имя пакета и имена файлов. Другие приложения не могут просматривать ваши внутренние каталоги, и не имеют доступа для чтения или записи, если явно не установить разрешения для чтения или записи. Так что, пока вы используете MODE_PRIVATE для ваших файлов во внутренней памяти, они не являются доступными для других приложений.

Сохраните файл на внешнем накопителе

Поскольку внешнее хранилище может быть недоступно — например, когда пользователь монтируется хранилище к ПК, или вынул SD карту, которая обеспечивает внешнее хранилище — вы всегда должны убедиться, что раздел доступен перед доступом к нему. Вы можете запросить состояния внешнего хранилища, вызвав getExternalStorageState() . Если возвращенное состояние равно MEDIA_MOUNTED , то вы можете читать и писать файлы. Например, следующие методы полезны для определения доступности хранилища:

/* Checks if external storage is available for read and write */ public boolean isExternalStorageWritable() < String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) < return true; >return false; > /* Checks if external storage is available to at least read */ public boolean isExternalStorageReadable() < String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) < return true; >return false; >

Хотя внешнее запоминающее устройство может изменяться пользователем и другими приложениями, есть две категории файлов, которые вы могли бы сохранить здесь:

Общедоступные файлы Файлы, которые должны быть в свободном доступе для других приложений и для пользователя. Когда пользователь удаляет ваше приложение, эти файлы должны оставаться доступными для пользователя.Например, фотографии, сделанные с помощью приложения, или другие загруженные файлы. Личные файлы Файлы, которые по праву принадлежат вашему приложению, и их следует удалить, когда пользователь удаляет ваше приложение. Хотя эти файлы являются технически доступными пользователю, и другим приложениям, т.к. они находятся на внешнем накопителе, это файлы, которые реально не представляют собой ценности для пользователя вне вашего приложения. Когда пользователь удаляет ваше приложение, система удаляет все файлы с внешнего приватного каталога вашего приложения.Например, дополнительные ресурсы загруженные вашим приложения или временные медиа-файлы.

Если вы хотите сохранить общедоступные файлы на внешнем устройстве хранения, используйте getExternalStoragePublicDirectory() метод для получения File представляющего соответствующий каталог на внешнем накопителе. Метод принимает аргумент, указывающий тип файла, который вы хотите сохранить, чтобы они могли быть логически организованы с другими общедоступными файлами, такими как DIRECTORY_MUSIC или DIRECTORY_PICTURES . Например:

public File getAlbumStorageDir(String albumName) < // Get the directory for the user's public pictures directory. File file = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), albumName); if (!file.mkdirs()) < Log.e(LOG_TAG, "Directory not created"); >return file; >

Если вы хотите сохранять файлы, которые являются приватными для вашего приложения, вы можете запросить соответствующий каталог, вызвав getExternalFilesDir() и передать ему имя, указывающее тип необходимого каталога. Каждый каталог, созданный таким способом, добавляется в родительский каталог, который инкапсулирует все файлы внешнего хранилища вашего приложения, которые система удаляет, когда пользователь удаляет ваше приложение.

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

public File getAlbumStorageDir(Context context, String albumName) < // Get the directory for the app's private pictures directory. File file = new File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName); if (!file.mkdirs()) < Log.e(LOG_TAG, "Directory not created"); >return file; >

Если ни одно из предопределенных имен подкаталогов не удовлетворяет вашим файлам, вы можете вместо этого вызвать getExternalFilesDir() и передать null . При это возвращается корневой каталог для приватных каталогов вашего приложения на внешнем накопителе.

Помните, что getExternalFilesDir() создает каталог внутри каталога, который удаляется, когда пользователь удаляет ваше приложение. Если сохраненные файлы должны оставаться доступными после того как пользователь удаляет ваше приложение — например, когда ваше приложение представляет собой камеру, и пользователь захочет сохранить фотографии — то следует использовать getExternalStoragePublicDirectory() .

Независимо от того, используете ли вы getExternalStoragePublicDirectory() для файлов, которые являются общими или getExternalFilesDir() для файлов, которые являются приватными для вашего приложения, важно, что вы используете имена каталогов, предоставляемые константами API, такими как DIRECTORY_PICTURES . Эти имена каталогов гарантируют, что файлы будут интерпретироваться системой должным образом. Например, файлы, сохраненные в DIRECTORY_RINGTONES классифицируются по системе медиа сканера как мелодии звонка вместо музыки.

Запросите свободное пространство

Если вы знаете заранее, сколько данных вы будете сохранять, вы можете выяснить, есть ли в наличие достаточно места, не вызывая IOException с помощью вызова getFreeSpace() или getTotalSpace() . Эти методы предоставляют информацию о текущем доступном пространстве и общем пространстве раздела, соответственно. Эта информация также полезна, чтобы избежать заполнения раздела накопителя выше определенного порога.

Тем не менее, система не гарантирует, что вы можете записать столько байт, сколько обозначено getFreeSpace() . Если возвращаемое число на несколько МБ больше, чем размер данных, которые вы хотите сохранить, или если файловая система заполнена меньше чем на 90%, то, наверное, можно продолжить. В противном случае, вероятно, не стоит записывать в хранилище.

Примечание: Вы не обязаны проверять количество свободного места, прежде чем вы сохраняете файл. Вместо этого, вы можете попробовать записать файл, и поймать IOException если оно произойдет. Возможно, вам придется сделать так, если вы не знаете точно, сколько места нужно. Например, если вы измените кодировку файла перед сохранением путем преобразования PNG изображения в JPEG, вы не будете знать размер файла заранее.

Удаление файла

Вы всегда должны удалить файлы, которые вам больше не нужны. Самый простой способ удалить файл это вызвать delete() .

myFile.delete();

Если файл сохранен во внутреннем хранилище, вы также можете попросить Context найти и удалить файл, вызвав deleteFile() :

myContext.deleteFile(fileName);

Примечание: Когда пользователь удаляет ваше приложение, Android система удаляет следующее:

  • Все файлы, сохраненные во внутреннем хранилище
  • Все файлы, сохраненные на внешнем накопителе, используя getExternalFilesDir() .

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

Продолжение: Сохранение данных в SQL базу данных

Если не указано иное, этот контент распространяется под лицензией Creative Commons Attribution 2.5. Для получения дополнительной информации и ограничений, см. Лицензия контента.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *