您的位置:首页 > 移动开发 > Android开发

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

2015-11-06 16:50 567 查看
由于最近在做的一个游戏项目有一个排行榜,

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

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

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

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

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

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

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

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

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

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

需求如下:

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

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

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

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

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

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

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

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

大致格式如下:

[html] view
plaincopy

{"rank":

[

{"person":"\u66f9\u64cd","index":1,"score":35852},

{"person":"\u66f9\u64cd","index":2,"score":32563},

{"person":"\u5b59\u6743","index":3,"score":10000},

{"person":"\u5218\u5907","index":4,"score":9638},

{"person":"\u5218\u5907","index":5,"score":8888},

{"person":"\u5b59\u6743","index":6,"score":8886},

{"person":"\u5218\u5907","index":7,"score":7865},

{"person":"\u5218\u5907","index":8,"score":6950},

{"person":"\u5218\u5907","index":9,"score":6548},

{"person":"\u5218\u5907","index":10,"score":6540},

{"person":"\u66f9\u64cd","index":11,"score":5288}

],

"base":"(服务端地址)",

"head":

[

{"person":"\u66f9\u64cd","filename":"\/caocao\/20130718185726036.png", "size":12343},

{"person":"\u5b59\u6743","filename":"\/sunqun\/20130718185726046.png", "size":12343},

{"person":"\u5218\u5907","filename":"\/liubei\/20130718185726056.png", "size":12343}

]

}

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
plaincopy

package com.joye3g.http;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import org.apache.http.HttpStatus;

