2)绘制部分
修改的ApiDemos的FingerPaint例子。有ClientView和ServerView,而父类BaseView放置共用的东西,也保证绘制效果一致。
2.1)BaseView.java
- public class BaseView extends View {
- protected OnExitedListener listener;
- public interface OnExitedListener {
- void onExited(View v);
- }
- protected Paint mPaint;
- protected Bitmap mBitmap;
- protected Canvas mCanvas;
- protected Path mPath;
- protected Paint mBitmapPaint;
- protected static final String KEY_INFO = "info";
- protected final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- String info = msg.getData().getString(KEY_INFO);
- Toast.makeText(getContext(), info, Toast.LENGTH_SHORT).show();
- }
- };
- public BaseView(Context context, int width, int height) {
- super(context);
- mPaint = new Paint(); // 创建线条画笔
- mPaint.setAntiAlias(true); // 设置抗锯齿
- mPaint.setDither(true); // 设置递色
- mPaint.setColor(0xFFFF0000); // 设置画笔颜色
- mPaint.setStyle(Paint.Style.STROKE); // 设置画笔类型
- mPaint.setStrokeJoin(Paint.Join.ROUND); // 默认MITER
- mPaint.setStrokeCap(Paint.Cap.ROUND); // 默认BUTT
- mPaint.setStrokeWidth(12); // 设置描边宽度
- mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); // 创建bitmap对象
- mCanvas = new Canvas(mBitmap); // 嵌入Canvas
- mPath = new Path(); // 创建画笔路径
- mBitmapPaint = new Paint(Paint.DITHER_FLAG); // 创建图像画笔
- /* 设置获得焦点,以触发onKeyDown */
- requestFocus();
- setFocusableInTouchMode(true);
- }
- protected void toastMessage(String info) {
- Message msg = mHandler.obtainMessage();
- Bundle data = new Bundle();
- data.putString(KEY_INFO, info);
- msg.setData(data);
- mHandler.sendMessage(msg);
- }
- public void onBackPressed() {
- }
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
- onBackPressed();
- }
- return super.onKeyDown(keyCode, event);
- }
- public void setOnExitedListener(OnExitedListener listener) {
- this.listener = listener;
- }
- }
2.2)ClientView.java
- public class ClientView extends BaseView implements OnClientListener {
- private EasyClient mEasyClient;
- private boolean hasStart = false;
- private Display mDisplay;
- private float wRatio = 1f, hRatio = 1f; // 屏幕缩放比
- private Runnable mRunnable = new Runnable() {
- @Override
- public void run() {
- Toast.makeText(getContext(), "已过5秒,网络不通畅?", Toast.LENGTH_LONG)
- .show();
- }
- };
- public ClientView(Context context, String host, int port, Display display) {
- super(context, display.getWidth(), display.getHeight());
- mDisplay = display;
- mEasyClient = new EasyClient(host, port, 10000);
- mEasyClient.setOnClientListener(this);
- mEasyClient.start();
- mHandler.postDelayed(mRunnable, 5000);
- }
- @Override
- public void onBackPressed() {
- mEasyClient.sendMessage(EasyServer.EXIT_COMMAND);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.drawColor(0xFFAAAAAA);
- canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
- canvas.drawPath(mPath, mPaint);
- }
- private float mX, mY;
- private void touch_start(float x, float y) {
- hasStart = true;
- mPath.reset();
- mPath.moveTo(x, y);
- mX = x;
- mY = y;
- }
- private void touch_move(float x, float y) {
- if (hasStart) {
- mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
- mX = x;
- mY = y;
- } else {
- touch_start(x, y);
- }
- }
- private void touch_up(float x, float y) {
- hasStart = false;
- // mPath.lineTo(mX, mY);
- mPath.lineTo(x, y);
- // commit the path to our offscreen
- mCanvas.drawPath(mPath, mPaint);
- // kill this so we don't double draw
- mPath.reset();
- }
- @Override
- public void onConnectException() {
- mHandler.removeCallbacks(mRunnable);
- toastMessage("连接不到服务器!");
- if (null != listener) {
- listener.onExited(this);
- }
- }
- @Override
- public void onTimeoutException() {
- mHandler.removeCallbacks(mRunnable);
- toastMessage("连接服务器超时!");
- if (null != listener) {
- listener.onExited(this);
- }
- }
- @Override
- public void onSocketException() {
- mHandler.removeCallbacks(mRunnable);
- toastMessage("通信异常!");
- if (null != listener) {
- listener.onExited(this);
- }
- }
- @Override
- public void onConnected() {
- mHandler.removeCallbacks(mRunnable);
- toastMessage("连接上了服务器!");
- }
- @Override
- public void onReceive(String msg) {
- Object obj = JsonUtil.jsonToObj(msg);
- if (obj instanceof ScreenInfo) {
- ScreenInfo info = (ScreenInfo) obj;
- wRatio = ((float) mDisplay.getWidth()) / info.getWidth();
- hRatio = ((float) mDisplay.getHeight()) / info.getHeight();
- } else if (obj instanceof PonitInfo) {
- PonitInfo info = (PonitInfo) obj;
- float x = wRatio * info.getX();
- float y = hRatio * info.getY();
- switch (info.getState()) {
- case 0:
- touch_start(x, y);
- postInvalidate();
- break;
- case 1:
- touch_move(x, y);
- postInvalidate();
- break;
- case 2:
- touch_up(x, y);
- postInvalidate();
- break;
- }
- }
- }
- @Override
- public void onExited() {
- toastMessage("客户端退出了!");
- if (null != listener) {
- listener.onExited(this);
- }
- }
- }
2.3)ServerView.java
- public class ServerView extends BaseView implements OnServerListener {
- private EasyServer mEasyServer;
- private Display mDisplay;
- public ServerView(Context context, int port, Display display) {
- super(context, display.getWidth(), display.getHeight());
- mDisplay = display;
- /* 开启服务 */
- mEasyServer = new EasyServer(port);
- mEasyServer.setOnServerListener(this);
- mEasyServer.start();
- }
- @Override
- public void onBackPressed() {
- mEasyServer.sendMessage(EasyServer.EXIT_COMMAND);
- /* 返回至前页面时,端口仍被占用。可以在这里杀死相关进程,以避免端口占用。 */
- if (null != listener) {
- listener.onExited(this);
- }
- }
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.drawColor(0xFFAAAAAA);
- canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
- canvas.drawPath(mPath, mPaint);
- }
- private float mX, mY;
- private static final float TOUCH_TOLERANCE = 4;
- private void touch_start(float x, float y) {
- mEasyServer.sendMessage(JsonUtil.objToJson(new PonitInfo(x, y, 0)));
- mPath.reset();
- mPath.moveTo(x, y);
- mX = x;
- mY = y;
- }
- private void touch_move(float x, float y) {
- float dx = Math.abs(x - mX);
- float dy = Math.abs(y - mY);
- if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
- mEasyServer.sendMessage(JsonUtil.objToJson(new PonitInfo(x, y, 1)));
- mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
- mX = x;
- mY = y;
- }
- }
- private void touch_up() {
- mEasyServer.sendMessage(JsonUtil.objToJson(new PonitInfo(mX, mY, 2)));
- mPath.lineTo(mX, mY);
- // commit the path to our offscreen
- mCanvas.drawPath(mPath, mPaint);
- // kill this so we don't double draw
- mPath.reset();
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- float x = event.getX();
- float y = event.getY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- touch_start(x, y);
- invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- touch_move(x, y);
- invalidate();
- break;
- case MotionEvent.ACTION_UP:
- touch_up();
- invalidate();
- break;
- }
- return true;
- }
- @Override
- public void onBindException() {
- toastMessage("端口占用了,请关闭应用后重开!");
- }
- @Override
- public void onSocketException(InetAddress ip) {
- toastMessage(ip + "异常退出!");
- }
- @Override
- public void onClientConnected(InetAddress ip) {
- toastMessage(ip + "建立了连接!");
- /* 发送ScreenInfo信息 */
- mEasyServer.sendMessage(JsonUtil.objToJson(new ScreenInfo(mDisplay
- .getWidth(), mDisplay.getHeight())));
- }
- @Override
- public void onReceive(InetAddress ip, String msg) {
- /* 接收客户端消息 */
- }
- @Override
- public void onExited(InetAddress ip) {
- toastMessage(ip + "正常退出!");
- }
- }
四、后记
1、NIO Socket通信还不是很熟悉,所以还是Socket了。至于多线程和NIO效率在各情况下孰优孰劣不清楚。而长连接是为了实时。
2、客户端连接以Socket集合来记录,在n多时会有什么什么。算了,现Demo不面临这种风险~
3、现在的通信消息太复杂了,没必要这样的。
可以多拿几个设备测试玩玩^^
附件:http://down.51cto.com/data/2360760
本文转自winorlose2000 51CTO博客,原文链接:http://blog.51cto.com/vaero/893887,如需转载请自行联系原作者