Android处理服务器返回的图片数据

由于最近在做的一个游戏项目有一个排行榜,

排行榜是一个列表,界面大致如下:

 

排名     人物名称     头像图片     分数

排名     人物名称     头像图片     分数

排名     人物名称     头像图片     分数

排名     人物名称     头像图片     分数

排名     人物名称     头像图片     分数

排名     人物名称     头像图片     分数

 

排行     人物名称     头像图片     分数

 

列表中有100条数据,列表下面有一个

控件显示游戏玩家自己的排名信息

 

需求如下:

每次进入排行榜界面,则将游戏玩家的

人物名称和分数提交到服务端,服务端

接收请求后对数据库中的数据进行排序,

取得前100名的数据,还有一条游戏玩家

的数据,总共101条数据,由于客户端

还需要下载头像图片,所以返回的数据

还有头像图片的下载地址,服务端将所有

的数据包装成一个Json数据返回给客户端

大致格式如下:

 

[html]  view plain copy
  1. {"rank":  
  2. [  
  3. {"person":"\u66f9\u64cd","index":1,"score":35852},  
  4. {"person":"\u66f9\u64cd","index":2,"score":32563},  
  5. {"person":"\u5b59\u6743","index":3,"score":10000},  
  6. {"person":"\u5218\u5907","index":4,"score":9638},  
  7. {"person":"\u5218\u5907","index":5,"score":8888},  
  8. {"person":"\u5b59\u6743","index":6,"score":8886},  
  9. {"person":"\u5218\u5907","index":7,"score":7865},  
  10. {"person":"\u5218\u5907","index":8,"score":6950},  
  11. {"person":"\u5218\u5907","index":9,"score":6548},  
  12. {"person":"\u5218\u5907","index":10,"score":6540},  
  13. {"person":"\u66f9\u64cd","index":11,"score":5288}  
  14. ],  
  15.   
  16.   
  17. "base":"(服务端地址)",  
  18.   
  19. "head":  
  20. [  
  21. {"person":"\u66f9\u64cd","filename":"\/caocao\/20130718185726036.png", "size":12343},  
  22.   
  23. {"person":"\u5b59\u6743","filename":"\/sunqun\/20130718185726046.png", "size":12343},  
  24.   
  25. {"person":"\u5218\u5907","filename":"\/liubei\/20130718185726056.png", "size":12343}  
  26. ]  
  27. }  

 


rank的每个对象包括:人物名称,排名,分数

head的每个对象包括:人物名称,头像图片名称

base为服务端地址

 

大致流程如下:

1.进入排行榜界面,将游戏玩家的数据发送到服务端

2.取得服务端返回的Json数据,解析出rank数组,head数组和base字符串

3.使用头像图片路径下载头像图片到本地

4.新建一个ResultMessage类,属性包括:排名,人物名称,本地头像图片地址,分数

5.在解析rank数组时实例化ResultMessage,添加到List中并返回出去

 

主要有三个类:LoadImage.java,ResultMessage.java,Upload.java

 

LoadImage.java用于下载头像图片,由于每次进入排行榜界面都会向

服务端发送请求,每次都会返回头像图片的下载地址,所以需要

做下判断本地是否已经有此图片存在,还有就是判断图片大小是否

正确,因为会有这样一种情况,在下载图片时突然网络断开,这时

头像图片没有下载完整,下次进入排行榜界面的时候又向服务端

发送请求,又下载头像图片,此时程序判断出本地已经有此图片

存在,所以不会再下载图片,但是图片不完整,无法正常使用,

所以除了判断本地是否有图片之外,还需要判断图片的大小是不是

跟服务端发过来的大小一样,只有图片存在,并且大小一样的时候

才不下载图片

 

具体代码如下:

