android下调用lua脚本方法
在android里使用lua的文章网上已经有很多,这里就不具体说了。但网上大多数的例子只是简单的在java里调用了LdoString,很少有提到如何加载lua脚本文件。所以,这里主要说一下如何直接调用lua脚本文件的方法。我在网上查找到的方法以及自己研究后的结果整理如下:
lua脚本是文本文件,为了不让android将其编译成二进制的形式,一般将其放到res/raw下面或者assets下面。但在android里所有这些资源都是在apk包里的(本人经验不是很多,这是我目前所以理解的),所以不能够直接通过文件路径的方法访问,于是luajava的LdoFile也无法正常加载lua文件。那么只好通过变通的方式执行lua脚本了。
假设我们的lua文件为/res/raw/hello.lua(放在assets下也是同样的道理)
一、利用流读取lua脚本的内容并将其赋值给String变量,通过LdoString执行。
网上有类似的方法,整理如下:
L.LdoString(readStream(getResources().openRawResource(R.raw.hello)));
其中getResources().openRawResource(R.raw.hello))返回的是hello.lua的文件流。
readStream是读取全部文件内容,并以String的类型返回,代码如下
private String readStream(InputStream is) { try { ByteArrayOutputStream bo = new ByteArrayOutputStream(); int i = is.read(); while (i != -1) { bo.write(i); i = is.read(); } return bo.toString(); } catch (IOException e) { Log.e("ReadStream", "读取文件流失败"); return ""; } }这样就可以通过LdoString的方式执行lua脚本了。
二、将lua脚本复制到files文件夹下,再执行LdoFile
该方法主要是将apk中的lua文件复制出来,以便让程序能够通过文件路径的方式访问到脚本,进而可以执行LdoFile方法。
private void copyResourcesToLocal() { String name, sFileName; InputStream content; R.raw a = new R.raw(); java.lang.reflect.Field[] t = R.raw.class.getFields(); Resources resources = getResources(); for (int i = 0; i < t.length; i++) { FileOutputStream fs = null; try { name = resources.getText(t[i].getInt(a)).toString(); sFileName = name.substring(name.lastIndexOf('/') + 1, name .length()); content = getResources().openRawResource(t[i].getInt(a)); // Copies script to internal memory only if changes were made sFileName = getApplicationContext().getFilesDir() + "/" + sFileName; Log.d("Copy Raw File", "Copying from stream " + sFileName); content.reset(); int bytesum = 0; int byteread = 0; fs = new FileOutputStream(sFileName); byte[] buffer = new byte[1024]; while ((byteread = content.read(buffer)) != -1) { bytesum += byteread; // 字节数 文件大小 System.out.println(bytesum); fs.write(buffer, 0, byteread); } fs.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
copyResourcesToLocal的作用是复制lua文件。这是我在ScriptForAndroidTemplate工程看到的,它的方法就是将脚本文件直接复制到脚本解释器的目录下。
当然,这里我没有判断lua文件是否已经存在以及文件是否有变化,真正的程序里最好加上判断,当真的需要复制文件时再进行复制。
copyResourcesToLocal方法需要放在执行luajava的方法的前面,可以是onCreate开始的位置。之后就可以调用luajava的LdoFile方法了
L.LdoFile(getApplicationContext().getFilesDir() + "/" + "hello.lua");
下面贴一个本身测试用的完整的Activity
package helloandroid.test; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.res.Resources; import android.os.Bundle; import android.widget.TextView; import android.util.Log; import org.keplerproject.luajava.*; public class Helloandroid extends Activity { @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); copyResourcesToLocal(); } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { LuaState L = LuaStateFactory.newLuaState(); System.out.println("Lua:newLuaState"); L.openLibs(); System.out.println("Lua:openLibs"); try { L.pushObjectValue(Log.class); L.setGlobal("Log"); } catch (LuaException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // String lua = this.getClass().getResource("").getPath(); System.out.println("Lua script: " + getResources().getString(R.raw.hello)); System.out.println("path: " + getApplicationContext().getPackageCodePath() + "/" + getResources().getText(R.raw.hello).toString()); int luaerr = L.LdoFile(getApplicationContext().getFilesDir() + "/" + "hello.lua"); // System.out.println("Lua:LdoString"); // getResources().getResourceName(R.raw.hello); // int luaerr = // L.LdoString(readStream(getResources().openRawResource(R.raw.hello))); System.out.println("Lua:LdoFile error " + luaerr); L.getGlobal("text"); System.out.println("Lua:getGlobal"); String text = "default content"; text = L.toString(-1); L.getGlobal("chinese"); text += L.toString(-1); // L.pop(2); super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText(text); L.getGlobal("setcontent"); try { L.pushObjectValue(tv); } catch (LuaException e) { // TODO Auto-generated catch block e.printStackTrace(); } L.pcall(1, 0, 0); setContentView(tv); } /** * 读取输入流的全部字节,并以String形式返回 * * @param is * @return */ private String readStream(InputStream is) { try { ByteArrayOutputStream bo = new ByteArrayOutputStream(); int i = is.read(); while (i != -1) { bo.write(i); i = is.read(); } return bo.toString(); } catch (IOException e) { Log.e("ReadStream", "读取文件流失败"); return ""; } } /** * 将/res/raw下面的资源复制到 /data/data/applicaton.package.name/files */ private void copyResourcesToLocal() { String name, sFileName; InputStream content; R.raw a = new R.raw(); java.lang.reflect.Field[] t = R.raw.class.getFields(); Resources resources = getResources(); for (int i = 0; i < t.length; i++) { FileOutputStream fs = null; try { name = resources.getText(t[i].getInt(a)).toString(); sFileName = name.substring(name.lastIndexOf('/') + 1, name .length()); content = getResources().openRawResource(t[i].getInt(a)); // Copies script to internal memory only if changes were made sFileName = getApplicationContext().getFilesDir() + "/" + sFileName; Log.d("Copy Raw File", "Copying from stream " + sFileName); content.reset(); int bytesum = 0; int byteread = 0; fs = new FileOutputStream(sFileName); byte[] buffer = new byte[1024]; while ((byteread = content.read(buffer)) != -1) { bytesum += byteread; // 字节数 文件大小 System.out.println(bytesum); fs.write(buffer, 0, byteread); } fs.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
hello.lua脚本的内容为:
text="I am in lua Script\n" chinese="我是中文,娃哈哈 " function setcontent(view) view:setText(text..chinese.."\nthis is setcontent") Log:i("LuaLog", "over setcontent") end print "end of lua script"
以上就是本人总结的方法,恳请各位拍砖