Android——Loading images with HTTP POST
Posted Jason Zhang~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android——Loading images with HTTP POST相关的知识,希望对你有一定的参考价值。
大家在进行安卓开发时,一般都会使用图片加载框架来进行图片的展示,如universalimageloader、Glide等。开发者只需要传值网络图片的URL以及要显示的图片控件即可。简单粗暴。但是如果你遇到了我这样的奇葩需求(图片是一个post请求的URL),那么这篇文章你算是找对了。
大家都知道,一般请求查询数据或者打开一个图片的url都是GET请求,当然要使用post也是ok的啦。但是测试发现项目中的universalimageloader、Glide两个图片加载框架,在处理POST请求的图片URL时就没用了。猜测这两个框架内默认都是使用了GET请求,所以,查看源码,寻找到对应的代码然后进行自定义或者修改成POST请求就行啦!
这里记录本人的操作,以便后续查看。
1、universalimageloader。源码修改。
因为项目中使用的universalimageloader框架是使用了源码,所以这里是直接找到源码进行修改的,如果不能直接修改源码的话,不知道是否提供了自定义方法来修改(Glide是使用自定义加载,可参考,但本人没研究)。
com.nostra13.universalimageloader.core.download.BaseImageDownloader 类,就是该框架使用HttpURLConnection的方式通过GET请求拿到InputStream来显示图片的。HttpURLConnection没有设置请求方式,就是使用了默认的GET请求。所以,我们在创建HttpURLConnection的时候加上设置请求方式为POST的代码即可。
// 源码
protected HttpURLConnection createConnection(String url, Object extra) throws IOException
String encodedUrl = Uri.encode(url, ALLOWED_URI_CHARS);
HttpURLConnection conn = (HttpURLConnection) new URL(encodedUrl).openConnection();
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
return conn;
// 修改后的代码
protected HttpURLConnection createConnection(String url, Object extra) throws IOException
String encodedUrl = Uri.encode(url, ALLOWED_URI_CHARS);
HttpURLConnection conn = (HttpURLConnection) new URL(encodedUrl).openConnection();
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(readTimeout);
// 只针对我们的项目,或某些只能使用POST拿到图片的URL才使用POST,其他的照旧使用GET
if (url.startsWith("XXXXXXX"))
conn.setRequestMethod("POST");
return conn;
经测试,OK。
2、Glide。自定义加载类。
Glide框架是通过配置gradle的形式使用的,所以就无法修改源码了。但是我们通过查看源码还是找到了它请求URL拿到InputStream的类。
com.bumptech.glide.load.data.HttpUrlFetcher
以下是请求的具体方法:
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)
throws IOException
if (redirects >= MAXIMUM_REDIRECTS)
throw new IOException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
else
// Comparing the URLs using .equals performs additional network I/O and is generally broken.
// See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
try
if (lastUrl != null && url.toURI().equals(lastUrl.toURI()))
throw new IOException("In re-direct loop");
catch (URISyntaxException e)
// Do nothing, this is best effort.
urlConnection = connectionFactory.build(url);
for (Map.Entry<String, String> headerEntry : headers.entrySet())
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(2500);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Connect explicitly to avoid errors in decoders if connection fails.
urlConnection.connect();
if (isCancelled)
return null;
final int statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2)
return getStreamForSuccessfulRequest(urlConnection);
else if (statusCode / 100 == 3)
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString))
throw new IOException("Received empty or null redirect url");
URL redirectUrl = new URL(url, redirectUrlString);
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
else
if (statusCode == -1)
throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
很显然,它也是使用了HttpURLConnection的默认请求方式GET。如果你使用的是源码的话,可以仿照universalimageloader的方式,在urlConnection.connect();
方法前做判断和设置成POST请求。
如果你也和我一样无法直接修改源码的话,可以使用如下方式:
1、复制HttpUrlFetcher类,把名字改成HttpUrlPostFetcher。要做的修改就是在urlConnection.connect();
方法前做判断和设置成POST请求。
2、新建一个ModelLoader的子类HttpUrlPostLoader,表明使用刚刚自定义的HttpUrlPostFetcher类,代码如下:
public class HttpUrlPostLoader implements ModelLoader<GlideUrl, InputStream>
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream>
public Factory()
@Override
public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories)
return new HttpUrlPostLoader();
@Override
public void teardown()
public HttpUrlPostLoader()
@Override
public DataFetcher<InputStream> getResourceFetcher(GlideUrl model, int width, int height)
return new HttpUrlPostFetcher(model);
3、自定义要使用的GlideModule的子类CustomGlideModule,使用第二步创建的ModelLoader,代码如下:
public class CustomGlideModule implements GlideModule
@Override
public void applyOptions(Context context, GlideBuilder builder)
//通过builder.setXXX进行配置.
@Override
public void registerComponents(Context context, Glide glide)
//通过glide.register进行配置.
glide.register(GlideUrl.class, InputStream.class, new HttpUrlPostLoader.Factory());
4、在androidManifest.xml中注册,代码如下:
<meta-data
android:name="XXXX.CustomGlideModule"
android:value="GlideModule" />
经测试,OK。
以上是关于Android——Loading images with HTTP POST的主要内容,如果未能解决你的问题,请参考以下文章
在我的 php 文件解析和下载数据时调用 preloader(gif , loading image)
VMWare------启动虚拟机时出现“start booting fron CD... Error loading image:DFEAULT.EZB”提示
jquery插件,用于轻松创建加载css3/images动画