Завантаження Android з URL-адреси у растрове зображення


74

У мене питання щодо завантаження зображення з веб-сайту. Код, який я використовую:

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

Але він завжди повертає виняток з нульовим покажчиком, і програма виходить з ладу. URL-адреса дійсна, і, схоже, вона працює для всіх інших. Я використовую 2.3.1.


1
Яке повідомлення про збій ви отримуєте? Що таке стек? Чи знаєте ви, який рядок спричиняє його збій?
zeh

CreateScalesBitmap видає NullPointerException, оскільки біт є нулем.
Tyeomans

1
Потрібен дозвіл в Інтернеті ... Додано <uses-permission android:name="android.permission.INTERNET" /> до androidmanifest.xml
Tyeomans

Відповіді:


178
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;
    }
}

5
як завантажити один із https?
Абдул Вахаб

13
стежте за блокуванням основної нитки. Це слід використовувати в похідному класі AsyncTask.
Радім Халфар

17
Код чудовий. Але буде виняток "Мережа в основному потоці". Спробуйте використати це всередині "Асинхронне завдання".
Vikrant_Dev

Як виявити, чи підвищений IOException спричинений відсутністю доступу до Інтернету?
cprcrack

плюс 1 за дружність до Android 6.0
Jacksonkr

27

Якщо ви використовуєте Picasso або Glide або Universal-Image-Loader для завантаження зображення з url.
Ви можете просто отримати завантажене растрове зображення

Для Пікассо (поточна версія 2.71828)

Код 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) {}
});

Код Котліна

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

Для
перевірки ковзання Як можна скористатись ковзанням, щоб завантажити зображення у растрове зображення?

Для
коду Java Universal-Image-Loader

imageLoader.loadImage(imageUrl, new SimpleImageLoadingListener() 
{
    @Override
    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) 
    {
         // loaded bitmap is here (loadedImage)
    }
});

11

Я віддаю перевагу цим:

Створює растрове зображення з InputStream і повертає його:

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

ПАМ’ЯТАЙТЕ:

Android включає два HTTP-клієнти : HttpURLConnection та Apache HTTP-клієнт. Для пряників та пізніших версій найкращий вибір - HttpURLConnection .

З Android 3.x Honeycomb або пізнішої версії ви не можете виконувати мережевий ввід-вивід на потоці інтерфейсу, і це робить android.os.NetworkOnMainThreadException . Ви повинні використовувати Asynctask замість цього, як показано нижче

/**     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);

        }
    }

Яка хороша практика робити це, якщо я хочу завантажити кілька растрових зображень і показати їх як фони елемента списку у поданнях списку. Чи слід викликати Asynctask для кожного растрового зображення?
Тушар Катурія

1
У мене запитання щодо AsyncTask. Як я можу викликати цей метод у класі, в який я хочу перетворити URL-адресу у Bitmap, і як отримати доступ до Bitmap всередині цього класу?
Маркос Гімараеш

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

3

Дотримуйтесь методу, щоб отримати url для растрового зображення в android, просто перейдіть за посиланням цього зображення та отримайте растрове зображення.

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

3

Його робота в Pie OS Використовуйте це

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

3

Використовуйте програми Kotlin для обробки ниток

Причиною збою коду є те, що його Bitmapнамагаються створити на Main Threadякому заборонено, оскільки це може спричинити помилки Android Not Responding (ANR) .

Використані поняття

  • Котлін Короткі ноти .
  • Нижче використовується шаблон завантаження, вмісту, помилок (LCE) . Якщо ви зацікавлені, ви можете дізнатись більше про це в цій бесіді та відео .
  • LiveData використовується для повернення даних. У цих примітках я зібрав свій улюблений ресурс LiveData .
  • В бонус - код , toBitmap()це функція розширення Котлин вимагає цю бібліотеку , щоб додати до залежностей додатків.

Впровадження

Код

1. Створіть Bitmapінший потік, а не Main Thread.

У цьому зразку за допомогою Kotlin Coroutines функція виконується в Dispatchers.IOпотоці, який призначений для операцій на основі процесора. Функція має префікс, suspendкотрий є синтаксисом корутину .

Бонус - Після Bitmapстворення він також стискається в, ByteArrayщоб його можна було передати через Intentпізніше, описаний у цьому повному зразку .

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назад на Bitmap.

Utils.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()
        }
    }

2

Передайте URL-адресу зображення: Спробуйте це:

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

Створення службових програм класу:

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

2

Цей метод зробить трюк із програмою kotlin, тому він не заблокує основний потік інтерфейсу користувача і поверне змінене зображення растрового зображення кола (як зображення профілю)

 private var image: Bitmap? = null
 private fun getBitmapFromURL(src: String?) {
    CoroutineScope(Job() + Dispatchers.IO).launch {
        try {
            val url = URL(src)
            val bitMap = BitmapFactory.decodeStream(url.openConnection().getInputStream())
            image = Bitmap.createScaledBitmap(bitMap, 100, 100, true)
        } catch (e: IOException) {
            // Log exception
        }
    }
}

1

Спробуйте це:

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"));

1
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

          }
    }); 

1
Ласкаво просимо до stackoverflow. Будь ласка, прочитайте Як відповісти .
Аксель

1
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;
}

Використовуйте бібліотеку Glide і запустіть наступний код у робочому ланцюжку, як розміщено


Будь ласка, відредагуйте, щоб включити коментар, що пояснює цю відповідь на користь інших користувачів.
Томас Сміт,

1
  private class AsyncTaskRunner extends AsyncTask<String, String, String> {
    String Imageurl;

    public AsyncTaskRunner(String Imageurl) {
        this.Imageurl = Imageurl;
    }

    @Override
    protected String doInBackground(String... strings) {

        try {

            URL url = new URL(Imageurl);
            thumbnail_r = BitmapFactory.decodeStream(url.openConnection().getInputStream());


        } catch (IOException e) {
        }
        return null;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);


        imgDummy.setImageBitmap(thumbnail_r);
        UtilityMethods.tuchOn(relProgress);
    }
}

Викличте асинктаск як:

 AsyncTaskRunner asyncTaskRunner = new AsyncTaskRunner(uploadsModel.getImages());
        asyncTaskRunner.execute();

0

дуже швидкий спосіб, цей метод працює дуже швидко:

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

Util.copyStream (is, os);
Навіть Ченг

0

Спробуйте виконати наступні кроки.

1) Створіть AsyncTask у класі або адаптері (якщо ви хочете змінити зображення елемента списку).

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) Зателефонуйте AsyncTask зі своєї діяльності, фрагмента або адаптера (всередині onBindViewHolder).

2.a) Для адаптера:

    String src = current.getProductImage();
    new AsyncTaskLoadImage(holder.icon).execute(src);

2.b) Для діяльності та фрагмента:

**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) Будь ласка, запустіть програму та перевірте зображення.

Щасливого кодування .... :)


0

Якщо ви використовуєте Picasso for Images, ви можете спробувати метод нижче!

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

0

якщо ви використовуєте Glide і 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)

0
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
}

Спробуйте це з пікассо


-1

Якщо ви завантажуєте URL-адресу із растрового зображення без використання AsyncTask, напишіть два рядки після setContentView (R.layout.abc);

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

try {
    URL url = new URL("http://....");
    Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch(IOException e) {
    System.out.println(e);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.