-
Notifications
You must be signed in to change notification settings - Fork 115
Android集成使用文档
打开项目的Gradle文件,在dependencies
中增加一行compile 'com.github.vimfung.luascriptcore:luascriptcore:2.3.2'
即可正常使用LuaScriptCore。
-
解压压缩包,将目录中的LuaScriptCore.jar文件拷贝到项目的libs目录中,其他的子目录(如:arm64-v8a、armeabi等)拷贝到jniLibs目录中。
-
在Android Studio中选中刚添加的LuaScriptCore.jar,右键弹出菜单选择"Add As Library..."。
-
打开主模块的build.gradle配置文件,设置jniLibs.srcDirs属性,如下:
android { //... sourceSets { main { jniLibs.srcDirs "jniLibs" } } }
-
成功编译后则可以正常使用LuaScriptCore了。
需要jar文件和so文件,可以按照下面步骤进行:
- 打开Android Studio,然后导入Source/Android/目录下的项目。
- 在Terminal中输入:
./gradlew clean build
对项目进行编译 - 编译成功后,打开模块的build/intermediates目录,在/intermediate-jars/release目录找到一个classes.jar和在library_and_local_jars_jni/release目录中找到JNI库文件目录(按照CPU架构划分)。
- 这个jar文件和jni目录中的so库就是LuaScriptCore的库文件。
需要aar文件,可以按照下面步骤进行:
- 打开Android Studio,然后导入Source/Android/目录下的项目。
- 在Terminal中输入:
./gradlew install
对项目进行编译 - 编译成功后,打开模块的build/outputs/arr目录可以找到对应的aar库文件。
LuaScriptCore中提供了LuaContext这个上下文对象类来维护整个Lua的环境,所以使用LuaScriptCore的第一步就是对LuaContext进行初始化。如:
LuaContext context = LuaContext.create(this);
初始化完毕后才能进行下面的各种操作。
原生层中要操作Lua中的变量或者方法,通常使用到的就是组织Lua脚本来进行一些列的Lua操作(LuaScriptCore屏蔽了Lua库中的C Api,目的是让代码更加接近原生,使用起来更加得心应手),然后交由Context进行脚本的解析。如:
context.evalScript("print('Hello World');");
对于一些耗时或者Lua无法实现的功能(如:手机设备的拍照),都可以考虑交由原生层来实现,然后提供接口让Lua进行调用。如下面获取手机设备信息的方法:
在Java代码中定义方法
context.registerMethod("getDeviceInfo", new LuaMethodHandler() {
@Override
public LuaValue onExecute(LuaValue[] arguments) {
HashMap devInfoMap = new HashMap();
devInfoMap.put("deviceName", Build.DISPLAY);
devInfoMap.put("deviceModel", Build.MODEL);
devInfoMap.put("systemName", Build.PRODUCT);
devInfoMap.put("systemVersion", Build.VERSION.RELEASE);
return new LuaValue(devInfoMap);
}
});
在Lua代码中调用方法
local tbl = getDeviceInfo();
有时候需要通过调用Lua中的方法来取得返回值(在原生层中只能取得一个返回值),然后再做后续的处理,例如:
在Lua代码中有add方法的定义
function add (a, b)
return a+b;
end
在Java代码中通过context调用Lua方法
LuaValue retValue = context.callMethod("add", new LuaValue[]{new LuaValue(100), new LuaValue(924)});
Log.v("luaScriptCore", String.format("%d", retValue.toInteger()));
LuaContext所定义的方法都是全局的,有时候需要对一系列的方法进行一个封装,希望这些方法都归类在某个模块下,一来方便根据模块来划分方法的功能,二来可以避免名称的冲突,同时也可以使用面向对象的方式在Lua中进行代码编写。因此,LuaScripCore提供了LuaExportType
来让原生代码中的类型方便快速地导入到Lua中,供Lua进行调用。其实现步骤如下:
- 新声明一个原生类型并实现LuaExportType接口
- 在创建的类型中定义需要导出到Lua的方法和属性,声明方式完全跟Java的方法一样(对于不想导出到Lua的方法可以在定义时使用下划线“_”开头)。
下面例子定义了一个日志模块,如:
/**
* 日志模块
* Created by vimfung on 16/9/23.
*/
public class Log implements LuaExportType
{
public String prefix;
public void writeLog(String message)
{
Log.v("luascriptcore", message);
}
private static Log _instance;
public static Log sharedInstance()
{
if (_instance == null)
{
_instance = new Log();
}
return _instance;
}
}
在Lua中则可进行如下调用:
local log = Log:sharedInstance();
log.prefix = "LuaScriptCore";
log:writeLog('Hello Lua Module!');
导出到Lua的原生类型可以直接通过类型()
方式来构造类型对象。如:
local obj = Object();
如果需要在实例对象构造或者销毁时做一些操作,则可以通过重写类型的init
和destroy
方法来实现。如:
function Object.prototype:init ()
print ("object created!");
end
function Object.prototype:destroy()
print ("object destroy!");
end
Lua中引入了原型prototype
实现,每个导出的原生类型带有此属性。其包含了类型的实例方法和属性定义。如果需要扩展某个类型的实例方法和属性,则可通过修改prototype
来实现。例如为Object
类型增加print
实例方法:
function Object.prototyp:print()
print(self);
end
对于类方法扩展,则可以直接在类型中进行声明,如:
function Object:createObject(name)
local instance = self();
instance.name = name;
return instance;
end
Lua中可以通过subclass
直接子类化原生类型来生成一个新的类型,如:
Object:subclass("MyClass");
-- 重写类型的初始化方法
function MyClass:init ()
print("MyClass instance initialize...");
end
-- 定义类型属性
MyClass.prototype.propertyName = 0;
local instance = MyClass();
print (instance.propertyName);
上述代码的subclass就是子类化对象方法,其接收一个类型名称参数,调用后会创建一个对应名称的类型。该类型拥有Object的所有特性。 当继承类需要覆盖父级类型的某个方法时,只要直接重写一遍父级方法即可,如下代码所示:
-- 创建一个Object的类方法
function Object:classMethodName ()
print ("Object classMethodName call");
end
-- 创建子类
Object:subclass("MyClass");
-- 覆盖父类方法
function MyClass:classMethodName ()
print ("MyClass classMethodName call");
end
如果需要在覆盖方法中调用父级方法,可以使用类型的super
属性,如:
function MyClass:classMethodName ()
MyClass.super.classMethodName(self);
print ("MyClass classMethodName call");
end
实例方法的覆盖方式大致相同,如:
-- 创建一个Object的实例方法
function Object.prototype:instanceMethodName ()
print ("Object instanceMethodName call");
end
-- 创建子类
Object:subclass("MyClass");
-- 覆盖父类方法
function MyClass.prototype:instanceMethodName ()
-- 调用父级方法
MyClass.super.prototype.instanceMethodName(self);
print ("MyClass instanceMethodName call");
end