年初的時候剛把去年末的一個電子書包的項目完結了,這不剛過了幾天又收到了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反之
- 問題:已丟包的形式傳遞一些命令數據好像是能夠,好比開關機之類的,但若是要實現相似於直播,屏幕的徹底監控好像有點力不從心,可能與流媒體有關,這也是我須要不斷學習的地方。