android中java与lua的相互调用

Android Studio Lua环境配置
开发环境
1. Android Studio 3.5
2. java sdk: 1.8.0
3.android sdk:28
配置环境
添加lua支持语法支持插件,打开android studio -> File -> Settings

然后重启Android Studio

三方库选择

参考文章:https://gameinstitute.qq.com/community/detail/117865

Luaj 纯Java实现的Lua解析器,无需使用native

首先切换到Project目录,在gradle构建工具中添加依赖Luaj,然后同步
引入第三方库Luaj

  • Java调用Lua函数
  1. 在main目录下新建assets资源目录文件夹,在其下存放lua文件

  2. test.lua

luaV1 = "lua String"

function luaFun1()
    print("Lua 无参无返回值方法");
end

function luaFun2(str)
    return "来自Java的参数:"..str;
end
  1. JavaTest.java
	@Test
    public void test1( ) {
        Globals globals = JsePlatform.standardGlobals();
        //加载Java脚本文件并编译Lua脚本
        globals.loadfile("src/main/assets/test.lua").call();
        //加载Lua常量
        LuaValue luaStr = globals.get(LuaValue.valueOf("luaV1"));
        System.out.println("来自Lua的字符串" + luaStr.toString());
        //加载无参无返回值函数
        LuaValue lua1 = globals.get(LuaValue.valueOf("luaFun1"));
        lua1.call();
        //加载有参有返回值函数
        LuaValue lua2 = globals.get(LuaValue.valueOf("luaFun2"));
        //传入参数
        LuaValue str = lua2.call(LuaValue.valueOf("Java~"));
        System.out.println(str.tostring());
    }
  1. 运行测试方法test1输出
来自Lua的字符串lua String
Lua 无参无返回值方法
来自Java的参数:Java~
  • Lua调用Java
  1. Utils.java
	public void javaFun1(String str){
        System.out.println("Java + " + str);
    }

    public static void javaStaticFun1(String str){
        System.out.println("Static Java +" + str);
    }
  1. test.lua
function luaFun3()
    --创建java对象
    fun1 = luajava.newInstance("com.example.luaandroid.Utils");
    fun1:javaFun1("Lua");
end

function luaFun4()
    --绑定Java类
    fun1 = luajava.bindClass("com.example.luaandroid.Utils");
    fun1:javaStaticFun1("Lua");
end
  1. JavaTest.java
	@Test
    public void test2(){
        Globals globals = JsePlatform.standardGlobals();
        //加载Java脚本文件并编译Lua脚本
        globals.loadfile("src/main/assets/test.lua").call();

        LuaValue lua1 = globals.get(LuaValue.valueOf("luaFun3"));
        lua1.call();
    }
  1. 运行测试方法test2输出:
Java + Lua
Static Java +Lua
  1. Lua与Java运算速度对比
    test.lua
function test()
    a = 0;
    for i = 0, 1000000, 1 do
        a = a + i;
    end
    return "over";
end

JavaTest.java

	@Test
    public void test(){
        long l = System.currentTimeMillis();
        int a = 0;
        for (int i = 0; i < 1000000; i++) {
            a += i;
        }
        System.out.println("Java : "+ (System.currentTimeMillis() - l));
        Globals globals = JsePlatform.standardGlobals();
        //加载Java脚本文件并编译Lua脚本
        globals.loadfile("src/main/assets/test.lua").call();

        LuaValue lua1 = globals.get(LuaValue.valueOf("test"));
        l = System.currentTimeMillis();
        lua1.call().tostring();
        System.out.println("Lua:"+ (System.currentTimeMillis() - l));
    }

输出结果:

Java : 7
Lua:518

在不加Lua脚本加载的时间,多次测试,大概计算速度相差五十倍左右

LuaJava 这个没找到具体的库~~
Android-Lua GitHub地址:https://github.com/liangchenhe55/Android-Lua
  • 引入库:
    implementation group: 'com.blakequ.luajava', name: 'luajava', version: '1.0'
  • 基本使用方法
  1. Java调用Lua函数
    MainActivity.java
//应用启动之后获取LuaState
mLuaState = LuaStateFactory.newLuaState();
mLuaState.openLibs();
//通过上下文返回lua脚本
mLuaState.LdoString(readAssetsTxt(this, "test.lua"));
//加载lua函数
mLuaState.getGlobal("luaFun1");
//传入参数
mLuaState.pushString("lua");
//第一个参数表示传入参数个数,第二个表示返回参数个数
mLuaState.call(1, 1);
//获取返回值
mLuaState.toString(-1);

test.lua

function luaFun1(str)
    return str;
end
  1. Lua中引用Java的方法
    Java的方法需要是继承至JavaFunction()方法的,并重写构造函数和execute()以及register()方法
    • 构造方法用于传入LuaState对象

    • execute()方法是想传入方法

    • register()为想生成的Lua函数取名

      具体实现看后面的实例

  • Android中Lua应用
  1. XMl文件配置
    activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="JavaFun"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.287"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.626" />
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="CallBack"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.823"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.626" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MyJavaFunction.java (注入Lua脚本中的方法一)

public class MyJavaFunction extends JavaFunction {

