Android建立网络连接,利用JSON数据获取百度图片搜索结果及GSON的简单使用
2017-02-14 10:38
1021 查看
1、建立网络连接的基本方式
Android中建立网络连接最主要的方式是利用HttpURLConnection,示例如下:public class HttpUtil { public static byte[] getUrlBytes(String urlSpec) throws IOException { //将地址信息封装成URL URL url = new URL(urlSpec); //创建指向URL链接的HttpURLConnection对象 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try { //保存返回结果 ByteArrayOutputStream out = new ByteArrayOutputStream(); //真正开始访问指定地址 InputStream in = connection.getInputStream(); //HTTP_OK才是成功建立链接 if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new IOException(connection.getResponseMessage() + ": with " + urlSpec); } int bytesRead; byte[] buffer = new byte[1024]; //不断从网络下载数据,并保存到out中 while ((bytesRead = in.read(buffer)) > 0) { out.write(buffer, 0, bytesRead); } out.close(); //下载完毕后,将结果转化成byte array return out.toByteArray(); } finally { //断开连接 connection.disconnect(); } } public static String getUrlString(String urlSpec) throws IOException{ //将byteArray转化为String return new String(getUrlBytes(urlSpec)); } }
2、下载百度图片对应的JSON数据
我们进入百度图片,例如“微距摄影”这个类别,其http地址如下:http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&sf=2&fmq=1480332039000_R_D&pv=&ic=0&nc=1&z=&se=&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E5%BE%AE%E8%B7%9D%E6%91%84%E5%BD%B1
其中:
http://image.baidu.com/search/index?
可以看作基础的http地址,后续的tn、ipn、ct等均是额外的访问参数。
例如:word后就是访问的类别,对应中文的“微距摄影”。
现在,基于这个地址,我们来看看如何获取百度图片搜索得到的结果:
public List<GalleryItem> fetchItems() { .............. try { //解析基础地址 String url = Uri.parse("http://image.baidu.com/search/index?") .buildUpon() //增加参数,这里指定结果以json格式返回 .appendQueryParameter("tn", "resultjson") //指定类别为微距摄影 .appendQueryParameter("word", "微距摄影") .build().toString(); Log.d("ZJTest", url); String jsonString = HttpUtil.getUrlString(url); Log.d("ZJTest", jsonString); ............ } catch (JSONException | IOException e) { e.printStackTrace(); } return items; }
我们增加了log信息,看看生成的url:
02-14 09:59:49.154 32471-32506/stark.a.is.zhang.photogallery D/ZJTest: http://image.baidu.com/search/index?tn=resultjson&word=%E5%BE%AE%E8%B7%9D%E6%91%84%E5%BD%B1[/code]
可以看到,url的信息结构与前面的http地址相似。
这里我们只使用了tn、word参数,还可以按照同样的方式,增加其它的要求。
我们再看看返回的结果,为了方便观察,我们修改一下返回结果的格式,增加一些回车和空格:02-14 09:59:49.354 32471-32506/stark.a.is.zhang.photogallery D/ZJTest: { "queryEnc":"%E5%BE%AE%E8%B7%9D%E6%91%84%E5%BD%B1", "queryExt":"微距摄影", "listNum":1965, "displayNum":208527, "gsm":"1000000001e", "bdSearchTime":"", "isNeedAsyncRequest":0, "bdIsClustered":"1", "data":[ { "thumbURL":"http://f.hiphotos.baidu.com/image/h%3D300/sign=e444f9f5a0014c08063b2ea53a7a025b/359b033b5bb5c9ea18ae77bfdc39b6003af3b308.jpg", "middleURL":"http://f.hiphotos.baidu.com/image/h%3D200/sign=1250a848b199a90124355c362d940a58/359b033b5bb5c9ea18ae77bfdc39b6003af3b308.jpg", "largeTnImageUrl":"", "hasLarge" :0, "hoverURL":"http://f.hiphotos.baidu.com/image/h%3D300/sign=e444f9f5a0014c08063b2ea53a7a025b/359b033b5bb5c9ea18ae77bfdc39b6003af3b308.jpg", "pageNum":0, "objURL":"http://imgsrc.baidu.com/forum/pic/item/a8ec8a13632762d006deaa12a0ec08fa503dc6bf.jpg", "fromURL":"http://tieba.baidu.com/p/1690102901", "fromURLHost":"tieba.baidu.com", "currentIndex":"", "width":900, "height":597, "type":"jpg", "filesize":"", "bdSrcType":"-1", "di":"0", "adid":"0", "is":"", "simid_info":null, "face_info":null, "xiangshi_info":null, "adPicId":"0", "pi":"0", "bdSetImgNum":0, "bdImgnewsDate":"1970-01-01 08:00", "fromPageTitle":"微距摄影", "fromPageTitleEnc":"微距摄影", "bdSourceName":"", "bdFromPageTitlePrefix":"", "token":"" }, { "thumbURL":"http://img4.imgtn.bdimg.com/it/u=1193418232,3244632658&fm=23&gp=0.jpg", "middleURL":"http://img4.imgtn.bdimg.com/it/u=1193418232,3244632658&fm=21&gp=0.jpg", "largeTnImageUrl":"", "hasLarge" :0, "hoverURL":"http://img4.imgtn.bdimg.com/it/u=1193418232,3244632658&fm=23&gp=0.jpg", "pageNum":1, "objURL":"http://img4.duitang.com/uploads/item/201408/30/20140830185456_Eijik.jpeg", "fromURL":"http://www.duitang.com/people/mblog/196468797/detail/", "fromURLHost":"www.duitang.com", "currentIndex":"", "width":1200, "height":800, "type":"jpeg", "filesize":"", "bdSrcType":"0", "di":"119581535480", "adid":"0", "is":"0,0", "simid_info":null, "face_info":null, "xiangshi_info":null, "adPicId":"0", "pi":"0", "bdSetImgNum":0, "bdImgnewsDate":"1970-01-01 08:00", "fromPageTitle":"<strong>微距摄影<\/strong>照片", "fromPageTitleEnc":"微距摄影照片", "bdSourceName":"", "bdFromPageTitlePrefix":"", "token":"" }, .........................
从上面的返回结果可以看出,JSON对象中的data域是一个数组,其中的每一项为实际的图片数据。
例如,我们可以获取data中的objURL,然后根据此地址获得实际的图片。
我们看看这部分完整的示例代码:public class ImageFetcher { public List<GalleryItem> fetchItems() { //我们在GalleryItem中存储解析出的JSON数据 List<GalleryItem> items = new ArrayList<>(); try { String url = Uri.parse("http://image.baidu.com/search/index?") .buildUpon() .appendQueryParameter("tn", "resultjson") .appendQueryParameter("word", "微距摄影") .build().toString(); String jsonString = HttpUtil.getUrlString(url); //将得到的返回结果分装到JSONObject中 JSONObject jsonBody = new JSONObject(jsonString); //然后,解析JSONObject parseItems(items, jsonBody); } catch (JSONException | IOException e) { e.printStackTrace(); } return items; } private void parseItems(List<GalleryItem> items, JSONObject jsonBody) throws IOException, JSONException { //根据返回的JSON数据格式,我们知道“data”域对应JSONArray JSONArray dataArray = jsonBody.getJSONArray("data"); for (int i = 0; i < dataArray.length(); ++i) { JSONObject dataObject = dataArray.getJSONObject(i); GalleryItem item = new GalleryItem(); //保存JSONArray中每一项的objURL,利用该Url就可以获取实际的数据 item.setUrl(dataObject.getString("objURL")); items.add(item); } } }
获取URL后的下载及解析图片的内容,在此篇博客中就不再进一步叙述了。3、补充
上面获取JSON数据的方法实际上是不得已的“野路子”,如果百度图片修改了JSON结果的格式,那么代码也要随之修改。
一般正常情况下,应该使用云服务提供的API,然后按照API定义的JSON格式处理返回结果,例如使用Google、比应等提供的API接口。
不过为了使用云服务,必须申请对应的Api key,这就涉及到一些申请过程和收费了,具体的可以参考这些服务的说明文档。
使用云服务的好处在于:接口稳定,而且有一些便捷的方法可以使用,例如flickr提供的接口(这段代码的主要部分引用于Android权威指南):public void fetchItems() { try { String url = Uri.parse("https://api.flickr.com/services/rest/") .buildUpon() //这就是云服务便利的地方,提供了方法给客户端使用 .appendQueryParameter("method", "flickr.photos.getRecent") //这里需要填写申请到的api_key .appendQueryParameter("api_key", API_KEY) .appendQueryParameter("format", "json") ........... .build().toString(); String jsonString = HttpUtil.getUrlString(url); //得到结果后,按照云服务约定的方式,解析JSON对象,方法与上面的代码类似 .................... } catch(IOException ioe) { ............ } }4、使用GSON来简化json数据的解析
对于固定格式的json数据而言,每次都用上述方式,分析数据格式然后逐步解析比较繁琐。
幸好有现成的第三方库Gson可以使用。
Gson的使用比较简单,主要是按照Json的格式定义序列化的Bean对象。
以上面百度图片返回的结果为例:public class Response { //每个成员与Json中的key值一致 private String queryEnc; private String queryExt; private String listNum; private String displayNum; private String gsm; private String bdSearchTime; private String isNeedAsyncRequest; private String bdIsClustered; //保存Json中的data数组 private List<Data> data; public String getQueryEnc() { return queryEnc; } public void setQueryEnc(String queryEnc) { this.queryEnc = queryEnc; } public String getQueryExt() { return queryExt; } public void setQueryExt(String queryExt) { this.queryExt = queryExt; } public String getListNum() { return listNum; } public void setListNum(String listNum) { this.listNum = listNum; } public String getDisplayNum() { return displayNum; } public void setDisplayNum(String displayNum) { this.displayNum = displayNum; } public String getGsm() { return gsm; } public void setGsm(String gsm) { this.gsm = gsm; } public String getBdSearchTime() { return bdSearchTime; } public void setBdSearchTime(String bdSearchTime) { this.bdSearchTime = bdSearchTime; } public String getIsNeedAsyncRequest() { return isNeedAsyncRequest; } public void setIsNeedAsyncRequest(String isNeedAsyncRequest) { this.isNeedAsyncRequest = isNeedAsyncRequest; } public String getBdIsClustered() { return bdIsClustered; } public void setBdIsClustered(String bdIsClustered) { this.bdIsClustered = bdIsClustered; } public List<Data> getData() { return data; } public void setData(List<Data> data) { this.data = data; } }
同样,再定义一个Data对象:public class Data { //同样,Data中的成员与Json内data的key值一致 private String thumbURL; private String middleURL; private String hasLarge; private String objURL; private String fromURLHost; private String currentIndex; private String width; private String height; private String type; private String filesize; private String bdSrcType; private String di; private String adid; private String is; private String simid_info; private String face_info; private String xiangshi_ifno; private String adPicId; private String pi; private String bdSetImgNum; private String bdImgnewsDate; private String fromPageTitle; private String fromPageTitleEnc; private String bdSourceName; private String bdFromPageTitlePrefix; private String token; public String getThumbURL() { return thumbURL; } public void setThumbURL(String thumbURL) { this.thumbURL = thumbURL; } public String getMiddleURL() { return middleURL; } public void setMiddleURL(String middleURL) { this.middleURL = middleURL; } public String getHasLarge() { return hasLarge; } public void setHasLarge(String hasLarge) { this.hasLarge = hasLarge; } public String getObjURL() { return objURL; } public void setObjURL(String objURL) { this.objURL = objURL; } public String getFromURLHost() { return fromURLHost; } public void setFromURLHost(String fromURLHost) { this.fromURLHost = fromURLHost; } public String getCurrentIndex() { return currentIndex; } public void setCurrentIndex(String currentIndex) { this.currentIndex = currentIndex; } public String getWidth() { return width; } public void setWidth(String width) { this.width = width; } public String getHeight() { return height; } public void setHeight(String height) { this.height = height; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getFilesize() { return filesize; } public void setFilesize(String filesize) { this.filesize = filesize; } public String getBdSrcType() { return bdSrcType; } public void setBdSrcType(String bdSrcType) { this.bdSrcType = bdSrcType; } public String getDi() { return di; } public void setDi(String di) { this.di = di; } public String getAdid() { return adid; } public void setAdid(String adid) { this.adid = adid; } public String getIs() { return is; } public void setIs(String is) { this.is = is; } public String getSimid_info() { return simid_info; } public void setSimid_info(String simid_info) { this.simid_info = simid_info; } public String getFace_info() { return face_info; } public void setFace_info(String face_info) { this.face_info = face_info; } public String getXiangshi_ifno() { return xiangshi_ifno; } public void setXiangshi_ifno(String xiangshi_ifno) { this.xiangshi_ifno = xiangshi_ifno; } public String getAdPicId() { return adPicId; } public void setAdPicId(String adPicId) { this.adPicId = adPicId; } public String getPi() { return pi; } public void setPi(String pi) { this.pi = pi; } public String getBdSetImgNum() { return bdSetImgNum; } public void setBdSetImgNum(String bdSetImgNum) { this.bdSetImgNum = bdSetImgNum; } public String getBdImgnewsDate() { return bdImgnewsDate; } public void setBdImgnewsDate(String bdImgnewsDate) { this.bdImgnewsDate = bdImgnewsDate; } public String getFromPageTitle() { return fromPageTitle; } public void setFromPageTitle(String fromPageTitle) { this.fromPageTitle = fromPageTitle; } public String getFromPageTitleEnc() { return fromPageTitleEnc; } public void setFromPageTitleEnc(String fromPageTitleEnc) { this.fromPageTitleEnc = fromPageTitleEnc; } public String getBdSourceName() { return bdSourceName; } public void setBdSourceName(String bdSourceName) { this.bdSourceName = bdSourceName; } public String getBdFromPageTitlePrefix() { return bdFromPageTitlePrefix; } public void setBdFromPageTitlePrefix(String bdFromPageTitlePrefix) { this.bdFromPageTitlePrefix = bdFromPageTitlePrefix; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } }
Bean对象定义完毕后,就可以使用Gson了,示例如下:public class ImageFetcher { public List<GalleryItem> fetchItems() { List<GalleryItem> items = new ArrayList<>(); try { String url = Uri.parse("http://image.baidu.com/search/index?") .buildUpon() .appendQueryParameter("tn", "resultjson") .appendQueryParameter("word", "微距摄影") .build().toString(); String jsonString = HttpUtil.getUrlString(url); //创建Gson Gson gson = new Gson(); //Gson按照Response中的定义,将字符串解析成Response对象 Response response = gson.fromJson(jsonString, Response.class); parseItems(items, response); } catch (JSONException | IOException e) { e.printStackTrace(); } return items; } private void parseItems(List<GalleryItem> items, Response response) throws IOException, JSONException { //然后就可以直接调用对象的接口得到需要的数据了 List<Data> dataList = response.getData(); for (Data data : dataList) { GalleryItem item = new GalleryItem(); item.setUrl(data.getObjURL()); items.add(item); } } }
相关文章推荐
- 学习笔记 Tianmao 篇 OkHttp 网络的使用的简单封装 获取Json用GSON来解析
- Android JSON数据格式的解析,与简单对象、带泛型的List和Map的转换,以及GSON的使用
- Android 获取网络数据(使用fastjson-1.2.3.jar 包)
- 学习笔记 Tianmao 篇 使用简单封装后的自定义OkHttp 获取json被GSON解析后的数据
- 使用基于Android网络通信的OkHttp库实现Get和Post方式简单操作服务器JSON格式数据
- Android 超简单音乐播放器(九)搜索网络歌曲,获得热门榜单(GridView)(易源api的使用)(JSON的解析)(刷新)
- Android使用AsyncTask异步线程网络通信获取数据(get json)
- 【android初级】之Android之从网络上获取数据(图片,网页,xml,json等)
- Android中通过网络获取json数据来播放视频
- android利用http从网络获取数据并存储或解析
- Android使用Json获取数据实例【这个例子不太好,仅作参考】
- Android利用Json来进行网络数据传输
- Android中使用Gson解析JSON数据的两种方法
- Android中使用Gson解析JSON数据
- android 从网络上获取数据(图片,网页,xml,json等)
- Android之从网络中获取数据并返回客户端的两种方式:XML格式返回与Json格式返回
- Android 使用JSON进行网络数据交换
- Android获取网络XML/JSON数据
- android:通过url向网络端获取json格式数据并解析显示
- Android使用JSON进行网络数据交换