2014年9月1日 星期一

android下调用lua脚本方法

http://fredguo.iteye.com/blog/1434471

在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执行。
网上有类似的方法,整理如下:
Java代码  收藏代码
  1. L.LdoString(readStream(getResources().openRawResource(R.raw.hello)));  
 其中getResources().openRawResource(R.raw.hello))返回的是hello.lua的文件流。
readStream是读取全部文件内容,并以String的类型返回,代码如下
Java代码  收藏代码
  1. private String readStream(InputStream is) {  
  2.   
  3.         try {  
  4.   
  5.             ByteArrayOutputStream bo = new ByteArrayOutputStream();  
  6.   
  7.             int i = is.read();  
  8.             while (i != -1) {  
  9.                 bo.write(i);  
  10.                 i = is.read();  
  11.   
  12.             }  
  13.             return bo.toString();  
  14.         } catch (IOException e) {  
  15.             Log.e("ReadStream""读取文件流失败");  
  16.             return "";  
  17.         }  
  18.   
  19.     }  
 这样就可以通过LdoString的方式执行lua脚本了。  

二、将lua脚本复制到files文件夹下,再执行LdoFile
该方法主要是将apk中的lua文件复制出来,以便让程序能够通过文件路径的方式访问到脚本,进而可以执行LdoFile方法。
Java代码  收藏代码
  1. private void copyResourcesToLocal() {  
  2.         String name, sFileName;  
  3.         InputStream content;  
  4.         R.raw a = new R.raw();  
  5.         java.lang.reflect.Field[] t = R.raw.class.getFields();  
  6.         Resources resources = getResources();  
  7.         for (int i = 0; i < t.length; i++) {  
  8.             FileOutputStream fs = null;  
  9.             try {  
  10.                 name = resources.getText(t[i].getInt(a)).toString();  
  11.                 sFileName = name.substring(name.lastIndexOf('/') + 1, name  
  12.                         .length());  
  13.                 content = getResources().openRawResource(t[i].getInt(a));  
  14.   
  15.                 // Copies script to internal memory only if changes were made  
  16.                 sFileName = getApplicationContext().getFilesDir() + "/"  
  17.                         + sFileName;  
  18.   
  19.                 Log.d("Copy Raw File""Copying from stream " + sFileName);  
  20.                 content.reset();  
  21.                 int bytesum = 0;  
  22.                 int byteread = 0;  
  23.                 fs = new FileOutputStream(sFileName);  
  24.                 byte[] buffer = new byte[1024];  
  25.                 while ((byteread = content.read(buffer)) != -1) {  
  26.                     bytesum += byteread; // 字节数 文件大小  
  27.                     System.out.println(bytesum);  
  28.                     fs.write(buffer, 0, byteread);  
  29.                 }  
  30.                 fs.close();  
  31.             } catch (Exception e) {  
  32.                 // TODO Auto-generated catch block  
  33.                 e.printStackTrace();  
  34.             }  
  35.         }  
  36.     }  

copyResourcesToLocal的作用是复制lua文件。这是我在ScriptForAndroidTemplate工程看到的,它的方法就是将脚本文件直接复制到脚本解释器的目录下。
当然,这里我没有判断lua文件是否已经存在以及文件是否有变化,真正的程序里最好加上判断,当真的需要复制文件时再进行复制。
copyResourcesToLocal方法需要放在执行luajava的方法的前面,可以是onCreate开始的位置。之后就可以调用luajava的LdoFile方法了
Java代码  收藏代码
  1. L.LdoFile(getApplicationContext().getFilesDir() + "/" + "hello.lua");  

