Как загрузить и сохранить изображение с заданного URL-адреса в Android?
Как загрузить и сохранить изображение с заданного URL-адреса в Android?
последнее крупное обновление: 31 марта 2016 г.
TL; DR или перестаньте говорить, просто дайте мне код !!
Перейдите к концу этого сообщения, скопируйте
BasicImageDownloader
(версию javadoc здесь ) в свой проект, реализуйтеOnImageLoaderListener
интерфейс, и все готово.Примечание : хотя он
BasicImageDownloader
обрабатывает возможные ошибки и предотвратит сбой вашего приложения в случае, если что-то пойдет не так, он не будет выполнять пост-обработку (например, уменьшение размера) загруженногоBitmaps
.
Поскольку этот пост получил довольно много внимания, я решил полностью переработать его, чтобы люди не могли использовать устаревшие технологии, плохие методы программирования или просто делать глупые вещи - например, искать «хаки» для запуска сети в основном потоке или принимать все сертификаты SSL.
Я создал демонстрационный проект под названием «Image Downloader», который демонстрирует, как загрузить (и сохранить) изображение, используя мою собственную реализацию загрузчика, встроенную в Android, DownloadManager
а также некоторые популярные библиотеки с открытым исходным кодом. Вы можете просмотреть полный исходный код или скачать проект на GitHub .
Примечание . Я еще не настраивал управление разрешениями для SDK 23+ (Marshmallow), поэтому проект нацелен на SDK 22 (Lollipop).
В моем заключении в конце этого поста я поделюсь своим скромным мнением о правильном сценарии использования для каждого конкретного способа загрузки изображений, который я упомянул.
Начнем с собственной реализации (код вы найдете в конце поста). Прежде всего, это Базовый ImageDownloader и все. Все, что он делает, - это подключается к заданному URL-адресу, считывает данные и пытается декодировать их как a Bitmap
, OnImageLoaderListener
при необходимости запуская обратные вызовы интерфейса. Преимущество такого подхода - он прост и у вас есть четкое представление о том, что происходит. Хороший способ пойти, если все, что вам нужно, это загрузка / отображение и сохранение некоторых изображений, в то время как вы не заботитесь о поддержании кеша памяти / диска.
Примечание: в случае больших изображений вам может потребоваться уменьшить их масштаб .
-
Android DownloadManager - это способ позволить системе выполнять загрузку за вас. На самом деле он способен загружать любые файлы, а не только изображения. Вы можете позволить загрузке происходить незаметно и незаметно для пользователя, или вы можете позволить пользователю видеть загрузку в области уведомлений. Вы также можете зарегистрировать, BroadcastReceiver
чтобы получать уведомления после завершения загрузки. Настройка довольно проста, см. Пример кода в связанном проекте.
Использование, как DownloadManager
правило, не является хорошей идеей, если вы также хотите отобразить изображение, поскольку вам нужно будет прочитать и декодировать сохраненный файл вместо того, чтобы просто устанавливать загруженный Bitmap
в файл ImageView
. ВDownloadManager
Также не предоставляет API для вас приложения для отслеживания прогресса загрузки.
-
Теперь о самом замечательном - о библиотеках. Они могут делать гораздо больше, чем просто загружать и отображать изображения, в том числе: создавать и управлять кешем памяти / диска, изменять размер изображений, преобразовывать их и многое другое.
Я начну с Volley , мощной библиотеки, созданной Google и покрытой официальной документацией. Будучи сетевой библиотекой общего назначения, не специализирующейся на изображениях, Volley имеет довольно мощный API для управления изображениями.
Вам нужно будет реализовать класс Singleton для управления запросами Volley, и все готово.
Возможно, вы захотите заменить ваш ImageView
на Volley NetworkImageView
, так что загрузка в основном становится однострочным:
((NetworkImageView) findViewById(R.id.myNIV)).setImageUrl(url, MySingleton.getInstance(this).getImageLoader());
Если вам нужно больше контроля, вот как выглядит создание с ImageRequest
помощью Volley:
ImageRequest imgRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
//do stuff
}
}, 0, 0, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888,
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//do stuff
}
});
Стоит отметить, что Volley имеет отличный механизм обработки ошибок, предоставляя VolleyError
класс, который помогает вам определить точную причину ошибки. Если ваше приложение много работает в сети и управление изображениями не является его основной целью, тогда Volley идеально вам подойдет.
-
Square's Picasso - это хорошо известная библиотека, которая сделает за вас всю загрузку изображений. Просто отобразить изображение с помощью Picasso так же просто, как:
Picasso.with(myContext)
.load(url)
.into(myImageView);
По умолчанию Picasso управляет кешем диска / памяти, поэтому вам не о чем беспокоиться. Для большего контроля вы можете реализоватьTarget
интерфейс и использовать его для загрузки изображения - это обеспечит обратные вызовы, аналогичные примеру Volley. Посмотрите демонстрационный проект для примеров.
Picasso также позволяет применять преобразования к загруженному изображению, и есть даже другие библиотеки , расширяющие этот API. Также очень хорошо работает в RecyclerView
/ ListView
/ GridView
.
-
Universal Image Loader - еще одна очень популярная библиотека, служащая для управления изображениями. Он использует свой собственный, ImageLoader
который (после инициализации) имеет глобальный экземпляр, который можно использовать для загрузки изображений в одной строке кода:
ImageLoader.getInstance().displayImage(url, myImageView);
Если вы хотите отслеживать прогресс загрузки или получить доступ к загруженному Bitmap
:
ImageLoader.getInstance().displayImage(url, myImageView, opts,
new ImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
//do stuff
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
//do stuff
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
//do stuff
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
//do stuff
}
}, new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri, View view, int current, int total) {
//do stuff
}
});
opts
Аргумент в этом примере является DisplayImageOptions
объектом. Обратитесь к демонстрационному проекту, чтобы узнать больше.
Подобно Volley, UIL предоставляет FailReason
класс, который позволяет вам проверить, что пошло не так при сбое загрузки. По умолчанию UIL поддерживает кэш памяти / диска, если вы явно не указали ему этого не делать.
Примечание : автор упомянул, что с 27 ноября 2015 года он больше не поддерживает проект. Но, поскольку участников много, мы можем надеяться, что Universal Image Loader продолжит свое существование.
-
Facebook Fresco - новейшая и (IMO) самая продвинутая библиотека, которая выводит управление изображениями на новый уровень: от сохранения Bitmaps
кучи java (до Lollipop) до поддержки анимированных форматов и потоковой передачи прогрессивного JPEG. .
Чтобы узнать больше об идеях и методах, лежащих в основе Fresco, прочтите этот пост .
Основное использование довольно простое. Обратите внимание, что вам нужно позвонить Fresco.initialize(Context);
только один раз, желательно в Application
классе. Инициализация Fresco более одного раза может привести к непредсказуемому поведению и ошибкам OOM.
Fresco использует Drawee
s для отображения изображений, вы можете думать о них как о ImageView
s:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/drawee"
android:layout_width="match_parent"
android:layout_height="match_parent"
fresco:fadeDuration="500"
fresco:actualImageScaleType="centerCrop"
fresco:placeholderImage="@drawable/placeholder_grey"
fresco:failureImage="@drawable/error_orange"
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImageScaleType="centerInside"
fresco:retryImageScaleType="centerCrop"
fresco:progressBarImageScaleType="centerInside"
fresco:progressBarAutoRotateInterval="1000"
fresco:roundAsCircle="false" />
Как видите, многие вещи (включая параметры преобразования) уже определены в XML, поэтому все, что вам нужно сделать для отображения изображения, - это однострочник:
mDrawee.setImageURI(Uri.parse(url));
Fresco предоставляет расширенный API настройки, который при определенных обстоятельствах может быть довольно сложным и требует от пользователя внимательного прочтения документации (да, иногда требуется RTFM).
Я включил в образец проекта примеры для прогрессивных JPEG и анимированных изображений.
Обратите внимание, что следующий текст отражает мое личное мнение и не должен восприниматься как постулат.
Recycler-/Grid-/ListView
и вам не нужна целая куча изображений для отображения, BasicImageDownloader должен соответствовать вашим потребностям.JSON
данные, работает с изображениями, но это не основная цель приложения, используйте Volley .Если вы пропустили это, ссылка Github для демонстрационного проекта.
А вот BasicImageDownloader.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Set;
public class BasicImageDownloader {
private OnImageLoaderListener mImageLoaderListener;
private Set<String> mUrlsInProgress = new HashSet<>();
private final String TAG = this.getClass().getSimpleName();
public BasicImageDownloader(@NonNull OnImageLoaderListener listener) {
this.mImageLoaderListener = listener;
}
public interface OnImageLoaderListener {
void onError(ImageError error);
void onProgressChange(int percent);
void onComplete(Bitmap result);
}
public void download(@NonNull final String imageUrl, final boolean displayProgress) {
if (mUrlsInProgress.contains(imageUrl)) {
Log.w(TAG, "a download for this url is already running, " +
"no further download will be started");
return;
}
new AsyncTask<Void, Integer, Bitmap>() {
private ImageError error;
@Override
protected void onPreExecute() {
mUrlsInProgress.add(imageUrl);
Log.d(TAG, "starting download");
}
@Override
protected void onCancelled() {
mUrlsInProgress.remove(imageUrl);
mImageLoaderListener.onError(error);
}
@Override
protected void onProgressUpdate(Integer... values) {
mImageLoaderListener.onProgressChange(values[0]);
}
@Override
protected Bitmap doInBackground(Void... params) {
Bitmap bitmap = null;
HttpURLConnection connection = null;
InputStream is = null;
ByteArrayOutputStream out = null;
try {
connection = (HttpURLConnection) new URL(imageUrl).openConnection();
if (displayProgress) {
connection.connect();
final int length = connection.getContentLength();
if (length <= 0) {
error = new ImageError("Invalid content length. The URL is probably not pointing to a file")
.setErrorCode(ImageError.ERROR_INVALID_FILE);
this.cancel(true);
}
is = new BufferedInputStream(connection.getInputStream(), 8192);
out = new ByteArrayOutputStream();
byte bytes[] = new byte[8192];
int count;
long read = 0;
while ((count = is.read(bytes)) != -1) {
read += count;
out.write(bytes, 0, count);
publishProgress((int) ((read * 100) / length));
}
bitmap = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.size());
} else {
is = connection.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
}
} catch (Throwable e) {
if (!this.isCancelled()) {
error = new ImageError(e).setErrorCode(ImageError.ERROR_GENERAL_EXCEPTION);
this.cancel(true);
}
} finally {
try {
if (connection != null)
connection.disconnect();
if (out != null) {
out.flush();
out.close();
}
if (is != null)
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
if (result == null) {
Log.e(TAG, "factory returned a null result");
mImageLoaderListener.onError(new ImageError("downloaded file could not be decoded as bitmap")
.setErrorCode(ImageError.ERROR_DECODE_FAILED));
} else {
Log.d(TAG, "download complete, " + result.getByteCount() +
" bytes transferred");
mImageLoaderListener.onComplete(result);
}
mUrlsInProgress.remove(imageUrl);
System.gc();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public interface OnBitmapSaveListener {
void onBitmapSaved();
void onBitmapSaveError(ImageError error);
}
public static void writeToDisk(@NonNull final File imageFile, @NonNull final Bitmap image,
@NonNull final OnBitmapSaveListener listener,
@NonNull final Bitmap.CompressFormat format, boolean shouldOverwrite) {
if (imageFile.isDirectory()) {
listener.onBitmapSaveError(new ImageError("the specified path points to a directory, " +
"should be a file").setErrorCode(ImageError.ERROR_IS_DIRECTORY));
return;
}
if (imageFile.exists()) {
if (!shouldOverwrite) {
listener.onBitmapSaveError(new ImageError("file already exists, " +
"write operation cancelled").setErrorCode(ImageError.ERROR_FILE_EXISTS));
return;
} else if (!imageFile.delete()) {
listener.onBitmapSaveError(new ImageError("could not delete existing file, " +
"most likely the write permission was denied")
.setErrorCode(ImageError.ERROR_PERMISSION_DENIED));
return;
}
}
File parent = imageFile.getParentFile();
if (!parent.exists() && !parent.mkdirs()) {
listener.onBitmapSaveError(new ImageError("could not create parent directory")
.setErrorCode(ImageError.ERROR_PERMISSION_DENIED));
return;
}
try {
if (!imageFile.createNewFile()) {
listener.onBitmapSaveError(new ImageError("could not create file")
.setErrorCode(ImageError.ERROR_PERMISSION_DENIED));
return;
}
} catch (IOException e) {
listener.onBitmapSaveError(new ImageError(e).setErrorCode(ImageError.ERROR_GENERAL_EXCEPTION));
return;
}
new AsyncTask<Void, Void, Void>() {
private ImageError error;
@Override
protected Void doInBackground(Void... params) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(imageFile);
image.compress(format, 100, fos);
} catch (IOException e) {
error = new ImageError(e).setErrorCode(ImageError.ERROR_GENERAL_EXCEPTION);
this.cancel(true);
} finally {
if (fos != null) {
try {
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onCancelled() {
listener.onBitmapSaveError(error);
}
@Override
protected void onPostExecute(Void result) {
listener.onBitmapSaved();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public static Bitmap readFromDisk(@NonNull File imageFile) {
if (!imageFile.exists() || imageFile.isDirectory()) return null;
return BitmapFactory.decodeFile(imageFile.getAbsolutePath());
}
public interface OnImageReadListener {
void onImageRead(Bitmap bitmap);
void onReadFailed();
}
public static void readFromDiskAsync(@NonNull File imageFile, @NonNull final OnImageReadListener listener) {
new AsyncTask<String, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(String... params) {
return BitmapFactory.decodeFile(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null)
listener.onImageRead(bitmap);
else
listener.onReadFailed();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, imageFile.getAbsolutePath());
}
public static final class ImageError extends Throwable {
private int errorCode;
public static final int ERROR_GENERAL_EXCEPTION = -1;
public static final int ERROR_INVALID_FILE = 0;
public static final int ERROR_DECODE_FAILED = 1;
public static final int ERROR_FILE_EXISTS = 2;
public static final int ERROR_PERMISSION_DENIED = 3;
public static final int ERROR_IS_DIRECTORY = 4;
public ImageError(@NonNull String message) {
super(message);
}
public ImageError(@NonNull Throwable error) {
super(error.getMessage(), error.getCause());
this.setStackTrace(error.getStackTrace());
}
public ImageError setErrorCode(int code) {
this.errorCode = code;
return this;
}
public int getErrorCode() {
return errorCode;
}
}
}
Cursor
(вonActivityResult()
методе), а затем создание сBitmap
использованием этого пути. И да, вам не уйти от использования aFileOutputStream
и a,ByteArrayOutputStream
если вы хотите сохранить этот образ на SD.Я только что решил эту проблему, и я хотел бы поделиться полным кодом, который можно загрузить, сохранить на SD-карту (и скрыть имя файла) и получить изображения, и, наконец, он проверяет, есть ли уже изображение. URL-адрес берется из базы данных, поэтому имя файла можно легко однозначно указать с помощью идентификатора.
первая загрузка изображений
private class GetImages extends AsyncTask<Object, Object, Object> { private String requestUrl, imagename_; private ImageView view; private Bitmap bitmap ; private FileOutputStream fos; private GetImages(String requestUrl, ImageView view, String _imagename_) { this.requestUrl = requestUrl; this.view = view; this.imagename_ = _imagename_ ; } @Override protected Object doInBackground(Object... objects) { try { URL url = new URL(requestUrl); URLConnection conn = url.openConnection(); bitmap = BitmapFactory.decodeStream(conn.getInputStream()); } catch (Exception ex) { } return null; } @Override protected void onPostExecute(Object o) { if(!ImageStorage.checkifImageExists(imagename_)) { view.setImageBitmap(bitmap); ImageStorage.saveToSdCard(bitmap, imagename_); } } }
Затем создайте класс для сохранения и извлечения файлов.
public class ImageStorage { public static String saveToSdCard(Bitmap bitmap, String filename) { String stored = null; File sdcard = Environment.getExternalStorageDirectory() ; File folder = new File(sdcard.getAbsoluteFile(), ".your_specific_directory");//the dot makes this directory hidden to the user folder.mkdir(); File file = new File(folder.getAbsoluteFile(), filename + ".jpg") ; if (file.exists()) return stored ; try { FileOutputStream out = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); out.flush(); out.close(); stored = "success"; } catch (Exception e) { e.printStackTrace(); } return stored; } public static File getImage(String imagename) { File mediaImage = null; try { String root = Environment.getExternalStorageDirectory().toString(); File myDir = new File(root); if (!myDir.exists()) return null; mediaImage = new File(myDir.getPath() + "/.your_specific_directory/"+imagename); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return mediaImage; } public static boolean checkifImageExists(String imagename) { Bitmap b = null ; File file = ImageStorage.getImage("/"+imagename+".jpg"); String path = file.getAbsolutePath(); if (path != null) b = BitmapFactory.decodeFile(path); if(b == null || b.equals("")) { return false ; } return true ; } }
Затем, чтобы получить доступ к изображениям, сначала проверьте, есть ли они там, если нет, затем загрузите
if(ImageStorage.checkifImageExists(imagename)) { File file = ImageStorage.getImage("/"+imagename+".jpg"); String path = file.getAbsolutePath(); if (path != null){ b = BitmapFactory.decodeFile(path); imageView.setImageBitmap(b); } } else { new GetImages(imgurl, imageView, imagename).execute() ; }
источник
AsyncTask
преимуществ (правильное использование параметризации, параллельное выполнение ...). Пожалуйста, обратитесь к моим примерам ниже за подробностями. PS . для тех, кто может подумать, что я написал это для продвижения собственного кода по какой-то причине: нет, я просто указываю на проблемы, которые я вижу в данном примере.download
методу, особенно кdoInBackground
методу задачи, которую я использую. AnIOException
приземлится вcatch (Throwable e)
блоке, что приведет кImageError
возврату иonError()
запуску обратного вызова.ImageError
Объект будет содержать исходные трассировки стеки и причину произошлиException
Зачем вам нужен собственный код для его загрузки? Как насчет того, чтобы просто передать свой URI диспетчеру загрузок?
public void downloadFile(String uRl) { File direct = new File(Environment.getExternalStorageDirectory() + "/AnhsirkDasarp"); if (!direct.exists()) { direct.mkdirs(); } DownloadManager mgr = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE); Uri downloadUri = Uri.parse(uRl); DownloadManager.Request request = new DownloadManager.Request( downloadUri); request.setAllowedNetworkTypes( DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE) .setAllowedOverRoaming(false).setTitle("Demo") .setDescription("Something useful. No, really.") .setDestinationInExternalPublicDir("/AnhsirkDasarp", "fileName.jpg"); mgr.enqueue(request); }
источник
это может вам помочь ..
Button download_image = (Button)bigimagedialog.findViewById(R.id.btn_downloadimage); download_image.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { boolean success = (new File("/sdcard/dirname")).mkdir(); if (!success) { Log.w("directory not created", "directory not created"); } try { URL url = new URL("YOUR_URL"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.connect(); InputStream input = connection.getInputStream(); Bitmap myBitmap = BitmapFactory.decodeStream(input); String data1 = String.valueOf(String.format("/sdcard/dirname/%d.jpg",System.currentTimeMillis())); FileOutputStream stream = new FileOutputStream(data1); ByteArrayOutputStream outstream = new ByteArrayOutputStream(); myBitmap.compress(Bitmap.CompressFormat.JPEG, 85, outstream); byte[] byteArray = outstream.toByteArray(); stream.write(byteArray); stream.close(); Toast.makeText(getApplicationContext(), "Downloading Completed", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } } });
источник
У меня есть простое решение, которое отлично работает. Код не мой, нашел по этой ссылке . Вот следующие шаги:
1. Перед загрузкой изображения напишем способ сохранения растрового изображения в файл изображения во внутреннем хранилище в android. Ему нужен контекст, лучше использовать проход в контексте приложения с помощью getApplicationContext (). Этот метод можно перенести в класс Activity или в другие служебные классы.
public void saveImage(Context context, Bitmap b, String imageName) { FileOutputStream foStream; try { foStream = context.openFileOutput(imageName, Context.MODE_PRIVATE); b.compress(Bitmap.CompressFormat.PNG, 100, foStream); foStream.close(); } catch (Exception e) { Log.d("saveImage", "Exception 2, Something went wrong!"); e.printStackTrace(); } }
2. Теперь у нас есть метод сохранения растрового изображения в файл изображения в andorid, давайте напишем AsyncTask для загрузки изображений по url. Этот частный класс необходимо поместить в ваш класс Activity в качестве подкласса. После загрузки изображения в методе onPostExecute он вызывает метод saveImage, определенный выше, для сохранения изображения. Обратите внимание, имя изображения жестко запрограммировано как «my_image.png».
private class DownloadImage extends AsyncTask<String, Void, Bitmap> { private String TAG = "DownloadImage"; private Bitmap downloadImageBitmap(String sUrl) { Bitmap bitmap = null; try { InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL bitmap = BitmapFactory.decodeStream(inputStream); // Decode Bitmap inputStream.close(); } catch (Exception e) { Log.d(TAG, "Exception 1, Something went wrong!"); e.printStackTrace(); } return bitmap; } @Override protected Bitmap doInBackground(String... params) { return downloadImageBitmap(params[0]); } protected void onPostExecute(Bitmap result) { saveImage(getApplicationContext(), result, "my_image.png"); } }
3. AsyncTask для загрузки изображения определен, но нам нужно выполнить его, чтобы запустить эту AsyncTask. Для этого напишите эту строку в своем методе onCreate в своем классе Activity или в методе onClick кнопки или в других местах, которые вы считаете подходящими.
new DownloadImage().execute("http://developer.android.com/images/activity_lifecycle.png");
Изображение должно быть сохранено в /data/data/your.app.packagename/files/my_image.jpeg, проверьте этот пост, чтобы получить доступ к этому каталогу с вашего устройства.
ИМО, это решает проблему! Если вам нужны дальнейшие шаги, такие как загрузка изображения, вы можете выполнить следующие дополнительные шаги:
4. После загрузки изображения нам нужен способ загрузки растрового изображения из внутреннего хранилища, чтобы мы могли его использовать. Напишем способ загрузки растрового изображения изображения. Этот метод принимает два параметра, контекст и имя файла изображения, без полного пути, context.openFileInput (imageName) будет искать файл в каталоге сохранения, когда это имя файла было сохранено в вышеуказанном методе saveImage.
public Bitmap loadImageBitmap(Context context, String imageName) { Bitmap bitmap = null; FileInputStream fiStream; try { fiStream = context.openFileInput(imageName); bitmap = BitmapFactory.decodeStream(fiStream); fiStream.close(); } catch (Exception e) { Log.d("saveImage", "Exception 3, Something went wrong!"); e.printStackTrace(); } return bitmap; }
5. Теперь у нас есть все необходимое для установки изображения ImageView или любых других представлений, в которых вы хотите использовать изображение. Когда мы сохраняем изображение, мы жестко запрограммировали имя изображения как «my_image.jpeg», теперь мы можем передать это имя изображения в вышеуказанный метод loadImageBitmap, чтобы получить растровое изображение и установить его в ImageView.
someImageView.setImageBitmap(loadImageBitmap(getApplicationContext(), "my_image.jpeg"));
6. Получить полный путь к изображению по имени изображения.
File file = getApplicationContext().getFileStreamPath("my_image.jpeg"); String imageFullPath = file.getAbsolutePath();
7. Проверьте, существует ли файл изображения.
Файл файл =
getApplicationContext().getFileStreamPath("my_image.jpeg"); if (file.exists()) Log.d("file", "my_image.jpeg exists!");
Чтобы удалить файл изображения.
Файл file = getApplicationContext (). GetFileStreamPath ("my_image.jpeg"); if (file.delete ()) Log.d ("файл", "my_image.jpeg удален!");
источник
этот код отлично работает в моем проекте
downloadImagesToSdCard(imagepath,imagepath); private void downloadImagesToSdCard(String downloadUrl,String imageName) { try { URL url = new URL("www.xxx.com"+downloadUrl); /* making a directory in sdcard */ // String sdCard=Environment.getExternalStorageDirectory().toString(); ContextWrapper cw = new ContextWrapper(getActivity()); // path to /data/data/yourapp/app_data/imageDir File directory = cw.getDir("files", Context.MODE_PRIVATE); File myDir = new File(directory,"folder"); /* if specified not exist create new */ if(!myDir.exists()) { myDir.mkdir(); Log.v("", "inside mkdir"); } /* checks the file and if it already exist delete */ String fname = imageName; File file = new File (myDir, fname); Log.d("file===========path", ""+file); if (file.exists ()) file.delete (); /* Open a connection */ URLConnection ucon = url.openConnection(); InputStream inputStream = null; HttpURLConnection httpConn = (HttpURLConnection)ucon; httpConn.setRequestMethod("GET"); httpConn.connect(); inputStream = httpConn.getInputStream(); /*if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) { inputStream = httpConn.getInputStream(); }*/ FileOutputStream fos = new FileOutputStream(file); int totalSize = httpConn.getContentLength(); int downloadedSize = 0; byte[] buffer = new byte[1024]; int bufferLength = 0; while ( (bufferLength = inputStream.read(buffer)) >0 ) { fos.write(buffer, 0, bufferLength); downloadedSize += bufferLength; Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ; } fos.close(); Log.d("test", "Image Saved in sdcard.."); viewimage(); } catch(IOException io) { io.printStackTrace(); } catch(Exception e) { e.printStackTrace(); } } public void viewimage() { String path = serialnumber+".png"; ContextWrapper cw = new ContextWrapper(getActivity()); //path to /data/data/yourapp/app_data/dirName File directory = cw.getDir("files", Context.MODE_PRIVATE); File mypath=new File(directory,"folder/"+path); Bitmap b; try { b = BitmapFactory.decodeStream(new FileInputStream(mypath)); // b.compress(format, quality, stream) profile_image.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
источник
Попробуй это
try { Bitmap bmp = null; URL url = new URL("Your_URL"); URLConnection conn = url.openConnection(); bmp = BitmapFactory.decodeStream(conn.getInputStream()); File f = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis() + ".jpg"); if(f.exists()) f.delete(); f.createNewFile(); Bitmap bitmap = bmp; ByteArrayOutputStream bos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos); byte[] bitmapdata = bos.toByteArray(); FileOutputStream fos = new FileOutputStream(f); fos.write(bitmapdata); fos.flush(); fos.close(); Log.e(TAG, "imagepath: "+f ); } catch (Exception e) { e.printStackTrace(); }
источник
public class testCrop extends AppCompatActivity { ImageView iv; String imagePath = "https://style.pk/wp-content/uploads/2015/07/omer-Shahzad-performed-umrah-600x548.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.testcrpop); iv = (ImageView) findViewById(R.id.testCrop); imageDownload image = new imageDownload(testCrop.this, iv); image.execute(imagePath); } class imageDownload extends AsyncTask<String, Integer, Bitmap> { Context context; ImageView imageView; Bitmap bitmap; InputStream in = null; int responseCode = -1; //constructor. public imageDownload(Context context, ImageView imageView) { this.context = context; this.imageView = imageView; } @Override protected void onPreExecute() { } @Override protected Bitmap doInBackground(String... params) { try { URL url = new URL(params[0]); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setDoOutput(true); httpURLConnection.connect(); responseCode = httpURLConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { in = httpURLConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(in); in.close(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bitmap; } @Override protected void onPostExecute(Bitmap data) { imageView.setImageBitmap(data); saveImage(data); } private void saveImage(Bitmap data) { File createFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"test"); createFolder.mkdir(); File saveImage = new File(createFolder,"downloadimage.jpg"); try { OutputStream outputStream = new FileOutputStream(saveImage); data.compress(Bitmap.CompressFormat.JPEG,100,outputStream); outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } }
ВЫХОД
Убедитесь, что вы добавили разрешение на запись данных в память
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
источник
Сообщение @Droidman довольно обширное. Volley хорошо работает с небольшими данными в несколько килобайт. Когда я попытался использовать «BasicImageDownloader.java», Android Studio предупредила меня, что класс AsyncTask должен быть статическим, иначе могут возникнуть утечки. Я использовал Volley в другом тестовом приложении, и оно продолжало давать сбой из-за утечек, поэтому я беспокоюсь об использовании Volley для загрузчика изображений (изображения могут быть немного меньше 100 КБ).
Я использовал Picasso, и он работал хорошо, есть небольшое изменение (вероятно, обновление Picasso) по сравнению с тем, что опубликовано выше. Ниже код работал у меня:
public static void imageDownload(Context ctx, String url){ Picasso.get().load(yourURL) .into(getTarget(url)); } private static Target getTarget(final String url){ Target target2 = new Target() { @Override public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) { new Thread(new Runnable() { @Override public void run() { File file = new File(localPath + "/"+"YourImageFile.jpg"); try { file.createNewFile(); FileOutputStream ostream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, ostream); ostream.flush(); ostream.close(); } catch (IOException e) { Log.e("IOException", e.getLocalizedMessage()); } } }).start(); } @Override public void onBitmapFailed(Exception e, Drawable errorDrawable) { } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } }; return target; }
источник
Как сообщает Google, пока что не забудьте добавить в манифест также для чтения во внешнем хранилище:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Источник: http://developer.android.com/training/basics/data-storage/files.html#GetWritePermission.
источник