    public MyJavaFunction(LuaState luaState) {
        super(luaState);
    }
    @Override
    public int execute() {
        // 获取栈中Lua传入的参数,注意第一个参数固定为上下文环境。
        String str = L.toString(2);
        L.pushString("Java的数据 + Lua的Str:"+str);
        return 1; // 返回值的个数
    }

    @Override
    public void register(String name){
        try {
            // 注册为 Lua 全局函数
            super.register("testJava");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

AsyncJavaFunction.java(注入Lua脚本中的Java方法二)

public class AsyncJavaFunction extends JavaFunction {

    // lua 回调函数
    // lua callback function
    private LuaObject callbackFun;

    public AsyncJavaFunction(LuaState L) {
        super(L);
    }

    @Override
    public int execute() {
        // 获取Lua传入的参数,注意第一个参数固定为上下文环境。
        if (L.isFunction(2)) {
            callbackFun = L.getLuaObject(2);
            new MyAsync().execute();
        }
        return 0;
    }

    void register() {
        try {
            // 注册为 Lua 全局函数
            register("http");
        } catch (LuaException e) {
            e.printStackTrace();
        }
    }

    class MyAsync extends AsyncTask<Integer, Integer, Integer> {

        long t;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            t = System.currentTimeMillis();
        }

        @Override
        protected Integer doInBackground(Integer... integers) {
            try {
                // 模拟耗时操作(例如网络请求)
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
            if (callbackFun != null) {
                try {
                    // 2个参数,0 个返回值。
                    callbackFun.call(new Object[]{"OK", System.currentTimeMillis() - t}, 0);
                } catch (LuaException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

test.lua

function luaFun1(str)
    return testJava(str);
end

function luaCallback(tv)
    -- http 函数是由 java `AsyncJavaFunction` 类注入的
    -- http function was injected by java `AsyncJavaFunction`
    http(function(result, time)
        tv:setText(string.format("result: %s\ntime: %dms", result, time));
    end
    )
end

MainActivity.java (主程序文件)

public class MainActivity extends AppCompatActivity {

    private TextView mTextView;
    private LuaState mLuaState;
    private Button mButton;
    private Button mButton2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定控件
        mTextView = findViewById(R.id.textView);
        mButton = findViewById(R.id.button);
        mButton2 = findViewById(R.id.button2);
        //应用启动之后获取LuaState
        mLuaState = LuaStateFactory.newLuaState();
        mLuaState.openLibs();
        //通过上下文返回lua脚本
        mLuaState.LdoString(readAssetsTxt(this, "test.lua"));

        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //利用Java函数生成lua函数,设置函数名为testJava
                new MyJavaFunction(mLuaState).register("testJava");
                //加载lua函数
                mLuaState.getGlobal("luaFun1");
                //传入参数
                mLuaState.pushString("test");
                //第一个参数表示传入参数个数,第二个表示返回参数个数
                mLuaState.call(1, 1);
                mTextView.setText(mLuaState.toString(-1));
            }
        });

        mButton2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mTextView.setText("Loading...");
                new AsyncJavaFunction(mLuaState).register();
                mLuaState.getGlobal("luaCallback");
                mLuaState.pushJavaObject(mTextView);
                mLuaState.call(1, 0);
            }
        });
    }

    public static String readAssetsTxt(Context context, String fileName) {
        try {
            InputStream is = context.getAssets().open(fileName);
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            String text = new String(buffer, "utf-8");
            return text;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "err";
    }

    @Override
    protected void onDestroy() {
        //关闭lua栈
        mLuaState.close();
        super.onDestroy();
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android平台下使用Lua调用Java代码,可以使用LuaJava库来实现。下面是经验总结: 1. 下载LuaJava库和Java的jar包,并将其放置到Android工程的libs目录下。 2. 在Java代码,需要先将Java对象注册到Lua,以便Lua可以调用该对象的方法和属性。可以使用LuaState对象的pushJavaObject()方法将Java对象推入栈,再使用LuaState对象的setGlobal()方法将该对象注册到Lua。例如: ``` LuaState L = LuaStateFactory.newLuaState(); L.openLibs(); JavaObject obj = new JavaObject(); L.pushJavaObject(obj); L.setGlobal("javaObj"); ``` 3. 在Lua脚本,使用require()函数引入LuaJava库,并使用Java对象的方法和属性。例如: ``` require("luajava") javaObj:sayHello("Hello from Lua!") ``` 4. 使用LuaJava调用Java代码时,需要注意Java方法的参数类型和返回值类型。如果参数类型或返回值类型与Lua的类型不匹配,则需要进行类型转换。可以使用LuaJava库的toJavaObject()和toLuaObject()方法进行类型转换。例如: ``` -- 调用Java方法 local str = "Hello from Lua!" local obj = luajava.newInstance("java.lang.String", str) local result = javaObj:callMethod("toUpperCase", obj) -- 转换返回值类型 local strResult = luajava.toJavaObject(result, "java.lang.String") -- 转换Lua类型 local table = {1, 2, 3} local array = luajava.toJavaObject(table, "int[]") ``` 5. 在Android Studio,需要在build.gradle文件添加以下依赖: ``` implementation 'org.keplerproject:luajava:1.2.1' implementation files('libs/javassist.jar') ``` 以上就是使用Lua调用Java代码的经验总结,希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值