mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-24 21:33:16 +08:00
新增 auto.setFlags("useShell"),可以使用shell获取当前活动和当前包名,更加准确
This commit is contained in:
parent
ff0b215115
commit
2312e610bf
Binary file not shown.
@ -64,10 +64,19 @@ android {
|
||||
productFlavors {
|
||||
common {
|
||||
buildConfigField "String", "CHANNEL", '"common"'
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a"
|
||||
}
|
||||
}
|
||||
coolapk {
|
||||
buildConfigField "String", "CHANNEL", '"coolapk"'
|
||||
}
|
||||
x86 {
|
||||
buildConfigField "String", "CHANNEL", '"common"'
|
||||
ndk {
|
||||
abiFilters "x86"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -111,7 +111,8 @@ module.exports = function(runtime, global){
|
||||
|
||||
const flagsMap = {
|
||||
"findOnUiThread": 1,
|
||||
"useUsageStats": 2
|
||||
"useUsageStats": 2,
|
||||
"useShell": 4
|
||||
};
|
||||
|
||||
var auto = function(mode){
|
||||
@ -163,7 +164,10 @@ module.exports = function(runtime, global){
|
||||
|
||||
auto.getRoot = function(){
|
||||
var root = runtime.accessibilityBridge.getRootInCurrentWindow();
|
||||
return com.stardust.automator.UiObject.createRoot(root);
|
||||
if(root == null){
|
||||
return null;
|
||||
}
|
||||
return com.stardust.automator.UiObject.Companion.createRoot(root);
|
||||
}
|
||||
|
||||
auto.setWindowFilter = function(filter){
|
||||
|
||||
@ -30,7 +30,7 @@ import com.stardust.autojs.script.JavaScriptSource;
|
||||
import com.stardust.util.ResourceMonitor;
|
||||
import com.stardust.util.ScreenMetrics;
|
||||
import com.stardust.util.UiHandler;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.autojs.core.activity.ActivityInfoProvider;
|
||||
import com.stardust.view.accessibility.AccessibilityNotificationObserver;
|
||||
import com.stardust.view.accessibility.AccessibilityService;
|
||||
import com.stardust.view.accessibility.LayoutInspector;
|
||||
@ -54,7 +54,7 @@ public abstract class AutoJs {
|
||||
private final Application mApplication;
|
||||
private final UiHandler mUiHandler;
|
||||
private final AppUtils mAppUtils;
|
||||
private final AccessibilityInfoProvider mAccessibilityInfoProvider;
|
||||
private final ActivityInfoProvider mActivityInfoProvider;
|
||||
private final ScreenCaptureRequester mScreenCaptureRequester = new ScreenCaptureRequesterImpl();
|
||||
private final ScriptEngineService mScriptEngineService;
|
||||
private final GlobalConsole mGlobalConsole;
|
||||
@ -68,7 +68,7 @@ public abstract class AutoJs {
|
||||
mAppUtils = createAppUtils(mContext);
|
||||
mGlobalConsole = createGlobalConsole();
|
||||
mNotificationObserver = new AccessibilityNotificationObserver(mContext);
|
||||
mAccessibilityInfoProvider = new AccessibilityInfoProvider(mContext);
|
||||
mActivityInfoProvider = new ActivityInfoProvider(mContext);
|
||||
mScriptEngineService = buildScriptEngineService();
|
||||
ScriptEngineService.setInstance(mScriptEngineService);
|
||||
init();
|
||||
@ -166,7 +166,7 @@ public abstract class AutoJs {
|
||||
|
||||
|
||||
private void addAccessibilityServiceDelegates() {
|
||||
AccessibilityService.Companion.addDelegate(100, mAccessibilityInfoProvider);
|
||||
AccessibilityService.Companion.addDelegate(100, mActivityInfoProvider);
|
||||
AccessibilityService.Companion.addDelegate(200, mNotificationObserver);
|
||||
AccessibilityService.Companion.addDelegate(300, mAccessibilityActionRecorder);
|
||||
}
|
||||
@ -195,8 +195,8 @@ public abstract class AutoJs {
|
||||
return mScriptEngineService;
|
||||
}
|
||||
|
||||
public AccessibilityInfoProvider getInfoProvider() {
|
||||
return mAccessibilityInfoProvider;
|
||||
public ActivityInfoProvider getInfoProvider() {
|
||||
return mActivityInfoProvider;
|
||||
}
|
||||
|
||||
|
||||
@ -229,8 +229,8 @@ public abstract class AutoJs {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityInfoProvider getInfoProvider() {
|
||||
return mAccessibilityInfoProvider;
|
||||
public ActivityInfoProvider getInfoProvider() {
|
||||
return mActivityInfoProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.stardust.autojs.core.accessibility;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
@ -14,7 +15,7 @@ import com.stardust.app.AppOpsKt;
|
||||
import com.stardust.autojs.runtime.accessibility.AccessibilityConfig;
|
||||
import com.stardust.util.IntentUtil;
|
||||
import com.stardust.util.UiHandler;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.autojs.core.activity.ActivityInfoProvider;
|
||||
import com.stardust.view.accessibility.AccessibilityNotificationObserver;
|
||||
import com.stardust.view.accessibility.AccessibilityService;
|
||||
|
||||
@ -34,6 +35,7 @@ public abstract class AccessibilityBridge {
|
||||
|
||||
public static final int FLAG_FIND_ON_UI_THREAD = 1;
|
||||
public static final int FLAG_USE_USAGE_STATS = 2;
|
||||
public static final int FLAG_USE_SHELL = 4;
|
||||
|
||||
private int mMode = MODE_NORMAL;
|
||||
private int mFlags = 0;
|
||||
@ -63,6 +65,7 @@ public abstract class AccessibilityBridge {
|
||||
@Nullable
|
||||
public AccessibilityNodeInfo getRootInCurrentWindow() {
|
||||
AccessibilityService service = getService();
|
||||
|
||||
if (service == null)
|
||||
return null;
|
||||
if (mWindowFilter != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
@ -89,7 +92,7 @@ public abstract class AccessibilityBridge {
|
||||
mWindowFilter = windowFilter;
|
||||
}
|
||||
|
||||
public abstract AccessibilityInfoProvider getInfoProvider();
|
||||
public abstract ActivityInfoProvider getInfoProvider();
|
||||
|
||||
public void setMode(int mode) {
|
||||
mMode = mode;
|
||||
@ -108,6 +111,7 @@ public abstract class AccessibilityBridge {
|
||||
}
|
||||
}
|
||||
getInfoProvider().setUseUsageStats((mFlags & FLAG_USE_USAGE_STATS) != 0);
|
||||
getInfoProvider().setUseShell((mFlags & FLAG_USE_SHELL) != 0);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@ -0,0 +1,181 @@
|
||||
package com.stardust.autojs.core.activity
|
||||
|
||||
import android.accessibilityservice.AccessibilityService
|
||||
import android.app.AppOpsManager
|
||||
import android.app.usage.UsageStatsManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.stardust.app.isOpPermissionGranted
|
||||
import com.stardust.autojs.core.util.Shell
|
||||
import com.stardust.view.accessibility.AccessibilityDelegate
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/9.
|
||||
*/
|
||||
|
||||
class ActivityInfoProvider(private val context: Context) : AccessibilityDelegate {
|
||||
|
||||
private val mPackageManager: PackageManager = context.packageManager
|
||||
|
||||
@Volatile
|
||||
private var mLatestPackage: String = ""
|
||||
@Volatile
|
||||
private var mLatestActivity: String = ""
|
||||
private var mLatestComponentFromShell: ComponentName? = null
|
||||
|
||||
private var mShell: Shell? = null
|
||||
private var mUseShell = false
|
||||
|
||||
val latestPackage: String
|
||||
get() {
|
||||
val compFromShell = mLatestComponentFromShell
|
||||
if (useShell && compFromShell != null) {
|
||||
return compFromShell.packageName
|
||||
}
|
||||
if (useUsageStats && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
mLatestPackage = getLatestPackageByUsageStats()
|
||||
}
|
||||
return mLatestPackage
|
||||
}
|
||||
|
||||
val latestActivity: String
|
||||
get() {
|
||||
val compFromShell = mLatestComponentFromShell
|
||||
if (useShell && compFromShell != null) {
|
||||
return compFromShell.className
|
||||
}
|
||||
return mLatestActivity
|
||||
}
|
||||
|
||||
var useUsageStats: Boolean = false
|
||||
|
||||
var useShell: Boolean
|
||||
get() = mUseShell
|
||||
set(value) {
|
||||
if (value) {
|
||||
mShell.let {
|
||||
if (it == null) {
|
||||
mShell = createShell(200)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mShell?.exit()
|
||||
mShell = null
|
||||
}
|
||||
mUseShell = value
|
||||
}
|
||||
|
||||
override val eventTypes: Set<Int>?
|
||||
get() = AccessibilityDelegate.ALL_EVENT_TYPES
|
||||
|
||||
override fun onAccessibilityEvent(service: AccessibilityService, event: AccessibilityEvent): Boolean {
|
||||
if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
|
||||
setLatestComponent(event.packageName, event.className)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getLatestPackageByUsageStatsIfGranted(): String {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && context.isOpPermissionGranted(AppOpsManager.OPSTR_GET_USAGE_STATS)) {
|
||||
return getLatestPackageByUsageStats()
|
||||
}
|
||||
return mLatestPackage
|
||||
}
|
||||
|
||||
private fun setLatestComponentFromShellOutput(output: String) {
|
||||
val matcher = WINDOW_PATTERN.matcher(output)
|
||||
if (!matcher.find() || matcher.groupCount() < 1) {
|
||||
Log.w(LOG_TAG, "invalid format: $output")
|
||||
return
|
||||
}
|
||||
val latestPackage = matcher.group(1)
|
||||
if (latestPackage.contains(":")) {
|
||||
return
|
||||
}
|
||||
val latestActivity = if (matcher.groupCount() >= 2) {
|
||||
matcher.group(2).orEmpty()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
Log.d(LOG_TAG, "setLatestComponent: output = $output, comp = $latestPackage/$latestActivity")
|
||||
mLatestComponentFromShell = ComponentName(latestPackage, latestActivity)
|
||||
}
|
||||
|
||||
private fun createShell(dumpInterval: Int): Shell {
|
||||
val shell = Shell(true)
|
||||
shell.setCallback(object : Shell.Callback {
|
||||
override fun onOutput(str: String) {
|
||||
|
||||
}
|
||||
|
||||
override fun onNewLine(line: String) {
|
||||
setLatestComponentFromShellOutput(line)
|
||||
}
|
||||
|
||||
override fun onInitialized() {
|
||||
}
|
||||
|
||||
override fun onInterrupted(e: InterruptedException) {
|
||||
|
||||
}
|
||||
})
|
||||
shell.exec(DUMP_WINDOW_COMMAND.format(dumpInterval))
|
||||
return shell
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
fun getLatestPackageByUsageStats(): String {
|
||||
val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
|
||||
val current = System.currentTimeMillis()
|
||||
val usageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, current - 60 * 60 * 1000, current)
|
||||
return if (usageStats.isEmpty()) {
|
||||
mLatestPackage
|
||||
} else {
|
||||
usageStats.sortBy {
|
||||
it.lastTimeStamp
|
||||
}
|
||||
usageStats.last().packageName
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setLatestComponent(latestPackage: CharSequence?, latestClass: CharSequence?) {
|
||||
if (latestPackage == null || latestClass == null)
|
||||
return
|
||||
val latestPackageStr = latestPackage.toString()
|
||||
val latestClassStr = latestClass.toString()
|
||||
if (latestClassStr.startsWith("android.view.") || latestClassStr.startsWith("android.widget."))
|
||||
return
|
||||
try {
|
||||
val componentName = ComponentName(latestPackageStr, latestClassStr)
|
||||
mLatestActivity = mPackageManager.getActivityInfo(componentName, PackageManager.MATCH_DEFAULT_ONLY).name
|
||||
} catch (ignored: PackageManager.NameNotFoundException) {
|
||||
return
|
||||
}
|
||||
mLatestPackage = latestPackage.toString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val WINDOW_PATTERN = Pattern.compile("Window\\{\\S+\\s\\S+\\s([^\\/]+)\\/?([^}]+)?\\}")
|
||||
private val DUMP_WINDOW_COMMAND = """
|
||||
oldActivity=""
|
||||
currentActivity=`dumpsys window windows | grep -E 'mCurrentFocus'`
|
||||
while true
|
||||
do
|
||||
if [[ ${'$'}oldActivity != ${'$'}currentActivity && ${'$'}currentActivity != *"=null"* ]]; then
|
||||
echo ${'$'}currentActivity
|
||||
oldActivity=${'$'}currentActivity
|
||||
fi
|
||||
currentActivity=`dumpsys window windows | grep -E 'mCurrentFocus'`
|
||||
done
|
||||
""".trimIndent()
|
||||
|
||||
private const val LOG_TAG = "ActivityInfoProvider"
|
||||
}
|
||||
}
|
||||
@ -47,7 +47,7 @@ import com.stardust.util.ScreenMetrics;
|
||||
import com.stardust.util.SdkVersionUtil;
|
||||
import com.stardust.util.Supplier;
|
||||
import com.stardust.util.UiHandler;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.autojs.core.activity.ActivityInfoProvider;
|
||||
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
import org.mozilla.javascript.RhinoException;
|
||||
@ -140,7 +140,7 @@ public class ScriptRuntime {
|
||||
public final SimpleActionAutomator automator;
|
||||
|
||||
@ScriptVariable
|
||||
public final AccessibilityInfoProvider info;
|
||||
public final ActivityInfoProvider info;
|
||||
|
||||
@ScriptVariable
|
||||
public final UI ui;
|
||||
|
||||
@ -1,87 +0,0 @@
|
||||
package com.stardust.view.accessibility
|
||||
|
||||
import android.accessibilityservice.AccessibilityService
|
||||
import android.app.AppOpsManager
|
||||
import android.app.usage.UsageStatsManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.stardust.app.isOpPermissionGranted
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/9.
|
||||
*/
|
||||
|
||||
class AccessibilityInfoProvider(private val context: Context) : AccessibilityDelegate {
|
||||
|
||||
private val mPackageManager: PackageManager = context.packageManager
|
||||
|
||||
@Volatile
|
||||
private var mLatestPackage: String = ""
|
||||
|
||||
val latestPackage: String
|
||||
get() {
|
||||
if (useUsageStats && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
mLatestPackage = getLatestPackageByUsageStats()
|
||||
}
|
||||
return mLatestPackage
|
||||
}
|
||||
|
||||
@Volatile
|
||||
var latestActivity = ""
|
||||
private set
|
||||
|
||||
var useUsageStats: Boolean = false
|
||||
|
||||
override val eventTypes: Set<Int>?
|
||||
get() = AccessibilityDelegate.ALL_EVENT_TYPES
|
||||
|
||||
override fun onAccessibilityEvent(service: AccessibilityService, event: AccessibilityEvent): Boolean {
|
||||
if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
|
||||
setLatestComponent(event.packageName, event.className)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getLatestPackageByUsageStatsIfGranted(): String {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && context.isOpPermissionGranted(AppOpsManager.OPSTR_GET_USAGE_STATS)) {
|
||||
return getLatestPackageByUsageStats()
|
||||
}
|
||||
return mLatestPackage
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
fun getLatestPackageByUsageStats(): String {
|
||||
val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
|
||||
val current = System.currentTimeMillis()
|
||||
val usageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, current - 60 * 60 * 1000, current)
|
||||
return if (usageStats.isEmpty()) {
|
||||
mLatestPackage
|
||||
} else {
|
||||
usageStats.sortBy {
|
||||
it.lastTimeStamp
|
||||
}
|
||||
usageStats.last().packageName
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setLatestComponent(latestPackage: CharSequence?, latestClass: CharSequence?) {
|
||||
if (latestPackage == null || latestClass == null)
|
||||
return
|
||||
val latestPackageStr = latestPackage.toString()
|
||||
val latestClassStr = latestClass.toString()
|
||||
if (latestClassStr.startsWith("android.view.") || latestClassStr.startsWith("android.widget."))
|
||||
return
|
||||
try {
|
||||
val componentName = ComponentName(latestPackageStr, latestClassStr)
|
||||
latestActivity = mPackageManager.getActivityInfo(componentName, PackageManager.MATCH_DEFAULT_ONLY).name
|
||||
} catch (ignored: PackageManager.NameNotFoundException) {
|
||||
return
|
||||
}
|
||||
mLatestPackage = latestPackage.toString()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user