Android 模擬一個電子畫板同屏的效果

年初的時候剛把去年末的一個電子書包的項目完結了,這不剛過了幾天又收到了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

 在CODE上查看代碼片派生到個人代碼片

  1. /** 
  2.     * 繪製代理,通知狀態變動和獲取數據 
  3.     */  
  4.    public interface DrawingStepDelegate {  
  5.        /** 
  6.         * 當前繪製step建立時回調,一般用於遠程同步 
  7.         * step處於變化狀態 
  8.         * 
  9.         * @param drawingView 當前view 
  10.         * @param step        當前繪製step,任意修改此step可能致使錯誤 
  11.         */  
  12.        void onDrawingStepBegin(DrawingView drawingView, DrawingStep step);  
  13.   
  14.        /** 
  15.         * 當前繪製step變動時回調,每次touch繪製都會執行,text圖層修改內容也會執行,此回調執行頻繁,一般用於遠程同步 
  16.         * step處於變化狀態 
  17.         * 
  18.         * @param drawingView 當前view 
  19.         * @param step        當前繪製step,任意修改此step可能致使錯誤 
  20.         */  
  21.        void onDrawingStepChange(DrawingView drawingView, DrawingStep step);  
  22.   
  23.        /** 
  24.         * 當前繪製狀態已改變,繪製一筆或進行撤銷/重作/清空等變動記錄數據的操做都會觸發此回調 
  25.         * step已經完成 
  26.         * 
  27.         * @param drawingView 當前view 
  28.         * @param step        當前繪製step,任意修改此step可能致使錯誤 
  29.         */  
  30.        void onDrawingStepEnd(DrawingView drawingView, DrawingStep step);  
  31.   
  32.        /** 
  33.         * 當前step撤銷 
  34.         * 
  35.         * @param drawingView 當前view 
  36.         * @param step        當前繪製step,任意修改此step可能致使錯誤 
  37.         */  
  38.        void onDrawingStepCancel(DrawingView drawingView, DrawingStep step);  
  39.    }  
  40. 很明顯,當我在DrawingView上繪圖時會觸發這個接口裏的四個方法,我想這裏就應該是我想要的座標數據,我只要推送這些數據就好了,那麼問題來了,如今我推送只能推送json數據,接收的時候再轉成我想要的類,那麼DrawingStep如何才能變json呢,點到DrawingStep類裏你就回恍然大悟,纔會發現此人早就替你想好這一點。原來這個類自己就是個json解析類。他的思路應該是這樣的,繪畫的時候每一步記錄座標(JSon數據)——解析成DrawingStep——而後drawingView根據DrawingStep繪製,DrawingData存放DrawingStep的集合。既然它是個解析Json的類,那麼天然有類轉JSon的方法

     

     

    [java] view plain copy

     在CODE上查看代碼片派生到個人代碼片

  41. /** 
  42.  * 複製step 
  43.  * @return 複製的step 
  44.  */  
  45. public DrawingStep copy() {  
  46.     return new Json<>(this.getClass()).modelFromJson(this.toJson());  
  47. }  

