Scriptable Apk -

Google Play Store Policy 4.5 (Dangerous Products):

Apps that download executable code (e.g., scripts, dex files, native libraries) from a source other than Google Play are prohibited unless the code is part of the app’s core functionality and is signed with the same certificate.

Safe practices for scriptable APKs:

Case example: Tasker allows JavaScript but restricts network and file write permissions unless user approves each.


1. Add dependency in build.gradle:

implementation 'org.luaj:luaj-jse:3.0.1'

2. Place script main.lua in src/main/assets/

3. Load and execute in MainActivity:

class MainActivity : AppCompatActivity() 
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    val luaState = LuaState.Factory.newLuaState()
    luaState.openLibs()
// Register Android context
    val globals = luaState.getGlobals()
    globals.set("androidContext", this)
// Load script from assets
    val script = assets.open("main.lua").bufferedReader().use  it.readText() 
    luaState.load(script, "main")
    luaState.call()

4. Example main.lua:

function showToast(msg)
  local context = androidContext
  local toast = context:getSystemService("toast")
  toast:makeText(context, msg, 0):show()
end

showToast("Hello from Lua inside APK")


A scriptable APK typically consists of four core components: scriptable apk

| Component | Description | |-----------|-------------| | Host App | Native Android (Java/Kotlin/C++) shell containing UI, permissions, and system integration. | | Script Interpreter | Embedded runtime (LuaJIT, QuickJS, PyTorch Mobile, or custom VM). | | Script Repository | Local (/assets/) or remote (HTTPS, CDN) storage for scripts. | | Bridge Interface | JNI/FFI bindings exposing Android APIs (sensors, files, intents) to the scripting environment. |

Example data flow:

For years, Android applications (APKs) have followed a rigid model: a developer writes Java or Kotlin code, compiles resources, signs the package, and distributes it. The end user installs the app and interacts with it exactly as the developer intended—no modifications, no runtime logic changes, and certainly no scripting.

But a new paradigm has been quietly gaining traction: the scriptable APK. Google Play Store Policy 4

A scriptable APK is an Android application package that embeds a scripting engine (such as Lua, Python, JavaScript, or even BASIC) and allows users—or the app itself—to modify, extend, or automate the app’s behavior without recompiling the entire APK. This concept merges the portability of native Android apps with the flexibility of scripts.

In this long article, we’ll explore what makes an APK scriptable, why you might want one, how to build it, and real-world examples that are changing mobile automation.


Google Play Store Policy 4.5 (Dangerous Products):

Apps that download executable code (e.g., scripts, dex files, native libraries) from a source other than Google Play are prohibited unless the code is part of the app’s core functionality and is signed with the same certificate.

Safe practices for scriptable APKs:

Case example: Tasker allows JavaScript but restricts network and file write permissions unless user approves each.


1. Add dependency in build.gradle:

implementation 'org.luaj:luaj-jse:3.0.1'

2. Place script main.lua in src/main/assets/

3. Load and execute in MainActivity:

class MainActivity : AppCompatActivity() 
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    val luaState = LuaState.Factory.newLuaState()
    luaState.openLibs()
// Register Android context
    val globals = luaState.getGlobals()
    globals.set("androidContext", this)
// Load script from assets
    val script = assets.open("main.lua").bufferedReader().use  it.readText() 
    luaState.load(script, "main")
    luaState.call()

4. Example main.lua:

function showToast(msg)
  local context = androidContext
  local toast = context:getSystemService("toast")
  toast:makeText(context, msg, 0):show()
end

showToast("Hello from Lua inside APK")


A scriptable APK typically consists of four core components:

| Component | Description | |-----------|-------------| | Host App | Native Android (Java/Kotlin/C++) shell containing UI, permissions, and system integration. | | Script Interpreter | Embedded runtime (LuaJIT, QuickJS, PyTorch Mobile, or custom VM). | | Script Repository | Local (/assets/) or remote (HTTPS, CDN) storage for scripts. | | Bridge Interface | JNI/FFI bindings exposing Android APIs (sensors, files, intents) to the scripting environment. |

Example data flow:

For years, Android applications (APKs) have followed a rigid model: a developer writes Java or Kotlin code, compiles resources, signs the package, and distributes it. The end user installs the app and interacts with it exactly as the developer intended—no modifications, no runtime logic changes, and certainly no scripting.

But a new paradigm has been quietly gaining traction: the scriptable APK.

A scriptable APK is an Android application package that embeds a scripting engine (such as Lua, Python, JavaScript, or even BASIC) and allows users—or the app itself—to modify, extend, or automate the app’s behavior without recompiling the entire APK. This concept merges the portability of native Android apps with the flexibility of scripts.

In this long article, we’ll explore what makes an APK scriptable, why you might want one, how to build it, and real-world examples that are changing mobile automation.