[html]  view plain copy
  1. package com.joye3g.http;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.net.HttpURLConnection;  
  8. import java.net.URL;  
  9.   
  10. import org.apache.http.HttpStatus;  
  11.   
  12. public class LoadImage {  
  13.   
  14.     private static final int SUCCES = 1;//下载成功  
  15.     private static final int ERRO = -1;//下载失败  
  16.     private static final int EXIST = 0;//文件已存在  
  17.     private static int result = EXIST;//返回的下载结果  
  18.     private String localPath;//本地路径  
  19.       
  20.     public LoadImage(String localPath) {  
  21.         this.localPath = localPath;  
  22.     }  
  23.   
  24.     /**  
  25.      * @param urlPathPrefix       网址前缀  
  26.      * @param filename            文件名  
  27.      * @param size                文件大小  
  28.      * @return  
  29.      * @throws IOException  
  30.      */  
  31.     public int download(String urlPathPrefix, String filename, long size) throws IOException{  
  32.         String filePath = localPath + File.separator + filename.substring(filename.lastIndexOf("/") + 1);  
  33.         //判断filePath路径下有没有此图片存在,大小是否相同,如果不存在,则发送Http请求下载图片,存在则不下载  
  34.         if(isFileExist(filePath) && isSizeSame(filePath, size)){  
  35.             return result = EXIST;  
  36.         }else{  
  37.             //从URL中取得输入流  
  38.             InputStream is = getHttpInputStream(urlPathPrefix + filename);  
  39.             //创建新文件  
  40.             File file = createFile(filePath);  
  41.             //下载图片  
  42.             if(is != null) downLoadImage(file, is);    
  43.         }  
  44.         return result;  
  45.     }  
  46.   
  47.     /**  
  48.      * 下载图片  
  49.      * @param file  文件  
  50.      * @param is    从URL取得的输入流  
  51.      */  
  52.     private void downLoadImage(File file, InputStream is){  
  53.         FileOutputStream fs = null;  
  54.         try {  
  55.             fs = new FileOutputStream(file);  
  56.             byte[] buffer = new byte[4 * 1024];  
  57.             int len = 0;  
  58.             while((len = is.read(buffer)) != -1){  
  59.                 fs.write(buffer, 0, len);  
  60.             }  
  61.             fs.flush();  
  62.             result = SUCCES;  
  63.         } catch (Exception e) {  
  64.             result = ERRO;  
  65.             e.printStackTrace();  
  66.         }finally{  
  67.             try {  
  68.                 if(fs != null){  
  69.                     fs.close();  
  70.                 }  
  71.                 if(is != null){  
  72.                     is.close();  
  73.                 }  
  74.             } catch (IOException e) {  
  75.                 e.printStackTrace();  
  76.             }  
  77.         }  
  78.     }  
  79.   
  80.     /**  
  81.      * 根据URL取得输入流  
  82.      * @param urlPath   网络路径  
  83.      * @return  
  84.      * @throws IOException  
  85.      */  
  86.     private InputStream getHttpInputStream(String urlPath) throws IOException{  
  87.         URL url = new URL(urlPath);  
  88.         HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  89.         if(conn.getResponseCode() == HttpStatus.SC_OK) {  
  90.             return conn.getInputStream();  
  91.         }  
  92.         return null;  
  93.     }  
  94.   
  95.     /**  
  96.      * 判断文件是否已经存在  
  97.      * @param fileName     文件路径  
  98.      * @return  
  99.      */  
  100.     private boolean isFileExist(String fileName){  
  101.         File file = new File(fileName);  
  102.         return file.exists();  
  103.     }  
  104.   
  105.     /**  
  106.      * 在指定路径下创建新文件  
  107.      * @param fileName      文件路径  
  108.      * @return  
  109.      * @throws IOException  
  110.      */  
  111.     private File createFile(String fileName) throws IOException{  
  112.         File file = new File(fileName);  
  113.         if(!file.createNewFile()){  
  114.             file.delete();  
  115.             file.createNewFile();  
  116.         }  
  117.         return file;  
  118.     }  
  119.       
  120.     /**  
  121.      * 若文件已存在,判断文件大小是否正确  
  122.      * @param filePath         图片路径  
  123.      * @param size             文件大小  
  124.      * @return  
  125.      */  
  126.     private boolean isSizeSame(String filePath, long size){  
  127.         File file = new File(filePath);  
  128.         return file.length() == size;  
  129.     }  
  130. }  


 

ResultMessage.java具体代码如下:

[html]  view plain copy
  1. package com.joye3g.http;  
  2.   
  3. public class ResultMessage {  
  4.       
  5.     private int index;  
  6.     private String name;  
  7.     private int score;  
  8.     private String imagePath;  
  9.       
  10.     public ResultMessage(int index, String name, int score, String imagePath) {  
  11.         this.index = index;  
  12.         this.name = name;  
  13.         this.score = score;  
  14.         this.imagePath = imagePath;  
  15.     }  
  16.   
  17.     public String getImagePath() {  
  18.         return imagePath;  
  19.     }  
  20.   
  21.     public void setImagePath(String imagePath) {  
  22.         this.imagePath = imagePath;  
  23.     }  
  24.   
  25.     public int getIndex() {  
  26.         return index;  
  27.     }  
  28.   
  29.     public void setIndex(int index) {  
  30.         this.index = index;  
  31.     }  
  32.   
  33.     public String getName() {  
  34.         return name;  
  35.     }  
  36.   
  37.     public void setName(String name) {  
  38.         this.name = name;  
  39.     }  
  40.   
  41.     public int getScore() {  
  42.         return score;  
  43.     }  
  44.   
  45.     public void setScore(int score) {  
  46.         this.score = score;  
  47.     }  
  48. }  


 

UpLoad.java用于向服务端发送请求并接受返回的数据,

对返回的数据进行包装再返回出去,首先在构造函数中

