年初的时候刚把去年末的一个电子书包的项目完结了,这不刚过了几天又收到了boss新的需求:添加一个电子白板,要求老师端绘画的时候,学生端的屏幕也能看到老师端的操做。java
难点:git
1.画板的写法github
2.如何推送数据到学生端,该推送什么格式的数据json
3.学生端收到数据该如何绘制。服务器
思路:app
1.画板的写法ok,网上一大堆socket
2.老师端绘制的时候,绘制的每个操做,又都横纵坐标记录,我只要推送这些记录给学生端,让学生端再根据 坐标绘制tcp
3.依然采起1.0的方案,客户端用socket(tcp)服务器端用(walkman)方式推送数据(已解决)ide
方案:学习
1.画板采用github上星星最多的AndroidDrawingView,前人种树好乘凉,个人建议是最好下载源码本身先看一遍他的思路,固然这里我早就发现这个demo彻底契合个人项目。这个demo居然已经为你扩展了如何实现同屏。请看
DrawingView.java里的这个接口:
[java] view plain copy


- /**
- * 绘制代理,通知状态变动和获取数据
- */
- public interface DrawingStepDelegate {
- /**
- * 当前绘制step建立时回调,一般用于远程同步
- * step处于变化状态
- *
- * @param drawingView 当前view
- * @param step 当前绘制step,任意修改此step可能致使错误
- */
- void onDrawingStepBegin(DrawingView drawingView, DrawingStep step);
-
- /**
- * 当前绘制step变动时回调,每次touch绘制都会执行,text图层修改内容也会执行,此回调执行频繁,一般用于远程同步
- * step处于变化状态
- *
- * @param drawingView 当前view
- * @param step 当前绘制step,任意修改此step可能致使错误
- */
- void onDrawingStepChange(DrawingView drawingView, DrawingStep step);
-
- /**
- * 当前绘制状态已改变,绘制一笔或进行撤销/重作/清空等变动记录数据的操做都会触发此回调
- * step已经完成
- *
- * @param drawingView 当前view
- * @param step 当前绘制step,任意修改此step可能致使错误
- */
- void onDrawingStepEnd(DrawingView drawingView, DrawingStep step);
-
- /**
- * 当前step撤销
- *
- * @param drawingView 当前view
- * @param step 当前绘制step,任意修改此step可能致使错误
- */
- void onDrawingStepCancel(DrawingView drawingView, DrawingStep step);
- }
-
很明显,当我在DrawingView上绘图时会触发这个接口里的四个方法,我想这里就应该是我想要的坐标数据,我只要推送这些数据就好了,那么问题来了,如今我推送只能推送json数据,接收的时候再转成我想要的类,那么DrawingStep如何才能变json呢,点到DrawingStep类里你就回恍然大悟,才会发现此人早就替你想好这一点。原来这个类自己就是个json解析类。他的思路应该是这样的,绘画的时候每一步记录坐标(JSon数据)——解析成DrawingStep——而后drawingView根据DrawingStep绘制,DrawingData存放DrawingStep的集合。既然它是个解析Json的类,那么天然有类转JSon的方法
[java] view plain copy
- /**
- * 复制step
- * @return 复制的step
- */
- public DrawingStep copy() {
- return new Json<>(this.getClass()).modelFromJson(this.toJson());
- }
那么如今就差与服务器约定 命令的请求头,将这坐标数据发送出去
- dv.setDrawingStepDelegate(new DrawingView.DrawingStepDelegate() {
- @Override
- public void onDrawingStepBegin(DrawingView drawingView, DrawingStep step) {
-
- //drawingView.getDrawingData().addDrawingStep(step);
- Logger.i("画板操做onDrawingStepBegin::"+step.toJson().toString());
- SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");
- singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));
-
-
-
- }
-
- @Override
- public void onDrawingStepChange(DrawingView drawingView, DrawingStep step) {
- Logger.i("画板操做onDrawingStepChange::"+step.toJson().toString());
- SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");
- singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));
- }
-
- @Override
- public void onDrawingStepEnd(DrawingView drawingView, DrawingStep step) {
- Logger.i("画板操做onDrawingStepEnd::"+step.toJson().toString());
-
- SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");
- singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));
- }
-
- @Override
- public void onDrawingStepCancel(DrawingView drawingView, DrawingStep step) {
- Logger.i("画板操做onDrawingStepCancel::"+step.toJson().toString());
-
- SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");
-
- singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));
- }
- });
数据发送出去了,学生端该接受数据:那么问题又来了,画板该如何跟据坐标绘制呢,让咱们看drawingView里的方法:
[java] view plain copy
- /**
- * 在当前绘制基础上增长绘制传入的step,若是传入的step与当前未完成的step是同一step(编号相同,远程同步step可能有未完成和已完成两种状态),更新当前step
- *
- * @param step 将要绘制的step
- */
- public void drawNextStep(@NonNull DrawingStep step) {
- step.setRemote(true);
- if (step.getStep() != getCurrentDrawingStep().getStep()) {
- endUnfinishedStep();
- getDrawingData().addDrawingStep(step);
- } else {
- getDrawingData().replaceDrawingStep(step);
- }
-
- if (step.isCanceled()) {
- internalCancelCurrentStep();
- getDrawingData().cancelDrawingStep();
- } else {
- internalUpdateCurrentStep(false);
- }
- }
-
- /**
- * 在当前绘制基础上增长绘制传入的step,此step必须是stepOver状态
- * 在远程同步绘制时,采用低频同步,仅在每一步绘制完成后同步时调用此方法
- * 不可与{@link #drawNextStep(DrawingStep)}同时使用
- *
- * @param step 将要绘制的step
- */
- public void drawNextOverStep(@NonNull DrawingStep step) {
- if (!step.isStepOver()) {
- return;
- }
-
- getDrawingData().addDrawingStep(step);
-
- if (step.isCanceled()) {
- return;
- }
-
- internalUpdateCurrentStep(true);
- }
- 那么接下来就是soeasy了:
[java] view plain copy
- private void initBroadCastReceiver() {
-
- IntentFilter filter = new IntentFilter();
- filter.addAction("SOCKET_MESSAGE");
- if (receiver==null){
- receiver=new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
-
- if (intent.getAction().equals("SOCKET_MESSAGE")) {
-
-
- Bundle data = intent.getBundleExtra("data");
- String msg = data.getString("message", "none");
- Log.i("服务器返回信息::", msg);
-
- try {
- ReceiveOrderBean receiveOrderBean = JSON.parseObject(msg, ReceiveOrderBean.class);
-
- switch (receiveOrderBean.getType()) {
- case "userSendPositionReceive":
- Toast.makeText(TestActivity.this,"获取到坐标数据",Toast.LENGTH_SHORT).show();
- // Logger.i("获取到坐标数据"+receiveOrderBean.getData());
- DrawingStep drawingStep = new Json<>(DrawingStep.class).modelFromJsonString(receiveOrderBean.getData());
-
- Logger.i("获取到坐标数据"+drawingStep.toJson().toString());
-
- dv.drawNextStep(drawingStep);
- dv.drawNextOverStep(drawingStep);
- // dv.getDrawingData().addDrawingStep(drawingStep);
- // dv.refreshWithDrawingData(dv.getDrawingData());
- break;
- }
-
- } catch (com.alibaba.fastjson.JSONException ex) {
- Log.i("命令解析出错", msg + "");
-
- }
-
- }
-
- }
- };
- App.localBroadcastManager.registerReceiver(receiver, filter);
- }
- }
附页:学生端应该是看老师端操做,本身不能操做,因此要设置:
[java] view plain copy
- dv.setDisableTouchDraw(true);//true是设置不能画,false反之
- 问题:已丢包的形式传递一些命令数据好像是能够,好比开关机之类的,但若是要实现相似于直播,屏幕的彻底监控好像有点力不从心,可能与流媒体有关,这也是我须要不断学习的地方。