J'ai une question sur le chargement d'une image à partir d'un site Web. Le code que j'utilise est:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Bitmap bit=null;
try {
bit = BitmapFactory.decodeStream((InputStream)new URL("http://www.mac-wallpapers.com/bulkupload/wallpapers/Apple%20Wallpapers/Apple-black-logo-wallpaper.jpg").getContent());
} catch (Exception e) {}
Bitmap sc = Bitmap.createScaledBitmap(bit,width,height,true);
canvas.drawBitmap(sc,0,0,null);
Mais il retourne toujours une exception de pointeur null et le programme se bloque ... .. L'URL est valide et semble fonctionner pour tout le monde . J'utilise 2.3.1.
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
// Log exception
return null;
}
}
Si vous utilisez Picasso ou Glide ou Universal-Image-Loader pour charger l'image à partir de l'URL.
Vous pouvez simplement obtenir le bitmap chargé par
Pour Picasso (version actuelle 2.71828
)
Code Java
Picasso.get().load(imageUrl).into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
// loaded bitmap is here (bitmap)
}
@Override
public void onBitmapFailed(Drawable errorDrawable) { }
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {}
});
Code de Kotlin
Picasso.get().load(url).into(object : com.squareup.picasso.Target {
override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
// loaded bitmap is here (bitmap)
}
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}
})
Pour Glide
Check Comment utiliser Glide pour télécharger une image dans un bitmap?
Pour Universal-Image-Loader
Code Java
imageLoader.loadImage(imageUrl, new SimpleImageLoadingListener()
{
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage)
{
// loaded bitmap is here (loadedImage)
}
});
Je préfère ceux-ci:
Crée Bitmap à partir de InputStream et le renvoie:
public static Bitmap downloadImage(String url) {
Bitmap bitmap = null;
InputStream stream = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1;
try {
stream = getHttpConnection(url);
bitmap = BitmapFactory.decodeStream(stream, null, bmOptions);
stream.close();
}
catch (IOException e1) {
e1.printStackTrace();
System.out.println("downloadImage"+ e1.toString());
}
return bitmap;
}
// Makes HttpURLConnection and returns InputStream
public static InputStream getHttpConnection(String urlString) throws IOException {
InputStream stream = null;
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
try {
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("GET");
httpConnection.connect();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream();
}
}
catch (Exception ex) {
ex.printStackTrace();
System.out.println("downloadImage" + ex.toString());
}
return stream;
}
RAPPELLES TOI :
Android comprend deux clients HTTP : HttpURLConnection et Apache HTTP Client. Pour Gingerbread et les versions ultérieures, HttpURLConnection est le meilleur choix.
À partir d'Android 3.x Honeycomb ou version ultérieure, vous ne pouvez pas exécuter Réseau IO sur le fil de l'interface utilisateur et pour ce faire, Android.os.NetworkOnMainThreadException . Vous devez utiliser Asynctask à la place comme indiqué ci-dessous
/** AsyncTAsk for Image Bitmap */
private class AsyncGettingBitmapFromUrl extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... params) {
System.out.println("doInBackground");
Bitmap bitmap = null;
bitmap = AppMethods.downloadImage(params[0]);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
System.out.println("bitmap" + bitmap);
}
}
public Drawable loadImageFromURL(String url, String name) {
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, name);
return d;
} catch (Exception e) {
return null;
}
}
Suivez la méthode pour obtenir les URL bitmap sous Android, il suffit de passer le lien de cette image et d’obtenir bitmap.
public static Bitmap getBitmapFromURL(String imgUrl) {
try {
URL url = new URL(imgUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
// Log exception
return null;
}
}
Transmettez l'URL de votre image: Essaye ça:
private Bitmap getBitmap(String url)
{
File file=fileCache.getFile(url);
Bitmap bm = decodeFile(file);
if(bm!=null)
return bm;
try {
Bitmap bitmap=null;
URL ImageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)ImageUrl.openConnection();
conn.setConnectTimeout(50000);
conn.setReadTimeout(50000);
conn.setInstanceFollowRedirects(true);
InputStream is = conn.getInputStream();
OutputStream os = new FileOutputStream(file);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(file);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
private Bitmap decodeFile(File file){
try {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file),null,opt);
final int REQUIRED_SIZE=70;
int width_tmp=opt.outWidth, height_tmp=opt.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
BitmapFactory.Options opte = new BitmapFactory.Options();
opte.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(file), null, opte);
} catch (FileNotFoundException e) {}
return null;
}
Créer des utilitaires de classe:
public class Utils {
public static void CopyStream(InputStream is, OutputStream os)
{
final int buffer_size=1024;
try
{
byte[] bytes=new byte[buffer_size];
for(;;)
{
int count=is.read(bytes, 0, buffer_size);
if(count==-1)
break;
os.write(bytes, 0, count);
}
}
catch(Exception ex){}
}
}
Glide.with(context)
.load("http://test.com/yourimage.jpg")
.asBitmap() // переводим его в нужный формат
.fitCenter()
.into(new SimpleTarget<Bitmap>(100,100) {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
// do something with you bitmap
bitmap
}
});
Essaye ça:
AQuery aq = new AQuery(getActivity());
aq.id(view.findViewById(R.id.image)).image(imageUrl, true, true, 0, 0,
new BitmapAjaxCallback() {
@Override
public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status){
iv.setImageBitmap(bm);
}
}.header("User-Agent", "Android"));
La raison pour laquelle le code plante est due au fait que la Bitmap
tente d'être créée sur le Main Thread
, ce qui n'est pas autorisé, car cela pourrait provoquer Android ne répond pas (ANR) des erreurs.
toBitmap()
est un fonction d'extension Kotlin nécessitant l'ajout de cette bibliothèque aux dépendances de l'application.Bitmap
dans un autre thread que le Main Thread
.Dans cet exemple utilisant Kotlin Coroutines , la fonction est en cours d'exécution dans le thread Dispatchers.IO
qui est destiné aux opérations basées sur la CPU. La fonction est préfixée avec suspend
qui est une syntaxe Coroutine .
Bonus - Une fois la Bitmap
créée, elle est également compressée en une ByteArray
pour pouvoir être transmise via une Intent
décrite plus loin dans cet complet échantillon .
Repository.kt
suspend fun bitmapToByteArray(url: String) = withContext(Dispatchers.IO) {
MutableLiveData<Lce<ContentResult.ContentBitmap>>().apply {
postValue(Lce.Loading())
postValue(Lce.Content(ContentResult.ContentBitmap(
ByteArrayOutputStream().apply {
try {
BitmapFactory.decodeStream(URL(url).openConnection().apply {
doInput = true
connect()
}.getInputStream())
} catch (e: IOException) {
postValue(Lce.Error(ContentResult.ContentBitmap(ByteArray(0), "bitmapToByteArray error or null - ${e.localizedMessage}")))
null
}?.compress(CompressFormat.JPEG, BITMAP_COMPRESSION_QUALITY, this)
}.toByteArray(), "")))
}
}
ViewModel.kt
//Calls bitmapToByteArray from the Repository
private fun bitmapToByteArray(url: String) = liveData {
emitSource(switchMap(repository.bitmapToByteArray(url)) { lce ->
when (lce) {
is Lce.Loading -> liveData {}
is Lce.Content -> liveData {
emit(Event(ContentResult.ContentBitmap(lce.packet.image, lce.packet.errorMessage)))
}
is Lce.Error -> liveData {
Crashlytics.log(Log.WARN, LOG_TAG,
"bitmapToByteArray error or null - ${lce.packet.errorMessage}")
}
}
})
}
ByteArray
en Bitmap
.tils.kt
fun ByteArray.byteArrayToBitmap(context: Context) =
run {
BitmapFactory.decodeByteArray(this, BITMAP_OFFSET, size).run {
if (this != null) this
// In case the Bitmap loaded was empty or there is an error I have a default Bitmap to return.
else AppCompatResources.getDrawable(context, ic_coinverse_48dp)?.toBitmap()
}
}
S'il vous plaît essayez ces étapes suivantes.
1) Créez une tâche asynchrone dans une classe ou un adaptateur (si vous souhaitez modifier l'image de l'élément de liste).
public class AsyncTaskLoadImage extends AsyncTask<String, String, Bitmap> {
private final static String TAG = "AsyncTaskLoadImage";
private ImageView imageView;
public AsyncTaskLoadImage(ImageView imageView) {
this.imageView = imageView;
}
@Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
try {
URL url = new URL(params[0]);
bitmap = BitmapFactory.decodeStream((InputStream) url.getContent());
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
try {
int width, height;
height = bitmap.getHeight();
width = bitmap.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
Paint.setColorFilter(f);
c.drawBitmap(bitmap, 0, 0, Paint);
imageView.setImageBitmap(bmpGrayscale);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2) Appelez AsyncTask depuis votre activité, votre fragment ou votre adaptateur (dans onBindViewHolder).
2.a) pour adaptateur:
String src = current.getProductImage();
new AsyncTaskLoadImage(holder.icon).execute(src);
2.b) Pour activité et fragment:
**Activity:**
ImageView imagview= (ImageView) findViewById(R.Id.imageview);
String src = (your image string);
new AsyncTaskLoadImage(imagview).execute(src);
**Fragment:**
ImageView imagview= (ImageView)view.findViewById(R.Id.imageview);
String src = (your image string);
new AsyncTaskLoadImage(imagview).execute(src);
3) Veuillez lancer l'application et vérifier l'image.
Bonne codage .... :)
fun getBitmap(url : String?) : Bitmap? {
var bmp : Bitmap ? = null
Picasso.get().load(url).into(object : com.squareup.picasso.Target {
override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
bmp = bitmap
}
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}
})
return bmp
}
Essayez ceci avec picasso
Si vous utilisez Picasso pour Images, vous pouvez essayer la méthode ci-dessous!
public static Bitmap getImageBitmapFromURL(Context context, String imageUrl){
Bitmap imageBitmap = null;
try {
imageBitmap = new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
try {
int targetHeight = 200;
int targetWidth = 200;
return Picasso.with(context).load(String.valueOf(imageUrl))
//.resize(targetWidth, targetHeight)
.placeholder(R.drawable.raw_image)
.error(R.drawable.raw_error_image)
.get();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
}
return imageBitmap;
}
public static Bitmap getImgBitmapFromUri(final String url, final Activity context, final CropImageView imageView, final File file) {
final Bitmap bitmap = null;
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try {
Utils.image = Glide.with(context)
.load(url).asBitmap()
.into(100, 100).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
context.runOnUiThread(new Runnable() {
@Override
public void run() {
if (imageView != null)
imageView.setImageBitmap(Utils.image);
}
});
}
});
return Utils.image;
}
Utilisez la bibliothèque Glide et exécutez le code suivant dans le fil de travail tel que posté.
Son fonctionnement dans Pie OS Utilisez ceci
@Override
protected void onCreate() {
super.onCreate();
//setNotificationBadge();
if (Android.os.Build.VERSION.SDK_INT >= 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
}
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
Menu menu = bottomNavigationView.getMenu();
MenuItem userImage = menu.findItem(R.id.navigation_download);
userImage.setTitle("Login");
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL("https://rukminim1.flixcart.com/image/832/832/jmux18w0/mobile/b/g/n/mi-redmi-6-mzb6387in-original-imaf9z8eheryfbsu.jpeg?q=70");
Bitmap myBitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
Log.e("keshav", "Bitmap " + myBitmap);
userImage.setIcon(new BitmapDrawable(getResources(), myBitmap));
} catch (IOException e) {
Log.e("keshav", "Exception " + e.getMessage());
}
}
});
manière très rapide, cette méthode fonctionne très rapidement:
private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
si vous utilisez Glide et Kotlin ,
Glide.with(this)
.asBitmap()
.load("https://...")
.addListener(object : RequestListener<Bitmap> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Bitmap>?,
isFirstResource: Boolean
): Boolean {
Toast.makeText(this@MainActivity, "failed: " + e?.printStackTrace(), Toast.LENGTH_SHORT).show()
return false
}
override fun onResourceReady(
resource: Bitmap?,
model: Any?,
target: Target<Bitmap>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
//image is ready, you can get bitmap here
var bitmap = resource
return false
}
})
.into(imageView)