You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android应用中运行KotlinScriptEngine并解决权限报错

解决方案:Android上运行Kotlin脚本引擎规避Non-SDK接口限制

核心问题分析

你遇到的错误源于Android 12(API 31)及以上版本对Non-SDK接口的严格限制,Kotlin官方的JSR223脚本引擎依赖sun.misc.Unsafe的getAndAddInt等隐藏方法,这些方法在targetSdk 34下被完全禁止调用,导致编译器初始化失败。以下是几种可行的解决方案:


方案1:临时降级targetSdk版本(快速验证)

如果允许暂时降低targetSdk,可以将build.gradle中的targetSdk改为32:

android {
    defaultConfig {
        targetSdk = 32
    }
}

此方案能直接绕过Android 12+的Non-SDK限制,和Code Assist的运行环境一致,但无法适配Android 13/14的新特性。


方案2:使用适配Android的Kotlin脚本引擎依赖

替换官方的kotlin-compiler-embeddable为第三方适配过的版本,这些版本通常移除了对sun.misc.Unsafe的依赖:

// 移除原有的runtimeOnly("org.jetbrains.kotlin:kotlin-compiler-embeddable")
implementation("com.github.prof18:kotlin-scripting-android:1.0.0")
implementation(kotlin("scripting-jsr223"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

然后修改脚本执行代码,适配Android类加载器:

import javax.script.ScriptEngineManager

val engineManager = ScriptEngineManager()
val engine = engineManager.getEngineByExtension("kts")
// 绑定当前应用的类加载器
engine.context.classLoader = this.classLoader
engine.eval(kotlinCode)

方案3:自定义Kotlin脚本执行逻辑(无JSR223依赖)

如果需要更灵活的控制,可以直接使用Kotlin Scripting核心API,避免JSR223封装带来的隐藏依赖:

  1. 添加Gradle依赖:
implementation("org.jetbrains.kotlin:kotlin-scripting-common")
implementation("org.jetbrains.kotlin:kotlin-scripting-jvm")
implementation("org.jetbrains.kotlin:kotlin-scripting-compiler-impl")
  1. 自定义脚本执行代码:
import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvm.*

// 配置脚本编译环境
val scriptCompilationConfig = ScriptCompilationConfiguration {
    defaultImports(listOf("kotlin.*"))
    jvm {
        dependenciesFromCurrentContext(wholeClasspath = true)
    }
}

// 执行表达式脚本
suspend fun runExpression(expression: String, a: Int, b: Int): ResultValue {
    val scriptCode = """
        fun compute(a: Int, b: Int) = $expression
        compute($a, $b)
    """.trimIndent()
    
    return runScripting {
        scriptCode.toScriptSource().evaluate(
            compilationConfiguration = scriptCompilationConfig,
            environment = ScriptEvaluationConfiguration {
                jvm {
                    classLoader = this@YourActivity.classLoader
                }
            }
        )
    }
}

此方案完全脱离JSR223,减少了对隐藏API的依赖,更适配Android环境。


方案4:添加Hidden API豁免(不推荐生产环境)

如果必须使用官方引擎且保持targetSdk34,可以通过Android的Hidden API豁免清单解除对特定方法的限制:

  1. 在src/main/res/xml/下创建hiddenapi-package-whitelist.xml:
<?xml version="1.0" encoding="utf-8"?>
<hidden-api-whitelist>
    <method signature="Lsun/misc/Unsafe;->getAndAddInt(Ljava/lang/Object;JI)I" />
    <field signature="Lsun/security/util/SecurityConstants;->GET_CLASSLOADER_PERMISSION:Ljava/lang/RuntimePermission;" />
</hidden-api-whitelist>
  1. 在AndroidManifest.xml中引用该清单:
<application>
    <meta-data
        android:name="android.app.hiddenapi.whitelist.xml"
        android:resource="@xml/hiddenapi_package_whitelist" />
</application>

注意:此方法依赖Android私有API豁免机制,可能在未来版本被废弃,且无法通过Google Play审核。


额外注意事项

  • 脚本编译属于耗时操作,必须放到后台线程(如使用Coroutine),避免主线程ANR
  • 对用户输入的表达式做语法限制,仅允许算术运算、基本Kotlin语法,防止恶意代码执行

内容的提问来源于stack exchange,提问作者Lavish Swarnkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 23:54:53