Android blockly 输出code执行代码解决过程

最近接手到需要写一个安卓blockly的项目,要求20天左右输出一个集成blockly的项目,一脸懵逼,啥是blockly?

查阅相关资料,值得推荐资料:

https://www.bilibili.com/video/BV1ME411L7Xh?p=2  一个B站的教程,把安卓集成的过程都详细了说明,

https://github.com/MDKusester/study_blocklyAndroid     视屏配套的 demo

https://github.com/google/blockly-android   官方blockly  demo  安卓版本2018年  已经停止维护

https://www.jianshu.com/p/a5d608538ef1   另一篇关于blockly的文章

全部找了一圈,关于安卓集成blockly的文章貌似是这几篇,其他的可能都已经是web方式集成了

本文集成的方式按照B站教程走,但是B站教程因为在js执行命令上 遇到if(函数)类型的复杂语句无法解析执行的问题,采用了xml方式去执行,然鹅在demo里面却没有开源xml'解析,时间紧迫任务重,只能逼着我重新用起我vue 里学的js功力去考虑解决。

//安卓java的代码 不懂的先看B站视频
@NonNull
protected CodeGenerationRequest.CodeGeneratorCallback mCodeGeneratorCallback = new CodeGenerationRequest.CodeGeneratorCallback() {
    @Override
    public void onFinishCodeGeneration(String generatedCode) {//得到的blockly运行后的代码
        Log.d(TAG, "得到的代码:\n" + generatedCode);
        final String code = generatedCode;
        mWebview.post(new Runnable() {
            @Override
            public void run() {
                String encoded = "Move.execute("
                        + JavascriptUtil.makeJsString(code) + ")";
                mWebview.loadUrl("javascript:" + encoded);
                Log.d(TAG, "执行的代码:\n" + encoded);
            }
        });
    }
};

js 的代码

/**
 * Execute the user's code.  Heaven help us...
 */
Move.execute = function(code) {
  console.log(`js里面执行的代码开始------------------`);
  console.log(code);

  inputCode = code
  try {
    eval(code);
  } catch (e) {
    // Null is thrown for infinite loop.
    // Otherwise, abnormal termination is a user error.
    if (e !== Infinity) {
      alert(e);
    }
  }

  // Turtle.log now contains a transcript of all the user's actions.
  // Reset the graphic and animate the transcript.
};

获得blockly的代码是

if (move.getCDS(1,500)) {
      move.setLED(1,1);
    } else {
      move.setDcMotor(1,0,0);
    }

 js 里面执行的 eval(code);的时候,日志显示,执行了getCDS 还有执行了setDcMotor的两个方法。。。这个搞得我就有点懵逼了,为啥一下执行了两个方法,我就设法在js里面做阻断,如果有if和get类型的方法调用的时候,set类型的方法不执行,然后把单个指令和指令集发给java处理,再用处理完的结果去替换单个命令字符串,最后再把命令集再给eval再处理,如此循环,就能处理完所有blockly的模块

js方法
在eval之前把要执行的code赋值给inputCode
move.getCDS= function(INport, midnum) {
  console.log(`js执行方法-------move.getCDS`);
  if (!move.isIncludeIf(inputCode)) { //判断code里面是否含有if语句
    Move.getCDS(`getCDS(${INport},${midnum})\r\n`, "");//调用java的方法,第一个参数单个命令字符串,第二参数,整个输入命令
  } else {
     Move.getCDS(`getCDS(${INport},${midnum})\r\n`, inputCode);//调用java的方法,第一个参数单个命令字符串,第二参数,整个输入命令
  }
};

安卓java

@JavascriptInterface
public synchronized void getCDS(final String command, final String procedureCode) {
    Log.d(TAG, "getCDSjava需要执行的命令~~~~: " + command);

    if (procedureCode.length() > 0) {
        Log.d(TAG, "getCDS还有要继续处理的代码段: " + procedureCode);
    }
}

TODO 安卓去拿getCDS的结果返回后解析判断,如果是true|false,用这个去替代procedureCode中的command字符串,得到新的字符串再放到js eval(procedureCode)里处理,
这样可以处理单个if的情况,但是如果有多if情况就会有问题,处理起来比较繁琐。

继续观察数据,查资料 发现 执行了getCDS 还有执行了setDcMotor 是不是因为getCDS执行的时候没有返回值直接按照false处理。如果在blockly模块的if语句不放模块

if (false) {
      move.setLED(1,1);
    }
      move.getCDS(1,1);
   

由此可以推出是否因为getCDS没有返回值,所以直接eval()认为是false所以执行了下面的getCDS,尝试在getCDS给上true的返回值,就可以正常控制if了,这个是一大进步嗄

因为是蓝牙调用getCDS,是否可以在这儿做阻断,等蓝牙处理好后再给出true或false给if里面呢,尝试给java里面一个阻断3s后再返回给js,如下代码

 js代码 
move.getCDS = function(status, threshold) {
  console.log(`js执行方法-------getCDS status=${status} threshold=${threshold}`);
  return  Move.getCDS(`getCDS(${status},${threshold})\r\n`, "");
};

安卓java代码

@JavascriptInterface
public synchronized boolean getCDS(final int INport, final int midnum) {
   
    String  command="getCDS("+INport+","+midnum+")";
try{
    Thread.sleep(300);
}catch (InterruptedException e){
    e.printStackTrace();
}
    return false;
}

程序等待了3秒后再执行setLED方法,因为js是单线程的,再调用java到时候,java用的是js的线程,java去调用蓝牙的时候,就形成了阻塞,所以拆除掉js的控制,最终的代码

'use strict';

/**
 * Execute the user's code.  Heaven help us...
 */
move.execute = function(code) {
  console.log(`js里面执行的代码开始------------------`);
  console.log(code);

  inputCode = code
  try {
    eval(code);
  } catch (e) {
    // Null is thrown for infinite loop.
    // Otherwise, abnormal termination is a user error.
    if (e !== Infinity) {
      alert(e);
    }
  }

};
public class MoveInterface {
    private Activity activity;
    private String TAG = "FriendsInterface";

    public FriendsInterface(Activity activity) {
        this.activity = activity;
    }

    // 定义JS需要调用的方法
    // 被JS调用的方法必须加入@JavascriptInterface注解
    @JavascriptInterface
    public void hello(String msg) {
        Log.d(TAG, "JS调用了Android的hello方法");
    }

    
    @JavascriptInterface
    public synchronized boolean getCDS(final int INport, final int midnum) {
        String  command="getCDS("+INport+","+midnum+")";
        //去拿结果,给出判断

        return true|false;
    }
 public synchronized int getCDS(final int INport, final int midnum) {
        String  command="getCDS("+INport+","+midnum+")";
        //去拿结果,给出判断
        int aaa=getCDSInt();
        return aaa;
    }
}

至此blockly的集成调用完成,目前测试所有blockly的语句都可以正常运行,B站的博主还没有联系,记录一下这个折腾摸索几天的过程

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值