Android 从 URL 加载到位图

我有一个关于从网站加载图片的问题,我使用的代码是:

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。

188804 次浏览
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;
}
}
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;
}
}

试试这个:

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

非常快的方法,这种方法工作非常快:

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

传递你的图片网址: 试试这个:

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

我更喜欢这个:

创建 来自 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和 < em > Apache HTTP 客户端。 对于姜饼和以后,HttpURLConnection是最好的选择。

在 Android 3.x 或更高版本的 Honeycomb 上,您不能在 UI 线程上执行 网络 IO,这样做会抛出 NetworkOnMainThreadException。您必须改为使用 异步,如下所示

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


}
}

如果使用 毕加索滑行通用图像载入器从 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?) {}
})

为了格莱德
检查“ href = “ https://stackoverflow. com/questions/27394016/How-does-one-use-glide-to-download-an-image-into-a-bitmap”如何使用 glide 将图像下载到位图中?

通用图像加载器
Java 代码

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

按照下面的方法在 android 中获取 URL 到位图,只需要传递这个图像的链接就可以得到位图。

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


}
});
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)在类或适配器中创建 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)从您的活动、片段或适配器(在 onBindViewHolder 内部)调用 AsyncTask。

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)请运行应用程序并检查图像。

编程愉快... . :)

如果不使用 AsyncTask 从位图加载 URL,请在 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);
}

如果你正在使用毕加索的图像,你可以尝试下面的方法!

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

如果你使用 滑行科特林,

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)

它在馅饼操作系统中的工作使用这个

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

使用 Kotlin 协程处理线程

代码崩溃的原因是因为 Bitmap试图在 Main Thread上创建,这是不允许的,因为它可能会导致 Android 没有响应(ANR)错误。

使用的概念

  • 柯特林协同程序 笔记
  • 下面使用的是 加载,内容,错误(LCE)模式。如果你感兴趣的话,可以在 这个谈话和视频中学到更多。
  • LiveData 用于返回数据。
  • 奖金代码中,toBitmap()是一个 Kotlin 扩展函数,需要将该库添加到应用程序依赖项中。

实施

密码

1. 在另一个线程中创建 Bitmap,然后是 Main Thread

在这个使用 Kotlin Coroutines的示例中,函数是在 Dispatchers.IO线程中执行的,Dispatchers.IO线程用于基于 CPU 的操作。函数的前缀是 suspend,这是一种 心肺复苏术语法。

额外奖励 -在 Bitmap被创建之后,它也被压缩成一个 ByteArray,因此它可以通过一个 Intent传递,稍后在这个 完整样本中概述。

知识库

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

用毕加索试试这个

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

这个方法将做的技巧与 kotlin 协程,所以它不会阻塞 UI 主线程 & 将返回调整大小的圆形位图图像(如配置文件图像)

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

如果你喜欢 线圈而不是 Glide。

val imageRequest = ImageRequest.Builder(context)
.data(imageUrl)
.target { drawable ->
val bitmap = drawable.toBitmap() // This is the bitmap 🚨
}
.build()
ImageLoader(context).enqueue(imageRequest)