传入要上传到服务端的人物名称,分数和上下文对象,

上下文对象主要用于取得程序的安装路径和UUID,

使用方法很简单:

UpLoad upload = new UpLoad("曹操", 23456, getApplicationContext());

List<ResultMessage> messages  = upload.post("服务端地址");

 

UpLoad.java具体代码如下:

[html]  view plain copy
  1. package com.joye3g.http;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.DataOutputStream;  
  5. import java.io.File;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.net.HttpURLConnection;  
  10. import java.net.URL;  
  11. import java.util.ArrayList;  
  12. import java.util.HashMap;  
  13. import java.util.List;  
  14. import java.util.Map;  
  15. import java.util.UUID;  
  16. import java.util.zip.GZIPInputStream;  
  17. import org.apache.http.HttpStatus;  
  18. import org.json.JSONArray;  
  19. import org.json.JSONException;  
  20. import org.json.JSONObject;  
  21.   
  22. import android.content.Context;  
  23. import android.telephony.TelephonyManager;  
  24.   
  25. /**  
  26.  * @author ZLQ  
  27.  *  
  28.  */  
  29. public class Upload {  
  30.   
  31.     private static final String GZIP = "gzip";  
  32.     private Context context;  
  33.     private JSONObject jsonData;  
  34.   
  35.     /**  
  36.      * 构造函数  
  37.      * @param name  
  38.      *            要上传的人物名称  
  39.      * @param score  
  40.      *            要上传的分数  
  41.      * @param context  
  42.      *            上下文对象,用于取得UUID和本地路径  
  43.      */  
  44.     public Upload(String name, int score, Context context) {  
  45.   
  46.         jsonData = new JSONObject();  
  47.         this.context = context;  
  48.   
  49.         try {  
  50.             jsonData.put("person", name);  
  51.             jsonData.put("uploaduser", getUUID());  
  52.             jsonData.put("score", score);  
  53.         } catch (JSONException e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.     }  
  57.   
  58.     /**  
  59.      * 发送post请求  
  60.      * @param url  
  61.      *            URL路径  
  62.      * @return 返回一个List<Message>链表  
  63.      */  
  64.     public List<ResultMessage> post(String url) {  
  65.         List<ResultMessage> messages = null;  
  66.         try {  
  67.             messages = sendHttpResponse(url);  
  68.         } catch (Exception e) {  
  69.             e.printStackTrace();  
  70.         }  
  71.         return messages;  
  72.     }  
  73.   
  74.     /**  
  75.      * 发送请求,返回结果  
  76.      * @param url  
  77.      *            URL路径  
  78.      * @return 返回一个List<Message>链表  
  79.      * @throws JSONException  
  80.      * @throws Exception  
  81.      */  
  82.     private List<ResultMessage> sendHttpResponse(String url)  
  83.             throws IOException, JSONException {  
  84.         URL uri = new URL(url);  
  85.         HttpURLConnection conn = (HttpURLConnection) uri.openConnection();  
  86.         conn.setRequestMethod("POST"); // Post方式  
  87.         conn.setDoOutput(true);// 允许输出  
  88.         conn.setRequestProperty("connection", "keep-alive"); // 客户端到服务器端的连接持续有效  
  89.         conn.setRequestProperty("Content-Type", "application/x-javascript; charset=UTF-8");  
  90.         conn.setRequestProperty("accept-encoding", "gzip,deflate");//设置 gzip的请求头   
  91.         DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());  
  92.         outStream.write(jsonData.toString().getBytes());//将数据内容写入到流中  
  93.         outStream.flush();  
  94.         outStream.close();  
  95.         return getReturnMessage(conn);//返回服务端返回的结果  
  96.     }  
  97.   
  98.     /**  
  99.      * 取得服务端返回的结果  
  100.      * @param conn  
  101.      * @return  
  102.      * @throws IOException  
  103.      * @throws JSONException  
  104.      */  
  105.     private List<ResultMessage> getReturnMessage(HttpURLConnection conn)  
  106.             throws IOException, JSONException {  
  107.   
  108.         List<ResultMessage> messages = null;  
  109.         String content_encode = conn.getContentEncoding();  
  110.         String content = null;  
  111.   
  112.         if (conn.getResponseCode() == HttpStatus.SC_OK) {  
  113.             if (null != content_encode && !"".equals(content_encode)  
  114.                     && content_encode.equals(GZIP)) {  
  115.                 //对服务端返回的内容进行解压  
  116.                 content = unGzip(conn.getInputStream());  
  117.             }  
  118.   
  119.             JSONObject objMain = new JSONObject(content);  
  120.             JSONArray ranks = objMain.getJSONArray("rank");//取得rank数组  
  121.             JSONArray heads = objMain.getJSONArray("head");//取得head数组  
  122.             String base = objMain.getString("base");//取得地址前缀  
  123.   
  124.             LoadImage load = new LoadImage(getLocalPath());  
  125.             Map<String, String> map = new HashMap<String, String>();  
  126.   
  127.             //取得heads数组中的对象  
  128.             for (int i = 0; i < heads.length(); i++) {  
  129.                 JSONObject head = heads.getJSONObject(i);  
  130.                 String person = head.getString("person");  
  131.                 String filename = head.getString("filename");  
  132.                 long size = head.getLong("size");  
  133.                 map.put(person, filename);  
  134.                 load.download(base, filename, size);//下载图片  
  135.             }  
  136.   
  137.             //取得除去最后一条的所有数据  
  138.             messages = new ArrayList<ResultMessage>();  
  139.             for (int i = 0; i < ranks.length() - 1; i++) {  
  140.                 JSONObject rankObj = ranks.getJSONObject(i);  
  141.                 messages.add(rank(rankObj, map));  
  142.             }  
  143.   
  144.             //取得最后一个数据  
  145.             JSONObject rankObj = ranks.getJSONObject(ranks.length() - 1);  
  146.             messages.add(rank(rankObj, map));  
  147.         }  
  148.         conn.disconnect();  
  149.         return messages;  
  150.     }  
  151.   
  152.     // 解析数据  
  153.     private ResultMessage rank(JSONObject rank, Map<String, String> map)  
  154.             throws JSONException {  
  155.         int num = rank.getInt("index");  
  156.         String person = rank.getString("person");  
  157.         String filename = map.get(person);  
  158.         //拼接本地图片路径  
  159.         String imagePath = getLocalPath() + File.separator  
  160.                 + filename.substring(filename.lastIndexOf("/") + 1);  
  161.         int score = rank.getInt("score");  
  162.         //实例化一个ResultMessage对象  
  163.         ResultMessage message = new ResultMessage(num, person, score, imagePath);  
  164.         return message;  
  165.     }  
  166.   
  167.     /**  
  168.      * 对服务器返回的内容进行解压并返回解压后的内容  
  169.      * @param is  
  170.      * @return  
  171.      * @throws IOException  
  172.      * @throws UnsupportedEncodingException  
  173.      */  
  174.     private static String unGzip(InputStream is) throws IOException,  
  175.     UnsupportedEncodingException {  
  176.         GZIPInputStream in = new GZIPInputStream(is);  
  177.         ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();  
  178.         int len = -1;  
  179.         byte[] buffer = new byte[1024];  
  180.         while ((len = in.read(buffer)) != -1) {  
  181.             arrayOutputStream.write(buffer, 0, len);  
  182.         }  
  183.         in.close();  
  184.         arrayOutputStream.close();  
  185.         is.close();  
  186.         return new String(arrayOutputStream.toByteArray(), "utf-8");  
  187.     }  
  188.   
  189.     /**  
  190.      * 返回UUID  
  191.      * @return  
  192.      */  
  193.     private String getUUID() {  
  194.         final TelephonyManager tm = (TelephonyManager) context  
  195.                 .getSystemService(Context.TELEPHONY_SERVICE);  
  196.         final String tmDevice, tmSerial, androidId;  
  197.         tmDevice = "" + tm.getDeviceId();  
  198.         tmSerial = "" + tm.getSimSerialNumber();  
  199.         androidId = ""  
  200.                 + android.provider.Settings.Secure.getString(  
  201.                         context.getContentResolver(),  
  202.                         android.provider.Settings.Secure.ANDROID_ID);  
  203.   
  204.         UUID deviceUUID = new UUID(androidId.hashCode(),  
  205.                 ((long) tmDevice.hashCode() << 32 | tmSerial.hashCode()));  
  206.         return deviceUUID.toString();  
  207.     }  
  208.   
  209.     /**  
  210.      * 返回应用程序的安装路径  
  211.      * @return  
  212.      */  
  213.     private String getLocalPath() {  
  214.         return context.getApplicationContext().getFilesDir().getAbsolutePath();  
  215.     }  
  216. }  


 

返回的messages中的每个对象的格式为:

排名,人物名称,本地头像图片的路径,分数

 

小结:

UUID,是手机的唯一标识,服务端通过UUID判断是否是同个用户提交数据

本地路径,程序安装在手机中,用户有可能会将程序移动到其他地方,所以数据,

如图片,数据文件等等文件应该放在程序路径下,这样程序移动时数据会一起

移动,不会出现程序移动后之前的数据找不到

GZIPInputStream,数据在网络中传递,速度和流量是一个重要方面,所以服务端应该先

将数据进行压缩再发送到客户端,客户端接收后再进行解压缩,这样可以减少流量开支

除此之外,通过网络传输数据,最好是对数据进行加密,保证安全性和完整性

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值