合并打包功能代码
autoJS打包目前只能兼容V1版本的签名,而由于谷歌的限制,如果targetSdk为30或以上的话,打包的应用就无法安装,所以打包(构建时选择inrt分支)时需要将TARGET_SDK_VERSION设置为29或以下。
This commit is contained in:
@@ -20,6 +20,7 @@ import org.autojs.autojs.engine.RootAutomatorEngine
|
||||
import org.autojs.autojs.engine.ScriptEngineManager
|
||||
import org.autojs.autojs.engine.ScriptEngineService
|
||||
import org.autojs.autojs.engine.ScriptEngineServiceBuilder
|
||||
import org.autojs.autojs.inrt.autojs.XJavaScriptEngine
|
||||
import org.autojs.autojs.pref.Pref.registerOnSharedPreferenceChangeListener
|
||||
import org.autojs.autojs.rhino.InterruptibleAndroidContextFactory
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
@@ -58,9 +59,17 @@ abstract class AbstractAutoJs protected constructor(protected val application: A
|
||||
val infoProvider = ActivityInfoProvider(context)
|
||||
val scriptEngineManager = ScriptEngineManager(context)
|
||||
val scriptEngineService: ScriptEngineService = run {
|
||||
scriptEngineManager.registerEngine(JavaScriptSource.ENGINE) {
|
||||
LoopBasedJavaScriptEngine(context).also { engine ->
|
||||
engine.runtime = createRuntime().also { runtime = it }
|
||||
if (org.autojs.autojs6.BuildConfig.isInrt) {
|
||||
scriptEngineManager.registerEngine(JavaScriptSource.ENGINE) {
|
||||
XJavaScriptEngine(context).also { engine ->
|
||||
engine.runtime = createRuntime().also { runtime = it }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scriptEngineManager.registerEngine(JavaScriptSource.ENGINE) {
|
||||
LoopBasedJavaScriptEngine(context).also { engine ->
|
||||
engine.runtime = createRuntime().also { runtime = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
initContextFactory()
|
||||
@@ -84,7 +93,14 @@ abstract class AbstractAutoJs protected constructor(protected val application: A
|
||||
}
|
||||
|
||||
private fun initContextFactory() {
|
||||
ContextFactory.initGlobal(InterruptibleAndroidContextFactory(File(context.cacheDir, "classes")))
|
||||
ContextFactory.initGlobal(
|
||||
InterruptibleAndroidContextFactory(
|
||||
File(
|
||||
context.cacheDir,
|
||||
"classes"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
protected open fun createRuntime(): ScriptRuntime = ScriptRuntime.Builder()
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.util.concurrent.Executors
|
||||
* Modified by SuperMonster003 as of Dec 1, 2021.
|
||||
* Transformed by SuperMonster003 on Oct 10, 2022.
|
||||
*/
|
||||
class AutoJs private constructor(private val appContext: Application) : AbstractAutoJs(appContext) {
|
||||
open class AutoJs(private val appContext: Application) : AbstractAutoJs(appContext) {
|
||||
|
||||
// @Thank to Zen2H
|
||||
private val printExecutor = Executors.newSingleThreadExecutor()
|
||||
|
||||
86
app/src/main/java/org/autojs/autojs/inrt/App.kt
Normal file
86
app/src/main/java/org/autojs/autojs/inrt/App.kt
Normal file
@@ -0,0 +1,86 @@
|
||||
package org.autojs.autojs.inrt
|
||||
|
||||
import android.app.Application
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.SimpleTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import org.autojs.autojs.inrt.App
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.inrt.autojs.GlobalKeyObserver
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.core.ui.inflater.ImageLoader
|
||||
import org.autojs.autojs.core.ui.inflater.util.Drawables
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/7/1.
|
||||
*/
|
||||
class App : Application() {
|
||||
companion object {
|
||||
|
||||
private const val BUGLY_APP_ID = "19b3607b53"
|
||||
|
||||
private lateinit var instance: WeakReference<App>
|
||||
|
||||
val app: App
|
||||
get() = instance.get()!!
|
||||
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
GlobalAppContext.set(this)
|
||||
instance = WeakReference(this)
|
||||
AutoJs.initInstance(this)
|
||||
GlobalKeyObserver.init()
|
||||
Drawables.defaultImageLoader=object : ImageLoader {
|
||||
override fun loadInto(imageView: ImageView, uri: Uri) {
|
||||
Glide.with(this@App)
|
||||
.load(uri)
|
||||
.into(imageView)
|
||||
}
|
||||
|
||||
override fun loadIntoBackground(view: View, uri: Uri) {
|
||||
Glide.with(this@App)
|
||||
.load(uri)
|
||||
.into(object : SimpleTarget<Drawable>() {
|
||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||
view.background = resource
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun load(view: View, uri: Uri): Drawable {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun load(view: View, uri: Uri, drawableCallback: ImageLoader.DrawableCallback) {
|
||||
Glide.with(this@App)
|
||||
.load(uri)
|
||||
.into(object : SimpleTarget<Drawable>() {
|
||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||
drawableCallback.onLoaded(resource)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun load(view: View, uri: Uri, bitmapCallback: ImageLoader.BitmapCallback) {
|
||||
Glide.with(this@App)
|
||||
.asBitmap()
|
||||
.load(uri)
|
||||
.into(object : SimpleTarget<Bitmap>() {
|
||||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||
bitmapCallback.onLoaded(resource)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
51
app/src/main/java/org/autojs/autojs/inrt/LogActivity.kt
Normal file
51
app/src/main/java/org/autojs/autojs/inrt/LogActivity.kt
Normal file
@@ -0,0 +1,51 @@
|
||||
package org.autojs.autojs.inrt
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.inrt.launch.GlobalProjectLauncher
|
||||
import org.autojs.autojs.core.console.ConsoleImpl
|
||||
import org.autojs.autojs.core.console.ConsoleView
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
class LogActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setupView()
|
||||
if (intent.getBooleanExtra(EXTRA_LAUNCH_SCRIPT, false)) {
|
||||
GlobalProjectLauncher.launch(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupView() {
|
||||
setContentView(R.layout.activity_main_inrt)
|
||||
val toolbar = findViewById<Toolbar>(R.id.toolbar)
|
||||
setSupportActionBar(toolbar)
|
||||
val consoleView = findViewById<ConsoleView>(R.id.console)
|
||||
consoleView.setConsole(AutoJs.instance.globalConsole as ConsoleImpl)
|
||||
consoleView.findViewById<View>(R.id.input_container).visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
startActivity(Intent(this, SettingsActivity::class.java))
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_main_inrt, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
|
||||
const val EXTRA_LAUNCH_SCRIPT = "launch_script"
|
||||
}
|
||||
}
|
||||
50
app/src/main/java/org/autojs/autojs/inrt/Pref.kt
Normal file
50
app/src/main/java/org/autojs/autojs/inrt/Pref.kt
Normal file
@@ -0,0 +1,50 @@
|
||||
package org.autojs.autojs.inrt
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceManager
|
||||
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/12/8.
|
||||
*/
|
||||
object Pref {
|
||||
|
||||
private const val KEY_FIRST_USING = "key_first_using"
|
||||
private var sPreferences: SharedPreferences? = null
|
||||
|
||||
private val preferences: SharedPreferences
|
||||
get() {
|
||||
return sPreferences ?: run {
|
||||
val pref = PreferenceManager.getDefaultSharedPreferences(GlobalAppContext.get())
|
||||
sPreferences = pref
|
||||
pref
|
||||
}
|
||||
}
|
||||
|
||||
val isFirstUsing: Boolean
|
||||
get() {
|
||||
val firstUsing = preferences.getBoolean(KEY_FIRST_USING, true)
|
||||
if (firstUsing) {
|
||||
preferences.edit().putBoolean(KEY_FIRST_USING, false).apply()
|
||||
}
|
||||
return firstUsing
|
||||
}
|
||||
|
||||
private fun getString(res: Int): String {
|
||||
return GlobalAppContext.get().getString(res)
|
||||
}
|
||||
|
||||
fun shouldEnableAccessibilityServiceByRoot(): Boolean {
|
||||
return preferences.getBoolean(getString(R.string.key_enable_a11y_service_with_root_access), true)
|
||||
}
|
||||
|
||||
fun shouldHideLogs(): Boolean {
|
||||
return preferences.getBoolean(getString(R.string.key_not_showing_main_activity), false)
|
||||
}
|
||||
|
||||
fun shouldStopAllScriptsWhenVolumeUp(): Boolean {
|
||||
return preferences.getBoolean(getString(R.string.key_use_volume_control_running), true)
|
||||
}
|
||||
}
|
||||
38
app/src/main/java/org/autojs/autojs/inrt/SettingsActivity.kt
Normal file
38
app/src/main/java/org/autojs/autojs/inrt/SettingsActivity.kt
Normal file
@@ -0,0 +1,38 @@
|
||||
package org.autojs.autojs.inrt
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.Nullable
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/12/8.
|
||||
*/
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setupViews()
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
setContentView(R.layout.activity_settings_inrt)
|
||||
fragmentManager.beginTransaction().replace(R.id.fragment_setting, PreferenceFragment()).commit()
|
||||
val toolbar = findViewById<Toolbar>(R.id.toolbar)
|
||||
toolbar.setTitle(R.string.text_settings)
|
||||
setSupportActionBar(toolbar)
|
||||
toolbar.setNavigationOnClickListener { finish() }
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
class PreferenceFragment : androidx.preference.PreferenceFragment() {
|
||||
|
||||
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.preference_inrt)
|
||||
}
|
||||
}
|
||||
}
|
||||
89
app/src/main/java/org/autojs/autojs/inrt/SplashActivity.kt
Normal file
89
app/src/main/java/org/autojs/autojs/inrt/SplashActivity.kt
Normal file
@@ -0,0 +1,89 @@
|
||||
package org.autojs.autojs.inrt
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager.PERMISSION_DENIED
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.NonNull
|
||||
import androidx.annotation.Nullable
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.inrt.launch.GlobalProjectLauncher
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2018/2/2.
|
||||
*/
|
||||
class SplashActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(@Nullable savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_splash_inrt)
|
||||
val slug = findViewById<TextView>(R.id.slug)
|
||||
slug.typeface = Typeface.createFromAsset(assets, "roboto_medium.ttf")
|
||||
if (!Pref.isFirstUsing) {
|
||||
main()
|
||||
} else {
|
||||
Handler(Looper.myLooper()!!).postDelayed({ this@SplashActivity.main() }, INIT_TIMEOUT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun main() {
|
||||
checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.READ_PHONE_STATE)
|
||||
}
|
||||
|
||||
|
||||
private fun runScript() {
|
||||
Thread {
|
||||
try {
|
||||
GlobalProjectLauncher.launch(this)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
runOnUiThread {
|
||||
Toast.makeText(this@SplashActivity, e.message, Toast.LENGTH_LONG).show()
|
||||
startActivity(Intent(this@SplashActivity, LogActivity::class.java))
|
||||
AutoJs.instance.globalConsole.printAllStackTrace(e)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, @NonNull permissions: Array<String>, @NonNull grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
runScript()
|
||||
}
|
||||
|
||||
private fun checkPermission(vararg permissions: String) {
|
||||
val requestPermissions = getRequestPermissions(permissions)
|
||||
if (requestPermissions.isNotEmpty()) {
|
||||
requestPermissions(requestPermissions, PERMISSION_REQUEST_CODE)
|
||||
} else {
|
||||
runScript()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getRequestPermissions(permissions: Array<out String>): Array<String> {
|
||||
val list = ArrayList<String>()
|
||||
for (permission in permissions) {
|
||||
if (checkSelfPermission(permission) == PERMISSION_DENIED) {
|
||||
list.add(permission)
|
||||
}
|
||||
}
|
||||
return list.toTypedArray()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val PERMISSION_REQUEST_CODE = 11186
|
||||
private const val INIT_TIMEOUT: Long = 1000
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
98
app/src/main/java/org/autojs/autojs/inrt/autojs/AutoJs.kt
Normal file
98
app/src/main/java/org/autojs/autojs/inrt/autojs/AutoJs.kt
Normal file
@@ -0,0 +1,98 @@
|
||||
package org.autojs.autojs.inrt.autojs
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.inrt.LogActivity
|
||||
import org.autojs.autojs.inrt.SettingsActivity
|
||||
import org.autojs.autojs.core.accessibility.AccessibilityTool
|
||||
import org.autojs.autojs.core.accessibility.AccessibilityService
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
import org.autojs.autojs.runtime.api.AppUtils
|
||||
import org.autojs.autojs.runtime.exception.ScriptException
|
||||
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
|
||||
import org.autojs.autojs.script.JavaScriptSource
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
class AutoJs private constructor(application: Application) : org.autojs.autojs.AutoJs(application) {
|
||||
|
||||
init {
|
||||
scriptEngineService.registerGlobalScriptExecutionListener(ScriptExecutionGlobalListener())
|
||||
scriptEngineManager.registerEngine(JavaScriptSource.ENGINE) {
|
||||
val engine = XJavaScriptEngine(application)
|
||||
engine.runtime = createRuntime()
|
||||
engine
|
||||
}
|
||||
}
|
||||
|
||||
override fun createAppUtils(context: Context): AppUtils {
|
||||
return AppUtils(context, context.packageName + ".fileprovider")
|
||||
}
|
||||
|
||||
override fun ensureAccessibilityServiceEnabled() {
|
||||
if (AccessibilityService.instance != null) {
|
||||
return
|
||||
}
|
||||
var errorMessage: String? = null
|
||||
if (isAccessibilityServiceEnabled()) {
|
||||
errorMessage = GlobalAppContext.get().getString(R.string.text_a11y_service_enabled_but_not_running)
|
||||
} else if (!getAccessibilityServiceTool().service.enableIfNeededAndWaitFor(2000)) {
|
||||
errorMessage = GlobalAppContext.get().getString(R.string.error_no_accessibility_permission)
|
||||
}
|
||||
if (errorMessage != null) {
|
||||
getAccessibilityServiceTool().launchSettings()
|
||||
throw ScriptException(errorMessage)
|
||||
}
|
||||
}
|
||||
|
||||
override fun waitForAccessibilityServiceEnabled(timeout: Long) {
|
||||
if (AccessibilityService.instance != null) {
|
||||
return
|
||||
}
|
||||
var errorMessage: String? = null
|
||||
if (isAccessibilityServiceEnabled()) {
|
||||
errorMessage = GlobalAppContext.get().getString(R.string.text_a11y_service_enabled_but_not_running)
|
||||
} else if (!getAccessibilityServiceTool().service.enableIfNeededAndWaitFor(2000)) {
|
||||
errorMessage = GlobalAppContext.get().getString(R.string.error_no_accessibility_permission)
|
||||
}
|
||||
if (errorMessage != null) {
|
||||
getAccessibilityServiceTool().launchSettings()
|
||||
if (!AccessibilityService.waitForEnabled(timeout)) {
|
||||
throw ScriptInterruptedException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createRuntime(): ScriptRuntime {
|
||||
val runtime = super.createRuntime()
|
||||
runtime.putProperty("class.settings", SettingsActivity::class.java)
|
||||
runtime.putProperty("class.console", LogActivity::class.java)
|
||||
return runtime
|
||||
}
|
||||
|
||||
private fun getAccessibilityServiceTool(): AccessibilityTool {
|
||||
return AccessibilityTool(application)
|
||||
}
|
||||
|
||||
private fun isAccessibilityServiceEnabled(): Boolean {
|
||||
return getAccessibilityServiceTool().service.isEnabled()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@JvmStatic
|
||||
lateinit var instance: AutoJs
|
||||
private set
|
||||
|
||||
@Synchronized
|
||||
fun initInstance(application: Application) {
|
||||
instance = AutoJs(application)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.autojs.autojs.inrt.autojs
|
||||
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.inrt.Pref
|
||||
import org.autojs.autojs.core.accessibility.AccessibilityService
|
||||
import org.autojs.autojs.core.accessibility.OnKeyListener
|
||||
import org.autojs.autojs.core.inputevent.InputEventObserver
|
||||
import org.autojs.autojs.core.inputevent.ShellKeyObserver
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/8/14.
|
||||
*/
|
||||
class GlobalKeyObserver internal constructor() : OnKeyListener, ShellKeyObserver.KeyListener {
|
||||
private var mVolumeDownFromShell: Boolean = false
|
||||
private var mVolumeDownFromAccessibility: Boolean = false
|
||||
private var mVolumeUpFromShell: Boolean = false
|
||||
private var mVolumeUpFromAccessibility: Boolean = false
|
||||
|
||||
init {
|
||||
AccessibilityService.stickOnKeyObserver
|
||||
.addListener(this)
|
||||
val observer = ShellKeyObserver()
|
||||
observer.setKeyListener(this)
|
||||
InputEventObserver.getGlobal(GlobalAppContext.get()).addListener(observer)
|
||||
}
|
||||
|
||||
fun onVolumeUp() {
|
||||
Log.d(LOG_TAG, "onVolumeUp at " + System.currentTimeMillis())
|
||||
if (Pref.shouldStopAllScriptsWhenVolumeUp()) {
|
||||
AutoJs.instance.scriptEngineService.stopAllAndToast()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKeyEvent(keyCode: Int, event: KeyEvent) {
|
||||
if (event.action != KeyEvent.ACTION_UP)
|
||||
return
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
if (mVolumeDownFromShell) {
|
||||
mVolumeDownFromShell = false
|
||||
return
|
||||
}
|
||||
mVolumeUpFromAccessibility = true
|
||||
onVolumeDown()
|
||||
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
|
||||
if (mVolumeUpFromShell) {
|
||||
mVolumeUpFromShell = false
|
||||
return
|
||||
}
|
||||
mVolumeUpFromAccessibility = true
|
||||
onVolumeUp()
|
||||
}
|
||||
}
|
||||
|
||||
fun onVolumeDown() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun onKeyDown(keyName: String) {
|
||||
|
||||
}
|
||||
|
||||
override fun onKeyUp(keyName: String) {
|
||||
if ("KEY_VOLUMEUP" == keyName) {
|
||||
if (mVolumeUpFromAccessibility) {
|
||||
mVolumeUpFromAccessibility = false
|
||||
return
|
||||
}
|
||||
mVolumeUpFromShell = true
|
||||
onVolumeUp()
|
||||
} else if ("KEY_VOLUMEDOWN" == keyName) {
|
||||
if (mVolumeDownFromAccessibility) {
|
||||
mVolumeDownFromAccessibility = false
|
||||
return
|
||||
}
|
||||
mVolumeDownFromShell = true
|
||||
onVolumeDown()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val LOG_TAG = "GlobalKeyObserver"
|
||||
private val sSingleton = GlobalKeyObserver()
|
||||
|
||||
fun init() {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.autojs.autojs.inrt.autojs
|
||||
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
import org.autojs.autojs.execution.ScriptExecution
|
||||
import org.autojs.autojs.execution.ScriptExecutionListener
|
||||
import org.autojs.autojs6.R
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/3.
|
||||
*/
|
||||
class ScriptExecutionGlobalListener : ScriptExecutionListener {
|
||||
|
||||
override fun onStart(execution: ScriptExecution) {
|
||||
execution.engine.setTag(ENGINE_TAG_START_TIME, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
override fun onSuccess(execution: ScriptExecution, result: Any?) {
|
||||
onFinish(execution)
|
||||
}
|
||||
|
||||
private fun onFinish(execution: ScriptExecution) {
|
||||
val millis = execution.engine.getTag(ENGINE_TAG_START_TIME) as Long? ?: return
|
||||
val seconds = (System.currentTimeMillis() - millis) / 1000.0
|
||||
AutoJs.instance.scriptEngineService.globalConsole
|
||||
.verbose(GlobalAppContext.get().getString(R.string.text_execution_finished), execution.source.toString(), seconds)
|
||||
}
|
||||
|
||||
override fun onException(execution: ScriptExecution, e: Throwable) {
|
||||
onFinish(execution)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ENGINE_TAG_START_TIME = "start_time"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.autojs.autojs.inrt.autojs
|
||||
|
||||
import android.content.Context
|
||||
import org.autojs.autojs.engine.LoopBasedJavaScriptEngine
|
||||
import org.autojs.autojs.engine.encryption.ScriptEncryption
|
||||
import org.autojs.autojs.pio.PFiles
|
||||
import org.autojs.autojs.script.EncryptedScriptFileHeader
|
||||
import org.autojs.autojs.script.JavaScriptFileSource
|
||||
import org.autojs.autojs.script.ScriptSource
|
||||
import org.autojs.autojs.script.StringScriptSource
|
||||
import java.io.File
|
||||
import java.security.GeneralSecurityException
|
||||
|
||||
class XJavaScriptEngine(context: Context) : LoopBasedJavaScriptEngine(context) {
|
||||
|
||||
|
||||
override fun execute(source: ScriptSource, callback: ExecuteCallback?) {
|
||||
if (source is JavaScriptFileSource) {
|
||||
try {
|
||||
if (execute(source.file)) {
|
||||
return
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
return
|
||||
}
|
||||
}
|
||||
super.execute(source, callback)
|
||||
}
|
||||
|
||||
private fun execute(file: File): Boolean {
|
||||
val bytes = PFiles.readBytes(file.path)
|
||||
if (!EncryptedScriptFileHeader.isValidFile(bytes)) {
|
||||
return false
|
||||
}
|
||||
try {
|
||||
super.execute(StringScriptSource(file.name, String(ScriptEncryption.decrypt(bytes, EncryptedScriptFileHeader.BLOCK_SIZE))))
|
||||
} catch (e: GeneralSecurityException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.autojs.autojs.inrt.launch
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.TextUtils
|
||||
import org.autojs.autojs.inrt.LogActivity
|
||||
import org.autojs.autojs.inrt.Pref
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.engine.encryption.ScriptEncryption
|
||||
import org.autojs.autojs.execution.ExecutionConfig
|
||||
import org.autojs.autojs.execution.ScriptExecution
|
||||
import org.autojs.autojs.pio.PFiles
|
||||
import org.autojs.autojs.pio.UncheckedIOException
|
||||
import org.autojs.autojs.project.ProjectConfig
|
||||
import org.autojs.autojs.script.JavaScriptFileSource
|
||||
import org.autojs.autojs.script.JavaScriptSource
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2018/1/24.
|
||||
*/
|
||||
open class AssetsProjectLauncher(private val mAssetsProjectDir: String, private val mActivity: Context) {
|
||||
private val mProjectDir: String = File(mActivity.filesDir, "project/").path
|
||||
private val mProjectConfig: ProjectConfig = ProjectConfig.fromAssets(mActivity, ProjectConfig.configFileOfDir(mAssetsProjectDir))
|
||||
private val mMainScriptFile: File = File(mProjectDir, mProjectConfig.mainScriptFile)
|
||||
private val mHandler: Handler = Handler(Looper.getMainLooper())
|
||||
private var mScriptExecution: ScriptExecution? = null
|
||||
|
||||
init {
|
||||
prepare()
|
||||
}
|
||||
|
||||
fun launch(activity: Activity) {
|
||||
//如果需要隐藏日志界面,则直接运行脚本
|
||||
if (mProjectConfig.launchConfig.shouldHideLogs() || Pref.shouldHideLogs()) {
|
||||
runScript(activity)
|
||||
} else {
|
||||
//如果不隐藏日志界面
|
||||
//如果当前已经是日志界面则直接运行脚本
|
||||
if (activity is LogActivity) {
|
||||
runScript(null)
|
||||
} else {
|
||||
//否则显示日志界面并在日志界面中运行脚本
|
||||
mHandler.post {
|
||||
activity.startActivity(Intent(mActivity, LogActivity::class.java)
|
||||
.putExtra(LogActivity.EXTRA_LAUNCH_SCRIPT, true))
|
||||
activity.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun runScript(activity: Activity?) {
|
||||
if (mScriptExecution != null && mScriptExecution!!.engine != null &&
|
||||
!mScriptExecution!!.engine.isDestroyed) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
val source = JavaScriptFileSource("main", mMainScriptFile)
|
||||
val config = ExecutionConfig(workingDirectory = mProjectDir)
|
||||
if (source.executionMode and JavaScriptSource.EXECUTION_MODE_UI != 0) {
|
||||
config.intentFlags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME
|
||||
} else {
|
||||
activity?.finish()
|
||||
}
|
||||
mScriptExecution = AutoJs.instance.scriptEngineService.execute(source, config)
|
||||
} catch (e: Exception) {
|
||||
AutoJs.instance.globalConsole.error(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun prepare() {
|
||||
val projectConfigPath = PFiles.join(mProjectDir, ProjectConfig.CONFIG_FILE_NAME)
|
||||
val projectConfig = ProjectConfig.fromFile(projectConfigPath)
|
||||
if (projectConfig != null &&
|
||||
TextUtils.equals(projectConfig.buildInfo.buildId, mProjectConfig.buildInfo.buildId)) {
|
||||
initKey(projectConfig)
|
||||
return
|
||||
}
|
||||
initKey(mProjectConfig)
|
||||
PFiles.deleteRecursively(File(mProjectDir))
|
||||
try {
|
||||
PFiles.copyAssetDir(mActivity.assets, mAssetsProjectDir, mProjectDir, null)
|
||||
} catch (e: IOException) {
|
||||
throw UncheckedIOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initKey(projectConfig: ProjectConfig) {
|
||||
val key = MD5.md5(projectConfig.packageName + projectConfig.versionName + projectConfig.mainScriptFile)
|
||||
val vec = MD5.md5(projectConfig.buildInfo.buildId + projectConfig.name).substring(0, 16)
|
||||
try {
|
||||
val fieldKey = ScriptEncryption::class.java.getDeclaredField("mKey")
|
||||
fieldKey.isAccessible = true
|
||||
fieldKey.set(null, key)
|
||||
val fieldVector = ScriptEncryption::class.java.getDeclaredField("mInitVector")
|
||||
fieldVector.isAccessible = true
|
||||
fieldVector.set(null, vec)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.autojs.autojs.inrt.launch
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import org.autojs.autojs.app.GlobalAppContext
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2018/3/21.
|
||||
*/
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object GlobalProjectLauncher: AssetsProjectLauncher("project", GlobalAppContext.get())
|
||||
31
app/src/main/java/org/autojs/autojs/inrt/launch/MD5.java
Normal file
31
app/src/main/java/org/autojs/autojs/inrt/launch/MD5.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package org.autojs.autojs.inrt.launch;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class MD5 {
|
||||
|
||||
public static byte[] md5Bytes(String message) {
|
||||
try {
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
md5.update(message.getBytes());
|
||||
return md5.digest();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String md5(String message) {
|
||||
byte[] bytes = md5Bytes(message);
|
||||
StringBuilder hexString = new StringBuilder(32);
|
||||
for (byte b : bytes) {
|
||||
String hex = Integer.toHexString(0xFF & b);
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user