下面贴一个本身测试用的完整的Activity
Java代码  收藏代码
  1. package helloandroid.test;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7.   
  8. import android.app.Activity;  
  9. import android.content.res.Resources;  
  10. import android.os.Bundle;  
  11. import android.widget.TextView;  
  12. import android.util.Log;  
  13.   
  14. import org.keplerproject.luajava.*;  
  15.   
  16. public class Helloandroid extends Activity {  
  17.   
  18.     @Override  
  19.     protected void onStart() {  
  20.         // TODO Auto-generated method stub  
  21.         super.onStart();  
  22.         copyResourcesToLocal();  
  23.     }  
  24.   
  25.     /** Called when the activity is first created. */  
  26.     @Override  
  27.     public void onCreate(Bundle savedInstanceState) {  
  28.         LuaState L = LuaStateFactory.newLuaState();  
  29.         System.out.println("Lua:newLuaState");  
  30.   
  31.         L.openLibs();  
  32.         System.out.println("Lua:openLibs");  
  33.   
  34.         try {  
  35.             L.pushObjectValue(Log.class);  
  36.             L.setGlobal("Log");  
  37.         } catch (LuaException e1) {  
  38.             // TODO Auto-generated catch block  
  39.             e1.printStackTrace();  
  40.         }  
  41.         // String lua = this.getClass().getResource("").getPath();  
  42.         System.out.println("Lua script: "  
  43.                 + getResources().getString(R.raw.hello));  
  44.         System.out.println("path: "  
  45.                 + getApplicationContext().getPackageCodePath() + "/"  
  46.                 + getResources().getText(R.raw.hello).toString());  
  47.         int luaerr = L.LdoFile(getApplicationContext().getFilesDir() + "/"  
  48.                 + "hello.lua");  
  49.         // System.out.println("Lua:LdoString");  
  50.         // getResources().getResourceName(R.raw.hello);  
  51.         // int luaerr =  
  52.         // L.LdoString(readStream(getResources().openRawResource(R.raw.hello)));  
  53.         System.out.println("Lua:LdoFile error " + luaerr);  
  54.         L.getGlobal("text");  
  55.         System.out.println("Lua:getGlobal");  
  56.         String text = "default content";  
  57.         text = L.toString(-1);  
  58.         L.getGlobal("chinese");  
  59.         text += L.toString(-1);  
  60.         // L.pop(2);  
  61.         super.onCreate(savedInstanceState);  
  62.         TextView tv = new TextView(this);  
  63.         tv.setText(text);  
  64.         L.getGlobal("setcontent");  
  65.         try {  
  66.             L.pushObjectValue(tv);  
  67.         } catch (LuaException e) {  
  68.             // TODO Auto-generated catch block  
  69.             e.printStackTrace();  
  70.         }  
  71.   
  72.         L.pcall(100);  
  73.         setContentView(tv);  
  74.     }  
  75.   
  76.     /** 
  77.      * 读取输入流的全部字节,并以String形式返回 
  78.      *  
  79.      * @param is 
  80.      * @return 
  81.      */  
  82.     private String readStream(InputStream is) {  
  83.   
  84.         try {  
  85.   
  86.             ByteArrayOutputStream bo = new ByteArrayOutputStream();  
  87.   
  88.             int i = is.read();  
  89.             while (i != -1) {  
  90.                 bo.write(i);  
  91.                 i = is.read();  
  92.   
  93.             }  
  94.             return bo.toString();  
  95.         } catch (IOException e) {  
  96.             Log.e("ReadStream""读取文件流失败");  
  97.             return "";  
  98.         }  
  99.   
  100.     }  
  101.   
  102.     /** 
  103.      * 将/res/raw下面的资源复制到 /data/data/applicaton.package.name/files 
  104.      */  
  105.     private void copyResourcesToLocal() {  
  106.         String name, sFileName;  
  107.         InputStream content;  
  108.         R.raw a = new R.raw();  
  109.         java.lang.reflect.Field[] t = R.raw.class.getFields();  
  110.         Resources resources = getResources();  
  111.         for (int i = 0; i < t.length; i++) {  
  112.             FileOutputStream fs = null;  
  113.             try {  
  114.                 name = resources.getText(t[i].getInt(a)).toString();  
  115.                 sFileName = name.substring(name.lastIndexOf('/') + 1, name  
  116.                         .length());  
  117.                 content = getResources().openRawResource(t[i].getInt(a));  
  118.   
  119.                 // Copies script to internal memory only if changes were made  
  120.                 sFileName = getApplicationContext().getFilesDir() + "/"  
  121.                         + sFileName;  
  122.   
  123.                 Log.d("Copy Raw File""Copying from stream " + sFileName);  
  124.                 content.reset();  
  125.                 int bytesum = 0;  
  126.                 int byteread = 0;  
  127.                 fs = new FileOutputStream(sFileName);  
  128.                 byte[] buffer = new byte[1024];  
  129.                 while ((byteread = content.read(buffer)) != -1) {  
  130.                     bytesum += byteread; // 字节数 文件大小  
  131.                     System.out.println(bytesum);  
  132.                     fs.write(buffer, 0, byteread);  
  133.                 }  
  134.                 fs.close();  
  135.             } catch (Exception e) {  
  136.                 // TODO Auto-generated catch block  
  137.                 e.printStackTrace();  
  138.             }  
  139.         }  
  140.     }  
  141. }  

 hello.lua脚本的内容为:
Lua代码  收藏代码
  1. text="I am in lua Script\n"  
  2. chinese="我是中文,娃哈哈 "  
  3.   
  4. function setcontent(view)  
  5.     view:setText(text..chinese.."\nthis is setcontent")  
  6.     Log:i("LuaLog""over setcontent")  
  7. end  
  8.   
  9. print "end of lua script"  

以上就是本人总结的方法,恳请各位拍砖