那麼如今就差與服務器約定 命令的請求頭,將這座標數據發送出去

  1. dv.setDrawingStepDelegate(new DrawingView.DrawingStepDelegate() {  
  2.            @Override  
  3.            public void onDrawingStepBegin(DrawingView drawingView, DrawingStep step) {  
  4.   
  5.                //drawingView.getDrawingData().addDrawingStep(step);  
  6.                Logger.i("畫板操做onDrawingStepBegin::"+step.toJson().toString());  
  7.                SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");  
  8.                singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));  
  9.   
  10.   
  11.   
  12.            }  
  13.   
  14.            @Override  
  15.            public void onDrawingStepChange(DrawingView drawingView, DrawingStep step) {  
  16.                Logger.i("畫板操做onDrawingStepChange::"+step.toJson().toString());  
  17.                SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");  
  18.                singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));  
  19.            }  
  20.   
  21.            @Override  
  22.            public void onDrawingStepEnd(DrawingView drawingView, DrawingStep step) {  
  23.                Logger.i("畫板操做onDrawingStepEnd::"+step.toJson().toString());  
  24.   
  25.                SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");  
  26.                singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));  
  27.            }  
  28.   
  29.  @Override  
  30.            public void onDrawingStepCancel(DrawingView drawingView, DrawingStep step) {  
  31.                Logger.i("畫板操做onDrawingStepCancel::"+step.toJson().toString());  
  32.   
  33.                SendOrderBean sendOrderBean=new SendOrderBean("userSendPositionRequest",JSON.toJSONString(new UserSendPositionRequest("4450187",step.toJson().toString())),System.currentTimeMillis()+"");  
  34.   
  35.                singleSocket.sendMessage(JSON.toJSONString(sendOrderBean));  
  36.            }  
  37.        });  

  38. 數據發送出去了,學生端該接受數據:那麼問題又來了,畫板該如何跟據座標繪製呢,讓咱們看drawingView裏的方法:

     

     

    [java] view plain copy

     在CODE上查看代碼片派生到個人代碼片

  39. /** 
  40.      * 在當前繪製基礎上增長繪製傳入的step,若是傳入的step與當前未完成的step是同一step(編號相同,遠程同步step可能有未完成和已完成兩種狀態),更新當前step 
  41.      * 
  42.      * @param step 將要繪製的step 
  43.      */  
  44.     public void drawNextStep(@NonNull DrawingStep step) {  
  45.         step.setRemote(true);  
  46.         if (step.getStep() != getCurrentDrawingStep().getStep()) {  
  47.             endUnfinishedStep();  
  48.             getDrawingData().addDrawingStep(step);  
  49.         } else {  
  50.             getDrawingData().replaceDrawingStep(step);  
  51.         }  
  52.   
  53.         if (step.isCanceled()) {  
  54.             internalCancelCurrentStep();  
  55.             getDrawingData().cancelDrawingStep();  
  56.         } else {  
  57.             internalUpdateCurrentStep(false);  
  58.         }  
  59.  }  
  60.   
  61.     /** 
  62.      * 在當前繪製基礎上增長繪製傳入的step,此step必須是stepOver狀態 
  63.      * 在遠程同步繪製時,採用低頻同步,僅在每一步繪製完成後同步時調用此方法 
  64.      * 不可與{@link #drawNextStep(DrawingStep)}同時使用 
  65.      * 
  66.      * @param step 將要繪製的step 
  67.      */  
  68.     public void drawNextOverStep(@NonNull DrawingStep step) {  
  69.         if (!step.isStepOver()) {  
  70.             return;  
  71.         }  
  72.   
  73.         getDrawingData().addDrawingStep(step);  
  74.   
  75.         if (step.isCanceled()) {  
  76.             return;  
  77.         }  
  78.   
  79.         internalUpdateCurrentStep(true);  
  80.     }  
  81. 那麼接下來就是soeasy了:

     

     

    [java] view plain copy

     在CODE上查看代碼片派生到個人代碼片

  82.  private void initBroadCastReceiver() {  
  83.   
  84.         IntentFilter filter = new IntentFilter();  
  85.         filter.addAction("SOCKET_MESSAGE");  
  86.         if (receiver==null){  
  87.             receiver=new BroadcastReceiver() {  
  88.                 @Override  
  89.                 public void onReceive(Context context, Intent intent) {  
  90.   
  91.                     if (intent.getAction().equals("SOCKET_MESSAGE")) {  
  92.   
  93.   
  94.                         Bundle data = intent.getBundleExtra("data");  
  95.                         String msg = data.getString("message", "none");  
  96.                         Log.i("服務器返回信息::", msg);  
  97.   
  98.                         try {  
  99.                             ReceiveOrderBean receiveOrderBean = JSON.parseObject(msg, ReceiveOrderBean.class);  
  100.   
  101.                             switch (receiveOrderBean.getType()) {  
  102.   case "userSendPositionReceive":  
  103.                                     Toast.makeText(TestActivity.this,"獲取到座標數據",Toast.LENGTH_SHORT).show();  
  104.                                    // Logger.i("獲取到座標數據"+receiveOrderBean.getData());  
  105.                                     DrawingStep drawingStep = new Json<>(DrawingStep.class).modelFromJsonString(receiveOrderBean.getData());  
  106.   
  107.                                     Logger.i("獲取到座標數據"+drawingStep.toJson().toString());  
  108.   
  109.                                     dv.drawNextStep(drawingStep);  
  110.                                     dv.drawNextOverStep(drawingStep);  
  111. //                                    dv.getDrawingData().addDrawingStep(drawingStep);  
  112. //                                    dv.refreshWithDrawingData(dv.getDrawingData());  
  113.                                     break;  
  114.                             }  
  115.   
  116.                         } catch (com.alibaba.fastjson.JSONException ex) {  
  117.                             Log.i("命令解析出錯", msg + "");  
  118.   
  119.                         }  
  120.   
  121.                     }  
  122.   
  123.                 }  
  124.             };  
  125.             App.localBroadcastManager.registerReceiver(receiver, filter);  
  126.         }  
  127.     }  

  128. 附頁:學生端應該是看老師端操做,本身不能操做,因此要設置:

     

     

    [java] view plain copy

     在CODE上查看代碼片派生到個人代碼片

  129. dv.setDisableTouchDraw(true);//true是設置不能畫,false反之  
  130. 問題:已丟包的形式傳遞一些命令數據好像是能夠,好比開關機之類的,但若是要實現相似於直播,屏幕的徹底監控好像有點力不從心,可能與流媒體有關,這也是我須要不斷學習的地方。
相關文章
相關標籤/搜索