84 votes

Android charger à partir de l'URL vers Bitmap

J'ai une question concernant 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 cela retourne toujours une exception de pointeur nul et le programme plante. L'URL est valide, et cela semble fonctionner pour tout le monde. Je suis en train d'utiliser la version 2.3.1.

1 votes

Quel message de crash obtenez-vous? Quelle est la trace de la pile? Savez-vous quelle ligne provoque le crash?

0 votes

La méthode createScalesBitmap lance une NullPointerException car bit est nul.

1 votes

Nécessaire l'autorisation Internet... Ajouté à androidmanifest.xml

3voto

Keshav Gera Points 1892

Cela fonctionne 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("Connexion");

        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());
                }
            }
        });

3voto

Pankaj Talaviya Points 1218

Suivez la méthode pour obtenir l'URL vers un bitmap dans Android en passant simplement le lien de cette image et obtenez le 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) {
        // Journaliser l'exception
        return null;
    }
}

3voto

Adam Hurwitz Points 902

Utiliser les Coroutines Kotlin pour gérer le threading

La raison pour laquelle le code plante est parce que le Bitmap est en train d'être créé sur le Main Thread, ce qui n'est pas autorisé car cela pourrait entraîner des erreurs de type Android Not Responding (ANR).

Concepts utilisés

  • Les Coroutines Kotlin notes.
  • Le pattern Chargement, Contenu, Erreur (LCE) est utilisé ci-dessous. Si vous êtes intéressé, vous pouvez en apprendre davantage à ce sujet dans cette conférence et cette vidéo.
  • LiveData est utilisé pour retourner les données. J'ai compilé mes ressources LiveData préférées dans ces notes.
  • Dans le code bonus, toBitmap() est une fonction d'extension Kotlin nécessitant d'ajouter cette bibliothèque aux dépendances de l'application.

Implémentation

Code

1. Créer un Bitmap dans un thread différent du Main Thread.

Dans cet exemple utilisant les Coroutines Kotlin, la fonction est exécutée dans le thread Dispatchers.IO qui est destiné aux opérations basées sur le CPU. La fonction est préfixée par suspend, qui est une syntaxe des Coroutines.

Bonus - Après la création du Bitmap, il est également compressé dans un ByteArray pour pouvoir être transmis via un Intent plus tard décrit dans cet exemple complet.

Repository.kt

suspend fun bitmapToByteArray(url: String) = withContext(Dispatchers.IO) {
    MutableLiveData>().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

//Appelle bitmapToByteArray du 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}")
            }
        }
    })
}

Bonus - Convertir un ByteArray en Bitmap.

Utils.kt

fun ByteArray.byteArrayToBitmap(context: Context) =
    run {
        BitmapFactory.decodeByteArray(this, BITMAP_OFFSET, size).run {
            if (this != null) this
            // Au cas où le Bitmap chargé serait vide ou s'il y a une erreur, j'ai un Bitmap par défaut à retourner.
            else AppCompatResources.getDrawable(context, ic_coinverse_48dp)?.toBitmap()
        }
    }

2voto

User Learning Points 1411

Indiquez l'URL de votre image: Essayez ceci:

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

`Créez la classe Utils:

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){}
    }
}`

2voto

Abhishek Dhyani Points 150

Si vous préférez Coil plutôt que Glide.

val imageRequest = ImageRequest.Builder(context)
        .data(imageUrl)
        .target { drawable ->
            val bitmap = drawable.toBitmap() // C'est le bitmap

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X