public class LoadImage {

private static final int SUCCES = 1;//下载成功

private static final int ERRO = -1;//下载失败

private static final int EXIST = 0;//文件已存在

private static int result = EXIST;//返回的下载结果

private String localPath;//本地路径

public LoadImage(String localPath) {

this.localPath = localPath;

}

/**

* @param urlPathPrefix 网址前缀

* @param filename 文件名

* @param size 文件大小

* @return

* @throws IOException

*/

public int download(String urlPathPrefix, String filename, long size) throws IOException{

String filePath = localPath + File.separator + filename.substring(filename.lastIndexOf("/") + 1);

//判断filePath路径下有没有此图片存在,大小是否相同,如果不存在,则发送Http请求下载图片,存在则不下载

if(isFileExist(filePath) && isSizeSame(filePath, size)){

return result = EXIST;

}else{

//从URL中取得输入流

InputStream is = getHttpInputStream(urlPathPrefix + filename);

//创建新文件

File file = createFile(filePath);

//下载图片

if(is != null) downLoadImage(file, is);

}

return result;

}

/**

* 下载图片

* @param file 文件

* @param is 从URL取得的输入流

*/

private void downLoadImage(File file, InputStream is){

FileOutputStream fs = null;

try {

fs = new FileOutputStream(file);

byte[] buffer = new byte[4 * 1024];

int len = 0;

while((len = is.read(buffer)) != -1){

fs.write(buffer, 0, len);

}

fs.flush();

result = SUCCES;

} catch (Exception e) {

result = ERRO;

e.printStackTrace();

}finally{

try {

if(fs != null){

fs.close();

}

if(is != null){

is.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

* 根据URL取得输入流

* @param urlPath 网络路径

* @return

* @throws IOException

*/

private InputStream getHttpInputStream(String urlPath) throws IOException{

URL url = new URL(urlPath);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

if(conn.getResponseCode() == HttpStatus.SC_OK) {

return conn.getInputStream();

}

return null;

}

/**

* 判断文件是否已经存在

* @param fileName 文件路径

* @return

*/

private boolean isFileExist(String fileName){

File file = new File(fileName);

return file.exists();

}

/**

* 在指定路径下创建新文件

* @param fileName 文件路径

* @return

* @throws IOException

*/

private File createFile(String fileName) throws IOException{

File file = new File(fileName);

if(!file.createNewFile()){

file.delete();

file.createNewFile();

}

return file;

}

/**

* 若文件已存在,判断文件大小是否正确

* @param filePath 图片路径

* @param size 文件大小

* @return

*/

private boolean isSizeSame(String filePath, long size){

File file = new File(filePath);

return file.length() == size;

}

}

ResultMessage.java具体代码如下:

[html] view
plaincopy

package com.joye3g.http;

public class ResultMessage {

private int index;

private String name;

private int score;

private String imagePath;

public ResultMessage(int index, String name, int score, String imagePath) {

this.index = index;

this.name = name;

this.score = score;

this.imagePath = imagePath;

}

public String getImagePath() {

return imagePath;

}

public void setImagePath(String imagePath) {

this.imagePath = imagePath;

}

public int getIndex() {

return index;

}

public void setIndex(int index) {

this.index = index;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getScore() {

return score;

}

public void setScore(int score) {

this.score = score;

}

}

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

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

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

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

使用方法很简单:

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

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

UpLoad.java具体代码如下:

[html] view
plaincopy

package com.joye3g.http;

import java.io.ByteArrayOutputStream;

import java.io.DataOutputStream;

import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.io.UnsupportedEncodingException;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.UUID;

import java.util.zip.GZIPInputStream;

import org.apache.http.HttpStatus;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import android.content.Context;

import android.telephony.TelephonyManager;

/**

* @author ZLQ

*

*/

public class Upload {

private static final String GZIP = "gzip";

private Context context;

private JSONObject jsonData;

/**

* 构造函数

* @param name

* 要上传的人物名称

* @param score

* 要上传的分数

* @param context

* 上下文对象,用于取得UUID和本地路径

*/

public Upload(String name, int score, Context context) {

jsonData = new JSONObject();

this.context = context;

try {

jsonData.put("person", name);

jsonData.put("uploaduser", getUUID());

jsonData.put("score", score);

} catch (JSONException e) {

e.printStackTrace();

}

}

/**

* 发送post请求

* @param url

* URL路径

* @return 返回一个List<Message>链表

*/

public List<ResultMessage> post(String url) {

List<ResultMessage> messages = null;

try {

messages = sendHttpResponse(url);

} catch (Exception e) {

e.printStackTrace();

}

return messages;

}

/**

* 发送请求,返回结果

* @param url

* URL路径

* @return 返回一个List<Message>链表

* @throws JSONException

* @throws Exception

*/

private List<ResultMessage> sendHttpResponse(String url)

throws IOException, JSONException {

URL uri = new URL(url);

HttpURLConnection conn = (HttpURLConnection) uri.openConnection();

conn.setRequestMethod("POST"); // Post方式

conn.setDoOutput(true);// 允许输出

conn.setRequestProperty("connection", "keep-alive"); // 客户端到服务器端的连接持续有效

conn.setRequestProperty("Content-Type", "application/x-javascript; charset=UTF-8");

conn.setRequestProperty("accept-encoding", "gzip,deflate");//设置 gzip的请求头

DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());

outStream.write(jsonData.toString().getBytes());//将数据内容写入到流中

outStream.flush();

outStream.close();

return getReturnMessage(conn);//返回服务端返回的结果

}

/**

* 取得服务端返回的结果

* @param conn

* @return

* @throws IOException

* @throws JSONException

*/

private List<ResultMessage> getReturnMessage(HttpURLConnection conn)

throws IOException, JSONException {

List<ResultMessage> messages = null;

String content_encode = conn.getContentEncoding();

String content = null;

if (conn.getResponseCode() == HttpStatus.SC_OK) {

if (null != content_encode && !"".equals(content_encode)

&& content_encode.equals(GZIP)) {

//对服务端返回的内容进行解压

content = unGzip(conn.getInputStream());

}

JSONObject objMain = new JSONObject(content);

JSONArray ranks = objMain.getJSONArray("rank");//取得rank数组

JSONArray heads = objMain.getJSONArray("head");//取得head数组

String base = objMain.getString("base");//取得地址前缀

LoadImage load = new LoadImage(getLocalPath());

Map<String, String> map = new HashMap<String, String>();

//取得heads数组中的对象

for (int i = 0; i < heads.length(); i++) {

JSONObject head = heads.getJSONObject(i);

String person = head.getString("person");

String filename = head.getString("filename");

long size = head.getLong("size");

map.put(person, filename);

load.download(base, filename, size);//下载图片

}

//取得除去最后一条的所有数据

messages = new ArrayList<ResultMessage>();

for (int i = 0; i < ranks.length() - 1; i++) {

JSONObject rankObj = ranks.getJSONObject(i);

messages.add(rank(rankObj, map));

}

//取得最后一个数据

JSONObject rankObj = ranks.getJSONObject(ranks.length() - 1);

messages.add(rank(rankObj, map));

}

conn.disconnect();

return messages;

}

// 解析数据

private ResultMessage rank(JSONObject rank, Map<String, String> map)

throws JSONException {

int num = rank.getInt("index");

String person = rank.getString("person");

String filename = map.get(person);

//拼接本地图片路径

String imagePath = getLocalPath() + File.separator

+ filename.substring(filename.lastIndexOf("/") + 1);

int score = rank.getInt("score");

//实例化一个ResultMessage对象

ResultMessage message = new ResultMessage(num, person, score, imagePath);

return message;

}

/**

* 对服务器返回的内容进行解压并返回解压后的内容

* @param is

* @return

* @throws IOException

* @throws UnsupportedEncodingException

*/

private static String unGzip(InputStream is) throws IOException,

UnsupportedEncodingException {

GZIPInputStream in = new GZIPInputStream(is);

ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

int len = -1;

byte[] buffer = new byte[1024];

while ((len = in.read(buffer)) != -1) {

arrayOutputStream.write(buffer, 0, len);

}

in.close();

arrayOutputStream.close();

is.close();

return new String(arrayOutputStream.toByteArray(), "utf-8");

}

/**

* 返回UUID

* @return

*/

private String getUUID() {

final TelephonyManager tm = (TelephonyManager) context

.getSystemService(Context.TELEPHONY_SERVICE);

final String tmDevice, tmSerial, androidId;

tmDevice = "" + tm.getDeviceId();

tmSerial = "" + tm.getSimSerialNumber();

androidId = ""

+ android.provider.Settings.Secure.getString(

context.getContentResolver(),

android.provider.Settings.Secure.ANDROID_ID);

UUID deviceUUID = new UUID(androidId.hashCode(),

((long) tmDevice.hashCode() << 32 | tmSerial.hashCode()));

return deviceUUID.toString();

}

/**

* 返回应用程序的安装路径

* @return

*/

private String getLocalPath() {

return context.getApplicationContext().getFilesDir().getAbsolutePath();

}

}

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

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

小结:

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

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

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

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

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

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

除此之外,通过网络传输数据,最好是对数据进行加密,保证安全性和完整性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: