<b>Android</b><b>實時繪制效果</b>
<b>一、概述</b>
通過長連接配接的Socket通信,實時發送繪制資訊給各用戶端,以實作實時顯示效果。
<b>二、運作效果</b>
<b>三、功能代碼</b>
<b>1</b><b>)通信部分</b>
長連接配接的Socket通信,支援多用戶端。伺服器和用戶端都可主動發送消息。消息的話,将Object轉成了json字元串了。
ps:不想轉json,還是想用ObjectOutputStream發送的,可參照《Java Socket通信》長連接配接通信内的對象消息樣例。
1.1)EasyServer.java
/**
* 長連接配接、1對n主動發消息的伺服器
*
* @author Join
*/
public class EasyServer extends Thread {
/** 退出指令 */
public static final String EXIT_COMMAND = "end";
/** 服務端口 */
private int port;
/** 服務套接字 */
private ServerSocket mServerSocket;
/** 線程池 */
private ExecutorService pool;
/** 用戶端套接字集合 */
private ArrayList<Socket> mClientList;
/** 伺服器監聽接口 */
private OnServerListener listener;
public EasyServer(int port) {
this.port = port;
pool = Executors.newCachedThreadPool(); // 緩存線程池
mClientList = new ArrayList<Socket>();
}
@Override
public void run() {
try {
mServerSocket = new ServerSocket(port); // 建立本地特定端口伺服器套接字
Socket client = null;
while (true) {
client = mServerSocket.accept(); // 接收連接配接的套接字
mClientList.add(client); // 加入用戶端清單
if (null != listener) {
listener.onClientConnected(client.getInetAddress());
}
pool.execute(new ThreadServer(client)); // 新線程執行任務
}
} catch (BindException e) { // 端口使用中
if (null != listener) {
listener.onBindException();
} catch (IOException e) {
e.printStackTrace();
}
/** 各個連接配接用戶端的服務線程 */
private class ThreadServer extends Thread {
private Socket client;
public ThreadServer(Socket client) {
this.client = client;
@Override
public void run() {
DataInputStream in = null;
try {
in = new DataInputStream(client.getInputStream());
while (true) {
/* 接收資料消息 */
String msg = in.readUTF();
if (EXIT_COMMAND.equals(msg)) {
/* 接收退出指令時,處理退出 */
DataOutputStream out = new DataOutputStream(
client.getOutputStream());
out.writeUTF(EXIT_COMMAND); // 再傳回至用戶端,使得退出循環
out.flush();
if (null != listener) {
listener.onExited(client.getInetAddress());
}
break;
} else {
/* 否則,處理接收消息*/
listener.onReceive(client.getInetAddress(), msg);
}
/* 回複或轉發已接收資料 */
} catch (SocketException e) { // Connection reset
listener.onSocketException(client.getInetAddress());
} catch (IOException e) {
e.printStackTrace();
} finally {
mClientList.remove(client); // 移除目前用戶端
try {
if (null != in) {
in.close();
if (null != client) {
client.close();
} catch (IOException e) {
e.printStackTrace();
/** 向用戶端群發資訊 */
public void sendMessage(String msg) {
int i = 0;
DataOutputStream out = null;
for (; i < mClientList.size(); i++) {
out = new DataOutputStream(mClientList.get(i).getOutputStream());
out.writeUTF(msg);
out.flush();
} catch (SocketException e) { // Connection reset
if (null != listener && mClientList.size() > 0) {
listener.onSocketException(mClientList.get(i).getInetAddress());
mClientList.remove(i); // 移除出異常的那個用戶端
/** 設定伺服器監聽接口 */
public void setOnServerListener(OnServerListener listener) {
this.listener = listener;
}
1.2)EasyClient.java
* 接收和發送消息的用戶端
public class EasyClient extends Thread {
(還報8W字元備援,受不住了,就這麼着吧T^T)...
1.3)JsonUtil.java<b></b>
public class JsonUtil {
/**
* 解析Object成為json
*
* @param obj 對象
* @return json字元串
*/
public static String objToJson(Object obj) {
JSONStringer arrayJson = new JSONStringer(); // Json構造對象
Class<?> clazz = obj.getClass(); // 擷取對象運作時類
arrayJson.array().value(clazz.getName()); // 建立數組,第一位存放類名
JSONStringer objJson = new JSONStringer(); // Json構造對象
objJson.object();
Field[] fields = clazz.getDeclaredFields(); // 傳回類聲明的所有字段
for (Field field : fields) {
field.setAccessible(true); // 設定變量可通路
objJson.key(field.getName()).value(field.get(obj));
objJson.endObject();
arrayJson.value(objJson).endArray(); // 第二位存放類對象
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (JSONException e) {
return arrayJson.toString();
* 解析json成為Object
* @param json json字元串
* @return 對象
* @warning 由于是使用newInstance()建構執行個體,自己寫構造函數時要顯式寫明預設構造函數
public static Object jsonToObj(String json) {
Object obj = null;
JSONArray jarray = new JSONArray(json);
String className = jarray.getString(0); // 獲得第一位類名
Class<?> clazz = Class.forName(className); // 載入該類
obj = clazz.newInstance(); // 建構執行個體
JSONObject jobj = new JSONObject(jarray.getString(1)); // 獲得第二位類對象
@SuppressWarnings("unchecked")
Iterator<String> it = jobj.keys();
Field field;
while (it.hasNext()) {
String key = it.next();
field = clazz.getDeclaredField(key);
setValue(obj, field, jobj.getString(key));
} catch (Exception e) {
return obj;
* 給字段設值
* @param field 字段
* @param value 值
private static void setValue(Object obj, Field field, String value)
throws IllegalArgumentException, IllegalAccessException {
...
<a target="_blank" href="http://vaero.blog.51cto.com/4350852/893887">Android實時繪制效果(二)(附件工程在該篇内)</a>
本文轉自winorlose2000 51CTO部落格,原文連結:http://blog.51cto.com/vaero/893886,如需轉載請自行聯系原作者