Come si scarica e si salva un'immagine da un determinato URL in Android?
Risposte:
ultimo importante aggiornamento: 31 marzo 2016
TL; DR aka smettila di parlare, dammi solo il codice !!
Salta alla fine di questo post, copia la
BasicImageDownloader
(versione javadoc qui ) nel tuo progetto, implementa l'OnImageLoaderListener
interfaccia e il gioco è fatto.Nota : sebbene
BasicImageDownloader
gestisca possibili errori e impedirà alla tua app di bloccarsi nel caso in cui qualcosa vada storto, non eseguirà alcuna post-elaborazione (es. Ridimensionamento) sul file scaricatoBitmaps
.
Dato che questo post ha ricevuto molta attenzione, ho deciso di rielaborarlo completamente per impedire alla gente di utilizzare tecnologie deprecate, cattive pratiche di programmazione o semplicemente fare cose stupide - come cercare "hack" per eseguire la rete sul thread principale o accetta tutti i certificati SSL.
Ho creato un progetto demo chiamato "Image Downloader" che dimostra come scaricare (e salvare) un'immagine utilizzando la mia implementazione del downloader, il built-in di Android DownloadManager
e alcune popolari librerie open source. Puoi visualizzare il codice sorgente completo o scaricare il progetto su GitHub .
Nota : non ho ancora modificato la gestione delle autorizzazioni per SDK 23+ (Marshmallow), quindi il progetto ha come target l'SDK 22 (Lollipop).
Nella mia conclusione alla fine di questo post condividerò la mia modesta opinione sul caso d'uso appropriato per ogni particolare modo di scaricare le immagini che ho menzionato.
Cominciamo con una propria implementazione (puoi trovare il codice alla fine del post). Prima di tutto, questo è un ImageDownloader di base e basta. Tutto ciò che fa è connettersi all'URL fornito, leggere i dati e provare a decodificarli come un Bitmap
, attivando i OnImageLoaderListener
callback dell'interfaccia quando appropriato. Il vantaggio di questo approccio: è semplice e hai una chiara panoramica di cosa sta succedendo. Un buon modo se tutto ciò di cui hai bisogno è scaricare / visualizzare e salvare alcune immagini, mentre non ti interessa mantenere una memoria / cache del disco.
Nota: in caso di immagini di grandi dimensioni, potrebbe essere necessario ridimensionarle .
-
Android DownloadManager è un modo per consentire al sistema di gestire il download per te. In realtà è in grado di scaricare qualsiasi tipo di file, non solo immagini. Puoi lasciare che il download avvenga in modo silenzioso e invisibile all'utente oppure puoi consentire all'utente di visualizzare il download nell'area di notifica. È inoltre possibile registrare un BroadcastReceiver
per ricevere una notifica al termine del download. La configurazione è molto semplice, fare riferimento al progetto collegato per il codice di esempio.
L'utilizzo di DownloadManager
non è generalmente una buona idea se si desidera visualizzare anche l'immagine, poiché è necessario leggere e decodificare il file salvato invece di impostare semplicemente il file scaricato Bitmap
in un file ImageView
. Il DownloadManager
inoltre, non fornisce alcuna API per voi app per monitorare l'avanzamento del download.
-
Ora l'introduzione della grande roba: le biblioteche. Possono fare molto di più che scaricare e visualizzare immagini, tra cui: creare e gestire la memoria / cache del disco, ridimensionare le immagini, trasformarle e altro ancora.
Inizierò con Volley , una potente libreria creata da Google e coperta dalla documentazione ufficiale. Pur essendo una libreria di rete generica non specializzata in immagini, Volley offre un'API piuttosto potente per la gestione delle immagini.
Dovrai implementare una classe Singleton per gestire le richieste di Volley e sei a posto.
Potresti voler sostituire il tuo ImageView
con Volley's NetworkImageView
, quindi il download diventa fondamentalmente un one-liner:
((NetworkImageView) findViewById(R.id.myNIV)).setImageUrl(url, MySingleton.getInstance(this).getImageLoader());
Se hai bisogno di più controllo, ecco come si crea un ImageRequest
con 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
}
});
Vale la pena ricordare che Volley offre un eccellente meccanismo di gestione degli errori fornendo la VolleyError
classe che ti aiuta a determinare la causa esatta di un errore. Se la tua app fa molto networking e la gestione delle immagini non è il suo scopo principale, Volley è perfetta per te.
-
Picasso di Square è una famosa libreria che farà tutto il caricamento delle immagini per te. La semplice visualizzazione di un'immagine utilizzando Picasso è semplice come:
Picasso.with(myContext)
.load(url)
.into(myImageView);
Per impostazione predefinita, Picasso gestisce la cache del disco / memoria, quindi non devi preoccuparti di questo. Per un maggiore controllo puoi implementare l' Target
interfaccia e usarla per caricare la tua immagine - questo fornirà callback simili all'esempio Volley. Controlla il progetto demo per esempi.
Picasso ti consente anche di applicare trasformazioni all'immagine scaricata e ci sono anche altre librerie in giro che estendono quelle API. Funziona anche molto bene in un RecyclerView
/ ListView
/ GridView
.
-
Universal Image Loader è un'altra libreria molto popolare che serve per la gestione delle immagini. Usa il proprio ImageLoader
che (una volta inizializzato) ha un'istanza globale che può essere utilizzata per scaricare immagini in una singola riga di codice:
ImageLoader.getInstance().displayImage(url, myImageView);
Se desideri monitorare l'avanzamento del download o accedere al download 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
}
});
L' opts
argomento in questo esempio è un DisplayImageOptions
oggetto. Fare riferimento al progetto demo per saperne di più.
Simile a Volley, UIL fornisce la FailReason
classe che ti consente di verificare cosa è andato storto in caso di download non riuscito. Per impostazione predefinita, UIL mantiene una memoria / cache del disco se non gli dici esplicitamente di non farlo.
Nota : l'autore ha detto che non manterrà più il progetto dal 27 novembre 2015. Ma poiché ci sono molti collaboratori, possiamo sperare che Universal Image Loader continui a vivere.
-
Fresco di Facebook è la più recente e (IMO) la libreria più avanzata che porta la gestione delle immagini a un nuovo livello: dal tenere Bitmaps
lontano l'heap java (prima di Lollipop) al supporto di formati animati e streaming JPEG progressivo .
Per saperne di più sulle idee e le tecniche alla base di Fresco, fare riferimento a questo post .
L'utilizzo di base è abbastanza semplice. Nota che dovrai chiamare Fresco.initialize(Context);
solo una volta, preferibile in Application
classe. L'inizializzazione di Fresco più di una volta può portare a comportamenti imprevedibili ed errori OOM.
Fresco usa Drawee
s per visualizzare le immagini, puoi immaginarle come di 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" />
Come puoi vedere, molte cose (comprese le opzioni di trasformazione) vengono già definite in XML, quindi tutto ciò che devi fare per visualizzare un'immagine è una riga:
mDrawee.setImageURI(Uri.parse(url));
Fresco fornisce un'API di personalizzazione estesa, che, in circostanze, può essere piuttosto complessa e richiede all'utente di leggere attentamente i documenti (sì, a volte è necessario RTFM).
Ho incluso esempi per JPEG progressivi e immagini animate nel progetto di esempio.
Si noti che il testo seguente riflette la mia opinione personale e non dovrebbe essere preso come un postulato.
Recycler-/Grid-/ListView
e non hai bisogno di un intero gruppo di immagini per essere pronto per la visualizzazione, BasicImageDownloader dovrebbe soddisfare le tue esigenze.JSON
dati, funziona con le immagini, ma questo non è lo scopo principale dell'app, vai con Volley .Nel caso ve lo foste perso, il link Github per il progetto demo.
Ed ecco il file 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
(nel onActivityResult()
metodo), quindi creare un Bitmap
percorso utilizzando quel percorso. E sì, non eviterai di usare a FileOutputStream
e a ByteArrayOutputStream
se vuoi salvare questa immagine su SD.
Sono appena tornato dalla risoluzione di questo problema e vorrei condividere il codice completo che può scaricare, salvare sulla sdcard (e nascondere il nome del file) e recuperare le immagini e infine controlla se l'immagine è già lì. L'URL proviene dal database, quindi il nome del file può essere facilmente utilizzato utilizzando id.
prime immagini di download
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_);
}
}
}
Quindi creare una classe per salvare e recuperare i file
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 ;
}
}
Quindi Per accedere alle immagini prima controlla se è già lì, altrimenti scarica
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
vantaggi di (uso corretto della parametrizzazione, esecuzione parallela ..). Fare riferimento ai miei esempi di seguito per i dettagli. PS . per coloro che potrebbero pensare che ho scritto questo per promuovere il mio codice per qualsiasi motivo: no, sto solo indicando i problemi che posso vedere nell'esempio fornito.
download
metodo, in particolare al doInBackground
metodo dell'attività che utilizzo. Un IOException
sarebbe atterrato nel catch (Throwable e)
blocco, risultando in un ImageError
essere restituito e la onError()
richiamata sarebbe stata attivata. L' ImageError
oggetto conterrà la traccia dello stack originale e la causa dell'accadutoException
Perché hai davvero bisogno del tuo codice per scaricarlo? Che ne dici di passare il tuo URI al Download manager?
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);
}
potrebbe aiutarti ..
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();
}
}
});
Ho una soluzione semplice che funziona perfettamente. Il codice non è mio, l'ho trovato su questo link . Ecco i passaggi da seguire:
1. Prima di scaricare l'immagine, scriviamo un metodo per salvare bitmap in un file immagine nella memoria interna di Android. Ha bisogno di un contesto, meglio usare il passaggio nel contesto dell'applicazione di getApplicationContext (). Questo metodo può essere scaricato nella tua classe Activity o in altre classi util.
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. Ora abbiamo un metodo per salvare la bitmap in un file immagine in andorid, scriviamo AsyncTask per il download di immagini tramite url. Questa classe privata deve essere inserita nella classe Attività come sottoclasse. Dopo aver scaricato l'immagine, nel metodo onPostExecute, chiama il metodo saveImage definito sopra per salvare l'immagine. Nota, il nome dell'immagine è hardcoded come "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. L'AsyncTask per il download dell'immagine è definito, ma dobbiamo eseguirlo per eseguire quell'AsyncTask. Per fare ciò, scrivi questa riga nel tuo metodo onCreate nella tua classe Activity, o in un metodo onClick di un pulsante o in altri posti che ritieni adatti.
new DownloadImage().execute("http://developer.android.com/images/activity_lifecycle.png");
L'immagine dovrebbe essere salvata in /data/data/your.app.packagename/files/my_image.jpeg, controlla questo post per accedere a questa directory dal tuo dispositivo.
IMO questo risolve il problema! Se desideri ulteriori passaggi come caricare l'immagine, puoi seguire questi passaggi aggiuntivi:
4. Dopo che l'immagine è stata scaricata, abbiamo bisogno di un modo per caricare l'immagine bitmap dalla memoria interna, in modo da poterla utilizzare. Scriviamo il metodo per caricare la bitmap dell'immagine. Questo metodo richiede due parametri, un contesto e un nome file immagine, senza il percorso completo, context.openFileInput (imageName) cercherà il file nella directory di salvataggio quando questo nome file è stato salvato nel metodo saveImage sopra.
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. Ora abbiamo tutto ciò di cui abbiamo bisogno per impostare l'immagine di un ImageView o di qualsiasi altra vista su cui desideri utilizzare l'immagine. Quando salviamo l'immagine, abbiamo codificato il nome dell'immagine come "my_image.jpeg", ora possiamo passare questo nome dell'immagine al metodo loadImageBitmap sopra per ottenere la bitmap e impostarla su ImageView.
someImageView.setImageBitmap(loadImageBitmap(getApplicationContext(), "my_image.jpeg"));
6. Per ottenere il percorso completo dell'immagine in base al nome dell'immagine.
File file = getApplicationContext().getFileStreamPath("my_image.jpeg");
String imageFullPath = file.getAbsolutePath();
7. Verificare se il file immagine esiste.
File file =
getApplicationContext().getFileStreamPath("my_image.jpeg");
if (file.exists()) Log.d("file", "my_image.jpeg exists!");
Per eliminare il file immagine.
File file = getApplicationContext (). GetFileStreamPath ("my_image.jpeg"); if (file.delete ()) Log.d ("file", "my_image.jpeg cancellato!");
questo codice funziona perfettamente nel mio progetto
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();
}
}
}
}
Assicurati di aver aggiunto l'autorizzazione per scrivere dati in memoria
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Come dice Google, per ora, non dimenticare di aggiungere anche leggibile su memoria esterna nel manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Fonte: http://developer.android.com/training/basics/data-storage/files.html#GetWritePermission