2012-05-06 16 views
11

Zajmuję się tworzeniem gry na Androida w Javie, która wykorzystuje skrypty Lua. Aby wykonać te skrypty, używam LuaJ z klasą ScriptEngine języka Java. Na przykład ...Jak uruchomić skrypty Lua na Androida w aplikacji Java?

ScriptEngineManager sem = new ScriptEngineManager(); 
scriptEngine = sem.getEngineByExtension(".lua"); 
script = ((Compilable)scriptEngine).compile("some lua here"); 

to jednak najwyraźniej nie są obsługiwane na Android (coś zrobić z androidem nie ma pełnowartościowy JVM, czytałem gdzieś). Czy istnieje sposób, w jaki mogę używać skryptów Lua na Androida? Może istnieje alternatywa LuaJ? Być może istnieje sposób na kompilowanie i wykonywanie skryptów Lua przy użyciu LuaJ bezpośrednio (choć nie widzę jak).

FYI, widzę ten błąd, gdy próbuję uruchomić ten kod na Androida:

05-06 16:12:32.870: E/dalvikvm(17509): Could not find class 'javax.script.ScriptEngineManager', referenced from method unearth.levels.LevelReader.<init> 
05-06 16:12:32.870: W/dalvikvm(17509): VFY: unable to resolve new-instance 787 (Ljavax/script/ScriptEngineManager;) in Lunearth/levels/LevelReader; 
05-06 16:12:32.870: D/dalvikvm(17509): VFY: replacing opcode 0x22 at 0x0018 
05-06 16:12:32.875: E/dalvikvm(17509): Could not find class 'javax.script.Compilable', referenced from method unearth.levels.LevelReader.parseScript 
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to resolve check-cast 782 (Ljavax/script/Compilable;) in Lunearth/levels/LevelReader; 
05-06 16:12:32.875: D/dalvikvm(17509): VFY: replacing opcode 0x1f at 0x0047 
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to resolve exception class 788 (Ljavax/script/ScriptException;) 
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to find exception handler at addr 0x51 
05-06 16:12:32.875: W/dalvikvm(17509): VFY: rejected Lunearth/levels/LevelReader;.parseScript (Lorg/w3c/dom/Element;Lunearth/levels/Level;)V 
05-06 16:12:32.875: W/dalvikvm(17509): VFY: rejecting opcode 0x0d at 0x0051 
05-06 16:12:32.875: W/dalvikvm(17509): VFY: rejected Lunearth/levels/LevelReader;.parseScript (Lorg/w3c/dom/Element;Lunearth/levels/Level;)V 
05-06 16:12:32.875: W/dalvikvm(17509): Verifier rejected class Lunearth/levels/LevelReader; 
05-06 16:12:32.890: W/dalvikvm(17509): threadid=11: thread exiting with uncaught exception (group=0x40c331f8) 
05-06 16:12:32.895: E/AndroidRuntime(17509): FATAL EXCEPTION: GLThread 1062 
05-06 16:12:32.895: E/AndroidRuntime(17509): java.lang.VerifyError: unearth/levels/LevelReader 
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.Game.startGame(Game.java:201) 
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.Game.update(Game.java:713) 
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.screens.LoadScreen.update(LoadScreen.java:56) 
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.UnearthListener.render(UnearthListener.java:71) 
05-06 16:12:32.895: E/AndroidRuntime(17509): at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:423) 
05-06 16:12:32.895: E/AndroidRuntime(17509): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1462) 
05-06 16:12:32.895: E/AndroidRuntime(17509): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216) 
05-06 16:12:58.600: D/dalvikvm(17509): GC_CONCURRENT freed 334K, 3% free 16196K/16647K, paused 2ms+6ms 

Aktualizacja:

Może ten projekt ma kilka przydatnych kodu? http://code.google.com/p/android-scripting/

Odpowiedz

11

Znalazłem sposób wykorzystania LuaJ na Androida! :-)

Kluczem jest użycie interfejsu API LuaJ bezpośrednio w przeciwieństwie do javax.script. Jest to trochę trudne do wymyślenia, ponieważ nie ma tutoriali, więc tutaj jest przed i po tak, aby inni nie musieli przechodzić przez przeglądanie kodu źródłowego LuaJ i JavaDoc. Naprawdę mam nadzieję, że to pomoże komuś, bo doprowadziło mnie do szału!

Uwaga: "secretgame" nie jest rzeczywista nazwa mojej gry ;-)

Po:

package secretgame.scripting; 

import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.ArrayList; 

import org.luaj.vm2.LuaClosure; 
import org.luaj.vm2.LuaTable; 
import org.luaj.vm2.LuaValue; 
import org.luaj.vm2.Prototype; 
import org.luaj.vm2.compiler.LuaC; 
import org.luaj.vm2.lib.jse.CoerceJavaToLua; 
import org.luaj.vm2.lib.jse.JsePlatform; 

import secretgame.SecretGameException; 
import secretgame.events.EventArgs; 
import secretgame.levels.Level; 

public class DirectLuaj implements Lua 
{ 
    private final Level level; 
    private final ScriptTools scriptTools; 
    private final ScriptEvents scriptEvents; 
    private int nextId = 0; 
    private ArrayList<LuaClosure> scripts = new ArrayList<LuaClosure>(); 

