语言环境
Cocos2dx 3.6
lua 5.1
java 1.8.0_144
本节问题:
lua 通过 luaj与java交互,在java中,如何回调lua?若要处理的事件代码必须在多线程中执行,又该如何保证数据的连贯统一?
本节发送的问题以及解决思路为本人实测,真实有效。
由lua 调用java 实现‘复制粘贴’说起:
复制不多说,网上成功的例子一大把,说说粘贴,
先上一段 lua 中调用java函数的代码
--调用java 取剪贴板数据
--回调函数
function AndroidFunc:getClipboard(callback)
--*注意:此为java回调luaj用例*
--*/回调函数作为参数以int【I】型传参
local resTab = {-1,'权限不足'}
--resTab =
local function clipboardCallbackFromJava(params)
-- print("ClipboardCallbackFromJava datas->"..params)
-- dump(params)
params = tostring(params)
if params == '@-1#' then --权限不足
resTab = {-1,'权限不足'}
elseif params == '@0#' then --内容为空
resTab = {0,''}
else
resTab = {0,params}
end
if type(callback) == 'function' then
callback(resTab)
end
end
local className = "org/cocos2dx/lua/AppActivity"
local funcName = "getPasteToClipboard"
local args = {clipboardCallbackFromJava}
local sigs = "(I)V"
local ok, ret = luaj.callStaticMethod(className, funcName , args ,sigs)
--多线程先执行
if not ok then
print("取剪贴板数据调用失败 失败代码:", ret)
resTab = {-1,'权限不足'}
if type(callback) == 'function' then
callback(resTab)
end
else
resTab = {}
print("取剪贴板数据调用成功 返回结果:", ret)
end
end
这是我改完后的版本,要注意的点:
1.如何将一个函数以参数的形式传进java,这一点在 luaj 中有介绍,我不多说,这里提供下地址,自己去看,
JIN中java类型的定义:https://www.cnblogs.com/tianshuai11/archive/2012/03/26/2477175.html
luaj的概念用法:https://blog.csdn.net/MartinLutherSu/article/details/50470259?locationNum=1&fps=1
2.接下来是java层面
从以上代码能看出我的功能函数写在了‘org.cocos2dx.lua.AppActivity’这个类中,写的比较杂,直接写在AppActivity这种用法不推荐,我是懒得改了,java粘贴功能的实现请参照:
cocos-lua实现复制粘贴 https://www.cnblogs.com/U-tansuo/p/clip.html
// 粘贴(取剪贴板数据)
public static void getPasteToClipboard(int callbackFuncID) {
final Context context = instance; // 参数要加final关键字,否则内部类不能访问
clipboardCallbackFunc = callbackFuncID //回调主线程的关键
if (clipboardCallbackFunc != -1){
try {
Runnable runnable = new Runnable() {
public void run() {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = clipboard.getPrimaryClip();
String resText = "@-1#"; //使用特殊字符串标识
if (clip != null){ //权限不足,获取失败
android.content.ClipData.Item textItem = clip.getItemAt(0);
if (textItem != null){ //权限不足,获取失败
if (textItem.getText() != null){ //判断文本内容
resText = textItem.getText().toString();
}else{
resText = "@0#";
};
};
};
final String aa = resText;
instance.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxLuaJavaBridge.callLuaFunctionWithString(clipboardCallbackFunc, aa);
}
});
//PasteToClipboard = textItem.getText().toString();
}
};
// getSystemService运行所在线程必须执行过Looper.prepare()
// 否则会出现Can't create handler inside thread that has not called
// Looper.prepare()
instance.runOnUiThread(runnable);
} catch (Exception e) {
Log.d("cocos2dx", "getPasteToClipboard error");
e.printStackTrace();
}
}
}
看过我上面的代码就应该明白,在执行 'getSystemService'时不能在主线程 即 handler 中运行,否则会出错,代码不要照搬啊,android.content.ClipboardManager 是我已经引入的包,若没有引入,可以通过上下文对象来获取,看到这个函数的参数 就知道 luaj 中的 callJavaStaticMethod 若传递的参数是函数 则以‘ int’来标识函数地址,这里我是这么理解的 ,lua向java 传递了一个函数,java实际拿到的是其钩子,‘clipboardCallbackFunc’这个变量是我在函数外部定义的,具体定义为:
public static int clipboardCallbackFunc = -1; //获取剪贴板粘贴的lua回调函数
回调的关键:
Cocos2dxLuaJavaBridge.callLuaFunctionWithString(clipboardCallbackFunc, resText);
完成以上步骤,就已经完成了一大半了,接下来就是实测,我这边测是没问题的
总结:
lua在调用java代码时尽量不要在主线程中进行操作,否则一旦阻塞进程就很严重了