Android實時繪製效果
ps:不想轉json,還是想用ObjectOutputStream發送的,可參照《Java Socket通信》長連接通信內的對象消息樣例。
- /**
- * 長連接、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 {
- /* 否則,處理接收消息*/
- if (null != listener) {
- listener.onReceive(client.getInetAddress(), msg);
- }
- }
- /* 回覆或轉發已接收數據 */
- }
- } catch (SocketException e) { // Connection reset
- if (null != listener) {
- 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;
- try {
- 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); // 移除出異常的那個客戶端
- } catch (IOException e) {
- e.printStackTrace();
- mClientList.remove(i); // 移除出異常的那個客戶端
- }
- }
- /** 設置服務器監聽接口 */
- public void setOnServerListener(OnServerListener listener) {
- this.listener = listener;
- }
- }
- /**
- * 接收和發送消息的客戶端
- *
- * @author Join
- */
- public class EasyClient extends Thread {
- (還報8W字符冗餘,受不住了,就這麼着吧T^T)...
- }
- public class JsonUtil {
- /**
- * 解析Object成爲json
- *
- * @param obj 對象
- * @return json字符串
- */
- public static String objToJson(Object obj) {
- JSONStringer arrayJson = new JSONStringer(); // Json構造對象
- Class<?> clazz = obj.getClass(); // 獲取對象運行時類
- try {
- 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) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return arrayJson.toString();
- }
- /**
- * 解析json成爲Object
- *
- * @param json json字符串
- * @return 對象
- * @warning 由於是使用newInstance()構建實例,自己寫構造函數時要顯式寫明默認構造函數
- */
- public static Object jsonToObj(String json) {
- Object obj = null;
- try {
- 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) {
- e.printStackTrace();
- }
- return obj;
- }
- /**
- * 給字段設值
- *
- * @param obj 對象
- * @param field 字段
- * @param value 值
- */
- private static void setValue(Object obj, Field field, String value)
- throws IllegalArgumentException, IllegalAccessException {
- ...
- }
- }