    public DirectLuaj(Level level, ScriptTools scriptTools, 
     ScriptEvents scriptEvents) 
    { 
    this.level = level; 
    this.scriptTools = scriptTools; 
    this.scriptEvents = scriptEvents; 
    } 

    @Override 
    public int add(String scriptText) throws SecretGameException 
    { 
    try { 
     InputStream input = new ByteArrayInputStream(scriptText.getBytes()); 
     Prototype p = LuaC.compile(input, "script"); 
     LuaValue g = JsePlatform.standardGlobals(); 
     LuaClosure c = new LuaClosure(p, g); 
     scripts.add(c); 
    } 
    catch (IOException e) { 
     throw new SecretGameException("compile failed", e); 
    } 

    return nextId++; 
    } 

    @Override 
    public void run(int id, EventArgs args) throws SecretGameException 
    { 
    LuaClosure script = scripts.get(id); 

    LuaTable bindings = new LuaTable(); 

    bindings.set("java", toLua(scriptTools)); 
    bindings.set("level", toLua(level)); 
    bindings.set("args", toLua(args)); 
    bindings.set("events", toLua(scriptEvents)); 

    script.setfenv(bindings); 

    script.call(); 
    } 

    private LuaValue toLua(Object javaValue) { 
    return javaValue == null? LuaValue.NIL: 
      javaValue instanceof LuaValue? (LuaValue) javaValue: 
      CoerceJavaToLua.coerce(javaValue); 
    } 
} 

Przed:

package secretgame.scripting; 

import java.util.ArrayList; 

import javax.script.Bindings; 
import javax.script.Compilable; 
import javax.script.CompiledScript; 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import javax.script.ScriptException; 

import secretgame.SecretGameException; 
import secretgame.events.EventArgs; 
import secretgame.levels.Level; 

// sadly this won't work on Android because there's no such thing 
// as javax.script in Dalvik ... dumb Android java :| 
public class JavaxScriptingLua implements Lua 
{ 
    private ScriptEngine scriptEngine; 
    private final Level level; 
    private final ScriptTools scriptTools; 
    private final ScriptEvents scriptEvents; 
    private int nextId = 0; 
    private ArrayList<CompiledScript> scripts = new ArrayList<CompiledScript>(); 

    public JavaxScriptingLua(Level level, ScriptTools scriptTools, ScriptEvents scriptEvents) 
    { 
    this.level = level; 
    this.scriptTools = scriptTools; 
    this.scriptEvents = scriptEvents; 

    ScriptEngineManager sem = new ScriptEngineManager(); 
    scriptEngine = sem.getEngineByExtension(".lua"); 
    } 

    public int add(String scriptText) throws SecretGameException 
    { 
    try { 
     CompiledScript script = ((Compilable)scriptEngine).compile(scriptText); 
     scripts.add(script); 
    } 
    catch (ScriptException e) { 
     throw new SecretGameException("could not compile lua.", e); 
    } 

    return nextId++; 
    } 

    public void run(int id, EventArgs args) throws SecretGameException 
    {  
    Bindings bindings = scriptEngine.createBindings(); 

    bindings.put("java", scriptTools); 
    bindings.put("level", level); 
    bindings.put("args", args); 
    bindings.put("events", scriptEvents); 

    try { 
     scripts.get(id).eval(bindings); 
    } 
    catch (ScriptException e) { 
     throw new SecretGameException("could not run script.", e); 
    } 
    } 
} 
1

Jednak to nie jest widocznie obsługiwane na Androidzie

Prawidłowe.

coś zrobić z androidem nie ma pełnowartościowy JVM, czytałem gdzieś

Prawidłowe. Jeśli spojrzysz na the JavaDocs, zobaczysz, że javax.script nie istnieje w pakiecie SDK systemu Android.

Może dam tego spróbować: https://github.com/damonkohler/sl4a

To jedna opcja. Innym jest osadzenie interpretera Lua w twojej aplikacji przez NDK, tak jak w this sample application.

+0

Dzięki za odpowiedź - ale udało mi się niech LuaJ będzie działał na Androida. Zobacz moją odpowiedź, jeśli jesteś zainteresowany. –

4

Zamiast LuaJ można (także) używać LuaJavy razem z Lua skompilowaną dla systemu Android przy użyciu NDK. Dzięki temu Lua ma pełny dostęp do tego, co jest dostępne z Javy. Spójrz na this example, aby dowiedzieć się, jak zacząć.

Lua 5.1.4 + LuaJava skompilowane są w katalogu libs (pojedynczy plik libluajava.so), jeśli nie chcesz bawić się z NDK, ale i tak jest to względnie łatwe.

+0

Kudos na AndroLua, ale znalazłem sposób na wykorzystanie LuaJ na Androida, więc w ten sposób nie muszę ponownie pisać mojego istniejącego kodu. Zobacz moją odpowiedź na pytanie, jak rozwiązałem problem. –

0

Aby użyj Lua na Androida, możesz użyć JNLua + Lua 5.2 (zaimplementowanej w C). Jedynym Android portu z JSR 223 (javax.script) wsparcie jest tutaj: https://github.com/danke-sra/jnlua-android

Korzystanie z tego portu, możesz robić, co chcesz:

ScriptEngine scriptEngine = new LuaScriptEngineFactory().getEngine(); scriptEngine.eval("lua statements");

Powiązane problemy