打開主模塊的build.gradle配置文件,設(shè)置jniLibs.srcDirs屬性,如下:
android {
//...
sourceSets {
main {
jniLibs.srcDirs "jniLibs"
}
}
}
成功編譯后則可以正常使用LuaScriptCore了。
LuaScriptCore中提供了LuaContext這個(gè)上下文對象類來維護(hù)整個(gè)Lua的環(huán)境,所以使用LuaScriptCore的第一步就是對LuaContext進(jìn)行初始化。如:
LuaContext context = LuaContext.create(this);
初始化完畢后才能進(jìn)行下面的各種操作。
原生層中要操作Lua中的變量或者方法,通常使用到的就是組織Lua腳本來進(jìn)行一些列的Lua操作(LuaScriptCore屏蔽了Lua庫中的C Api,目的是讓代碼更加接近原生,使用起來更加得心應(yīng)手),然后交由Context進(jìn)行腳本的解析。如:
context.evalScript("print('Hello World');");
對于一些耗時(shí)或者Lua無法實(shí)現(xiàn)的功能(如:手機(jī)設(shè)備的拍照),都可以考慮交由原生層來實(shí)現(xiàn),然后提供接口讓Lua進(jìn)行調(diào)用。如下面獲取手機(jī)設(shè)備信息的方法:
在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代碼中調(diào)用方法
local tbl = getDeviceInfo();
有時(shí)候需要通過調(diào)用Lua中的方法來取得返回值(在原生層中只能取得一個(gè)返回值),然后再做后續(xù)的處理,例如:
在Lua代碼中有add方法的定義
function add (a, b)
return a+b;
end
在Java代碼中通過context調(diào)用Lua方法
LuaValue retValue = context.callMethod("add", new LuaValue[]{new LuaValue(100), new LuaValue(924)});
Log.v("luaScriptCore", String.format("%d", retValue.toInteger()));
LuaContext所定義的方法都是全局的,有時(shí)候需要對一系列的方法進(jìn)行一個(gè)包裝,希望這些方法都?xì)w類在某個(gè)模塊下,一來方便根據(jù)模塊來劃分方法的功能,二來可以避免名稱的沖突。因此,可以使用LuaModule來對Lua的功能進(jìn)行擴(kuò)展。需要根據(jù)下面步驟實(shí)現(xiàn):
下面例子定義了一個(gè)日志模塊,如:
在Java代碼中定義LuaModule的子類
/**
* 日志模塊
* Created by vimfung on 16/9/23.
*/
public class LogModule extends LuaModule
{
public static String version()
{
return "1.0.0";
}
public static void writeLog(String message)
{
Log.v("luascriptcore", message);
}
}
注冊模塊
luaContext.registerModule(LogModule.class);
在Lua代碼中調(diào)用
LogModule.writeLog('Hello Lua Module!');
Lua中沒有明確的面向?qū)ο筇匦?,LuaScriptCore提供了一個(gè)面向?qū)ο蟮臄U(kuò)展,Lua可以簡單地封裝類型,并且進(jìn)行類型實(shí)例的使用。首先需要先注冊面向?qū)ο蟮哪K類LuaObjectClass(如果原生層有繼承于LuaObjectClass類的子類需要注冊時(shí),該步驟可省略),如:
luaContext.registerModule(LuaObjectClass.class);
注冊成功后,可以直接在Lua中定義類型,如:
Object.subclass("MyClass");
-- 重寫類型的初始化方法
function MyClass:init ()
print("MyClass instance initialize...");
end
-- 定義類型屬性
MyClass.property = 0;
local instance = MyClass.create();
print (instance.property);
上述代碼的subclass就是子類化對象方法,其接收一個(gè)類型名稱參數(shù),調(diào)用后會(huì)創(chuàng)建一個(gè)對應(yīng)名稱的類型。該類型擁有Object的所有特性。
對于Lua的類定義有如下設(shè)定:
- 所有類型的根類是Object,這個(gè)注冊LuaObjectClass后會(huì)有這個(gè)類的定義.
- 必須使用subclass方法來進(jìn)行子類化,必須傳入一個(gè)有效并且不重復(fù)的類型名稱參數(shù)。
- 必須使用類型的create方法進(jìn)行類對象的實(shí)例化。
- 類型中的方法(即類方法)都以.號(hào)進(jìn)行調(diào)用,類實(shí)例中的方法都以:號(hào)進(jìn)行調(diào)用。類型和實(shí)例的屬性都以.號(hào)進(jìn)行訪問。
- 每個(gè)類中都有一個(gè)叫super的屬性來指代其父類型。
- 需要調(diào)用父類方法時(shí),請使用"類型.super:method"方式進(jìn)行調(diào)用,如:
MyClass.super:test();
。- 當(dāng)類實(shí)例對象初始化時(shí)會(huì)觸發(fā)init方法,銷毀時(shí)會(huì)觸發(fā)destroy方法,可以通過重寫這些方法來進(jìn)行一些額外的工作。
如果需要讓原生類直接映射到Lua中,按照下面步驟實(shí)現(xiàn):
如在Java中有如下類型定義:
public class Person extends LuaObjectClass
{
public String name;
public void speak()
{
Log.v("luascriptcore", String.format("%s speak", name));
}
public void walk()
{
Log.v("luascriptcore", String.format("%s walk", name));
}
public static void printPersonName (Person person)
{
NSLog(@"Person name = %@", person.name);
}
public Person(LuaContext context)
{
super(context);
};
}
然后對該類型進(jìn)行注冊:
_luaContext.registerModule(Person.class);
注冊成功后,在lua中即可使用該類型:
local person = Person.create();
person:setName("vimfung");
person:walk();
person:speak();
Person.printPersonName(person);
更多建議: