
Saya pikir banyak pembaca hub pengembangan android telah mendengar bahwa Java memungkinkan Anda untuk memodifikasi dex dari aplikasi yang sudah diinstal dalam
runtime melalui
ClassLoader . Dengan ini, Anda dapat memuat kode yang dikompilasi dalam runtime dan menggunakannya. Tetapi Google memperlakukan penipuan semacam itu, dengan kata lain, tidak terlalu loyal dan melarang mereka yang tertangkap dalam aplikasi semacam itu.
Namun, ada cara alternatif untuk mengunduh dan menjalankan skrip pada perangkat seluler. Untuk detail di bawah kucing!
Jadi, meskipun kami tidak dapat memperbarui aplikasi dex di runtime, kami dapat menggunakan penerjemah bahasa scripting yang sepenuhnya ditulis dalam Java. Jadi Oracle, dimulai dengan versi 6, termasuk mesin jhascript Badak di JVM. Ini terjadi berkat implementasi spesifikasi JSR-223, yang menyatakan dukungan Java untuk bahasa pemrograman scripting.
Saat ini, ada beberapa mesin built-in untuk bahasa pemrograman populer seperti: Lua (Luaj), Python (Jython), Ruby (Jruby) dan java-script (Rhino, ...). Masing-masing memungkinkan Anda untuk menjalankan skrip dan fungsi akses yang ditulis dalam Java.
Sebagai demonstrasi kemungkinan, saya mengusulkan untuk menerapkan "lingkungan" pembangunan. Saya akan meninggalkan tautan ke sumber di akhir artikel. Agar tidak mengacaukan contoh, saya akan fokus pada Lua, meskipun tidak ada yang menghentikan Anda menghubungkan semua mesin pada saat yang sama dan beralih di antara mereka. Versi JLua saat ini pada saat penulisan tersedia di mvnrepository:
org.luaj: luaj-jse: 3.0.1 .
Setiap lingkungan pengembangan yang menghargai diri sendiri harus memiliki bidang untuk memasukkan skrip, bidang untuk menampilkan hasilnya, dan tombol yang memungkinkan Anda untuk melengkapi gagasan Anda.
UI lingkungan pengembangan yang menghargai diri sendiri:
<?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" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/scriptInput" android:layout_width="0dp" android:layout_height="0dp" android:gravity="top|start" android:hint="@string/write_script" android:inputType="textMultiLine" android:padding="4dp" android:textColor="#000000" app:layout_constraintBottom_toTopOf="@id/scriptOutput" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/scriptOutput" android:layout_width="0dp" android:layout_height="0dp" android:hint="@string/script_output" android:padding="4dp" android:textColor="#000000" app:layout_constraintBottom_toTopOf="@id/executeButton" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/scriptInput" /> <Button android:id="@+id/executeButton" android:layout_width="0dp" android:layout_height="48dp" android:text="@string/run_script" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Untuk mengeksekusi skrip Lua, kita perlu mendapatkan lingkungan global di mana ia akan dieksekusi -
Global . Luaj memungkinkan Anda untuk menyesuaikannya, misalnya, dengan mengatur variabel atau menambahkan binder ke kelas Java. Peluang penting bagi kami di sini adalah mengatur aliran keluaran pesan, karena
java.lang.System.out ,
java.lang.System.err digunakan secara default, yang sangat tidak nyaman ketika Anda perlu menampilkan hasil eksekusi di TextView. Untuk mengubah ini, Anda perlu mendefinisikan kembali nilai-nilai
Globals # STDOUT dan
Globals # STDERR .
Jadi, sekarang kita hanya perlu memuat derit ke lingkungan dan menjalankannya.
Inilah yang terlihat dalam contoh saya:
private fun runLua(script: String) { val charset = StandardCharsets.UTF_8 val globals = JsePlatform.standardGlobals() val outStream = ByteArrayOutputStream() val outPrintStream = PrintStream(outStream, true, charset.name()) globals.STDOUT = outPrintStream globals.STDERR = outPrintStream try { globals.load(script).call() scriptOutput.setTextColor(Color.BLACK) scriptOutput.text = String(outStream.toByteArray(), charset) } catch (e: LuaError) { scriptOutput.setTextColor(Color.RED) scriptOutput.text = e.message } finally { outPrintStream.close() } }
Sekarang mari kita mencoba untuk memperluas set fungsi yang tersedia dengan kemampuan untuk menunjukkan
Toast menggunakan pengikatan kelas Java di atas. Permudah menggunakan
CoerceJavaToLua :
globals.set("bubble", CoerceJavaToLua.coerce(Bubble(this))) ... private class Bubble(private val context: Context) {
Hasil yang saya dapatkan adalah ini:

Jadi, dengan contoh kecil, kami mempertimbangkan kemungkinan menjalankan skrip di dalam aplikasi seluler. Pembaca yang ingin tahu dapat menebak bahwa skrip dapat diunduh dari aset, sumber daya aplikasi, atau dari server. Apa yang bisa bermanfaat, misalnya, dalam game. Untungnya, luaj kompatibel dengan salah satu kerangka kerja game java yang paling populer - Libgdx. Secara umum, ruang lingkup di sini hanya dibatasi oleh imajinasi pengembang.
β
Sumber sampelβ
Luajβ
Jythonβ
Jrubyβ
Badak (
bungkus android )