修复 选择器有多个条件时无法找到目标的问题
优化 选择器搜索效率
This commit is contained in:
@@ -1,133 +0,0 @@
|
|||||||
package androidx.recyclerview.widget
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Build.VERSION
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.widget.EdgeEffect
|
|
||||||
import androidx.annotation.Nullable
|
|
||||||
import androidx.core.widget.EdgeEffectCompat
|
|
||||||
import com.stardust.theme.ThemeColor
|
|
||||||
import com.stardust.theme.ThemeColorManager
|
|
||||||
import com.stardust.theme.ThemeColorMutable
|
|
||||||
import java.lang.reflect.Field
|
|
||||||
|
|
||||||
open class ThemeColorRecyclerView : RecyclerView, ThemeColorMutable {
|
|
||||||
private var mLeftGlowField: Field? = null
|
|
||||||
private var mTopGlowField: Field? = null
|
|
||||||
private var mRightGlowField: Field? = null
|
|
||||||
private var mBottomGlowField: Field? = null
|
|
||||||
private var mEdgeEffectField: Field? = null
|
|
||||||
private var mColorPrimary: Int = 0
|
|
||||||
private var hasAppliedThemeColorLeft: Boolean = false
|
|
||||||
private var hasAppliedThemeColorTop: Boolean = false
|
|
||||||
private var hasAppliedThemeColorRight: Boolean = false
|
|
||||||
private var hasAppliedThemeColorBottom: Boolean = false
|
|
||||||
|
|
||||||
constructor(context: Context) : super(context) {
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(context: Context, @Nullable attrs: AttributeSet) : super(context, attrs) {
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(context: Context, @Nullable attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyThemeColor(edgeEffectCompatField: Field?): Boolean {
|
|
||||||
try {
|
|
||||||
val edgeEffectCompat = edgeEffectCompatField?.get(this) as EdgeEffectCompat?
|
|
||||||
if (edgeEffectCompat != null) {
|
|
||||||
return this.setEdgeEffectColor(edgeEffectCompat, this.mColorPrimary)
|
|
||||||
}
|
|
||||||
} catch (var3: Exception) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun init() {
|
|
||||||
try {
|
|
||||||
this.mEdgeEffectField = EdgeEffectCompat::class.java.getDeclaredField("mEdgeEffect")
|
|
||||||
this.mEdgeEffectField!!.isAccessible = true
|
|
||||||
this.mLeftGlowField = RecyclerView::class.java.getDeclaredField("mLeftGlow")
|
|
||||||
this.mLeftGlowField!!.isAccessible = true
|
|
||||||
this.mRightGlowField = RecyclerView::class.java.getDeclaredField("mRightGlow")
|
|
||||||
this.mRightGlowField!!.isAccessible = true
|
|
||||||
this.mTopGlowField = RecyclerView::class.java.getDeclaredField("mTopGlow")
|
|
||||||
this.mTopGlowField!!.isAccessible = true
|
|
||||||
this.mBottomGlowField = RecyclerView::class.java.getDeclaredField("mBottomGlow")
|
|
||||||
this.mBottomGlowField!!.isAccessible = true
|
|
||||||
} catch (var2: Exception) {
|
|
||||||
var2.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
ThemeColorManager.add(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setEdgeEffectColor(compat: EdgeEffectCompat?, color: Int): Boolean {
|
|
||||||
return if (compat == null) {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
if (VERSION.SDK_INT >= 21) {
|
|
||||||
val edgeEffect = this.mEdgeEffectField!!.get(compat) as EdgeEffect
|
|
||||||
edgeEffect.color = color
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
} catch (var4: Exception) {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setThemeColor(color: ThemeColor) {
|
|
||||||
if (color.colorPrimary != this.mColorPrimary) {
|
|
||||||
this.mColorPrimary = color.colorPrimary
|
|
||||||
this.invalidateGlows()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override fun invalidateGlows() {
|
|
||||||
super.invalidateGlows()
|
|
||||||
this.hasAppliedThemeColorTop = false
|
|
||||||
this.hasAppliedThemeColorRight = this.hasAppliedThemeColorTop
|
|
||||||
this.hasAppliedThemeColorLeft = this.hasAppliedThemeColorRight
|
|
||||||
this.hasAppliedThemeColorBottom = this.hasAppliedThemeColorLeft
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override fun ensureLeftGlow() {
|
|
||||||
super.ensureLeftGlow()
|
|
||||||
if (!this.hasAppliedThemeColorLeft) {
|
|
||||||
this.hasAppliedThemeColorLeft = this.applyThemeColor(this.mLeftGlowField)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override fun ensureRightGlow() {
|
|
||||||
super.ensureLeftGlow()
|
|
||||||
if (!this.hasAppliedThemeColorRight) {
|
|
||||||
this.hasAppliedThemeColorRight = this.applyThemeColor(this.mRightGlowField)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override fun ensureTopGlow() {
|
|
||||||
super.ensureTopGlow()
|
|
||||||
if (!this.hasAppliedThemeColorTop) {
|
|
||||||
this.hasAppliedThemeColorTop = this.applyThemeColor(this.mTopGlowField)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override fun ensureBottomGlow() {
|
|
||||||
super.ensureBottomGlow()
|
|
||||||
if (!this.hasAppliedThemeColorBottom) {
|
|
||||||
this.hasAppliedThemeColorBottom = this.applyThemeColor(this.mBottomGlowField)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,10 +15,12 @@ import com.stardust.automator.ActionArgument;
|
|||||||
import com.stardust.automator.UiGlobalSelector;
|
import com.stardust.automator.UiGlobalSelector;
|
||||||
import com.stardust.automator.UiObject;
|
import com.stardust.automator.UiObject;
|
||||||
import com.stardust.automator.UiObjectCollection;
|
import com.stardust.automator.UiObjectCollection;
|
||||||
import com.stardust.automator.filter.DfsFilter;
|
import com.stardust.automator.filter.Filter;
|
||||||
import com.stardust.concurrent.VolatileBox;
|
import com.stardust.concurrent.VolatileBox;
|
||||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
|
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
|
||||||
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT;
|
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT;
|
||||||
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE;
|
import static androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE;
|
||||||
@@ -106,7 +108,7 @@ public class UiSelector extends UiGlobalSelector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UiGlobalSelector textMatches(String regex) {
|
public UiGlobalSelector textMatches(@NotNull String regex) {
|
||||||
return super.textMatches(convertRegex(regex));
|
return super.textMatches(convertRegex(regex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,22 +122,22 @@ public class UiSelector extends UiGlobalSelector {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UiGlobalSelector classNameMatches(String regex) {
|
public UiGlobalSelector classNameMatches(@NotNull String regex) {
|
||||||
return super.classNameMatches(convertRegex(regex));
|
return super.classNameMatches(convertRegex(regex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UiGlobalSelector idMatches(String regex) {
|
public UiGlobalSelector idMatches(@NotNull String regex) {
|
||||||
return super.idMatches(convertRegex(regex));
|
return super.idMatches(convertRegex(regex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UiGlobalSelector packageNameMatches(String regex) {
|
public UiGlobalSelector packageNameMatches(@NotNull String regex) {
|
||||||
return super.packageNameMatches(convertRegex(regex));
|
return super.packageNameMatches(convertRegex(regex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UiGlobalSelector descMatches(String regex) {
|
public UiGlobalSelector descMatches(@NotNull String regex) {
|
||||||
return super.descMatches(convertRegex(regex));
|
return super.descMatches(convertRegex(regex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,13 +226,13 @@ public class UiSelector extends UiGlobalSelector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ScriptInterface
|
@ScriptInterface
|
||||||
public UiSelector id(final String id) {
|
public UiSelector id(@NotNull final String id) {
|
||||||
if (!id.contains(":")) {
|
if (!id.contains(":")) {
|
||||||
addFilter(new DfsFilter() {
|
addFilter(new Filter() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean isIncluded(UiObject nodeInfo) {
|
public boolean filter(@NotNull UiObject node) {
|
||||||
String fullId = mAccessibilityBridge.getInfoProvider().getLatestPackage() + ":id/" + id;
|
String fullId = mAccessibilityBridge.getInfoProvider().getLatestPackage() + ":id/" + id;
|
||||||
return fullId.equals(nodeInfo.getViewIdResourceName());
|
return fullId.equals(node.getViewIdResourceName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -245,11 +247,11 @@ public class UiSelector extends UiGlobalSelector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UiGlobalSelector idStartsWith(String prefix) {
|
public UiGlobalSelector idStartsWith(@NotNull String prefix) {
|
||||||
if (!prefix.contains(":")) {
|
if (!prefix.contains(":")) {
|
||||||
addFilter(new DfsFilter() {
|
addFilter(new Filter() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean isIncluded(UiObject nodeInfo) {
|
public boolean filter(@NotNull UiObject nodeInfo) {
|
||||||
String fullIdPrefix = mAccessibilityBridge.getInfoProvider().getLatestPackage() + ":id/" + prefix;
|
String fullIdPrefix = mAccessibilityBridge.getInfoProvider().getLatestPackage() + ":id/" + prefix;
|
||||||
String id = nodeInfo.getViewIdResourceName();
|
String id = nodeInfo.getViewIdResourceName();
|
||||||
return id != null && id.startsWith(fullIdPrefix);
|
return id != null && id.startsWith(fullIdPrefix);
|
||||||
|
|||||||
@@ -2,23 +2,7 @@ package com.stardust.automator
|
|||||||
|
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import com.stardust.automator.filter.*
|
||||||
import com.stardust.automator.filter.BooleanFilter
|
|
||||||
import com.stardust.automator.filter.BoundsFilter
|
|
||||||
import com.stardust.automator.filter.ClassNameFilter
|
|
||||||
import com.stardust.automator.filter.DescFilter
|
|
||||||
import com.stardust.automator.filter.DfsFilter
|
|
||||||
import com.stardust.automator.filter.IdFilter
|
|
||||||
import com.stardust.automator.filter.IntFilter
|
|
||||||
import com.stardust.automator.filter.ListFilter
|
|
||||||
import com.stardust.automator.filter.PackageNameFilter
|
|
||||||
import com.stardust.automator.filter.TextFilter
|
|
||||||
import com.stardust.automator.simple_action.Able
|
|
||||||
import com.stardust.util.Supplier
|
|
||||||
|
|
||||||
import java.util.ArrayList
|
|
||||||
import java.util.LinkedList
|
|
||||||
import java.util.Queue
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/3/8.
|
* Created by Stardust on 2017/3/8.
|
||||||
@@ -26,154 +10,154 @@ import java.util.Queue
|
|||||||
|
|
||||||
open class UiGlobalSelector {
|
open class UiGlobalSelector {
|
||||||
|
|
||||||
private val mFilters = LinkedList<ListFilter>()
|
private val mSelector = Selector()
|
||||||
|
|
||||||
//// 第一类筛选条件
|
//// 第一类筛选条件
|
||||||
|
|
||||||
open fun id(id: String): UiGlobalSelector {
|
open fun id(id: String): UiGlobalSelector {
|
||||||
mFilters.add(IdFilter.equals(id))
|
mSelector.add(IdFilter.equals(id))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun idContains(str: String): UiGlobalSelector {
|
fun idContains(str: String): UiGlobalSelector {
|
||||||
mFilters.add(IdFilter.contains(str))
|
mSelector.add(IdFilter.contains(str))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun idStartsWith(prefix: String): UiGlobalSelector {
|
open fun idStartsWith(prefix: String): UiGlobalSelector {
|
||||||
mFilters.add(IdFilter.startsWith(prefix))
|
mSelector.add(IdFilter.startsWith(prefix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun idEndsWith(suffix: String): UiGlobalSelector {
|
fun idEndsWith(suffix: String): UiGlobalSelector {
|
||||||
mFilters.add(IdFilter.endsWith(suffix))
|
mSelector.add(IdFilter.endsWith(suffix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun idMatches(regex: String): UiGlobalSelector {
|
open fun idMatches(regex: String): UiGlobalSelector {
|
||||||
mFilters.add(IdFilter.matches(regex))
|
mSelector.add(IdFilter.matches(regex))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun text(text: String): UiGlobalSelector {
|
fun text(text: String): UiGlobalSelector {
|
||||||
mFilters.add(TextFilter.equals(text))
|
mSelector.add(TextFilters.equals(text))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun textContains(str: String): UiGlobalSelector {
|
fun textContains(str: String): UiGlobalSelector {
|
||||||
mFilters.add(TextFilter.contains(str))
|
mSelector.add(TextFilters.contains(str))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun textStartsWith(prefix: String): UiGlobalSelector {
|
fun textStartsWith(prefix: String): UiGlobalSelector {
|
||||||
mFilters.add(TextFilter.startsWith(prefix))
|
mSelector.add(TextFilters.startsWith(prefix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun textEndsWith(suffix: String): UiGlobalSelector {
|
fun textEndsWith(suffix: String): UiGlobalSelector {
|
||||||
mFilters.add(TextFilter.endsWith(suffix))
|
mSelector.add(TextFilters.endsWith(suffix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun textMatches(regex: String): UiGlobalSelector {
|
open fun textMatches(regex: String): UiGlobalSelector {
|
||||||
mFilters.add(TextFilter.matches(regex))
|
mSelector.add(TextFilters.matches(regex))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun desc(desc: String): UiGlobalSelector {
|
fun desc(desc: String): UiGlobalSelector {
|
||||||
mFilters.add(DescFilter.equals(desc))
|
mSelector.add(DescFilters.equals(desc))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun descContains(str: String): UiGlobalSelector {
|
fun descContains(str: String): UiGlobalSelector {
|
||||||
mFilters.add(DescFilter.contains(str))
|
mSelector.add(DescFilters.contains(str))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun descStartsWith(prefix: String): UiGlobalSelector {
|
fun descStartsWith(prefix: String): UiGlobalSelector {
|
||||||
mFilters.add(DescFilter.startsWith(prefix))
|
mSelector.add(DescFilters.startsWith(prefix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun descEndsWith(suffix: String): UiGlobalSelector {
|
fun descEndsWith(suffix: String): UiGlobalSelector {
|
||||||
mFilters.add(DescFilter.endsWith(suffix))
|
mSelector.add(DescFilters.endsWith(suffix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun descMatches(regex: String): UiGlobalSelector {
|
open fun descMatches(regex: String): UiGlobalSelector {
|
||||||
mFilters.add(DescFilter.matches(regex))
|
mSelector.add(DescFilters.matches(regex))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun className(className: String): UiGlobalSelector {
|
fun className(className: String): UiGlobalSelector {
|
||||||
mFilters.add(ClassNameFilter.equals(className))
|
mSelector.add(ClassNameFilters.equals(className))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun classNameContains(str: String): UiGlobalSelector {
|
fun classNameContains(str: String): UiGlobalSelector {
|
||||||
mFilters.add(ClassNameFilter.contains(str))
|
mSelector.add(ClassNameFilters.contains(str))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun classNameStartsWith(prefix: String): UiGlobalSelector {
|
fun classNameStartsWith(prefix: String): UiGlobalSelector {
|
||||||
mFilters.add(ClassNameFilter.startsWith(prefix))
|
mSelector.add(ClassNameFilters.startsWith(prefix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun classNameEndsWith(suffix: String): UiGlobalSelector {
|
fun classNameEndsWith(suffix: String): UiGlobalSelector {
|
||||||
mFilters.add(ClassNameFilter.endsWith(suffix))
|
mSelector.add(ClassNameFilters.endsWith(suffix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun classNameMatches(regex: String): UiGlobalSelector {
|
open fun classNameMatches(regex: String): UiGlobalSelector {
|
||||||
mFilters.add(ClassNameFilter.matches(regex))
|
mSelector.add(ClassNameFilters.matches(regex))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun packageName(packageName: String): UiGlobalSelector {
|
fun packageName(packageName: String): UiGlobalSelector {
|
||||||
mFilters.add(PackageNameFilter.equals(packageName))
|
mSelector.add(PackageNameFilter.equals(packageName))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun packageNameContains(str: String): UiGlobalSelector {
|
fun packageNameContains(str: String): UiGlobalSelector {
|
||||||
mFilters.add(PackageNameFilter.contains(str))
|
mSelector.add(PackageNameFilter.contains(str))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun packageNameStartsWith(prefix: String): UiGlobalSelector {
|
fun packageNameStartsWith(prefix: String): UiGlobalSelector {
|
||||||
mFilters.add(PackageNameFilter.startsWith(prefix))
|
mSelector.add(PackageNameFilter.startsWith(prefix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun packageNameEndsWith(suffix: String): UiGlobalSelector {
|
fun packageNameEndsWith(suffix: String): UiGlobalSelector {
|
||||||
mFilters.add(PackageNameFilter.endsWith(suffix))
|
mSelector.add(PackageNameFilter.endsWith(suffix))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun packageNameMatches(regex: String): UiGlobalSelector {
|
open fun packageNameMatches(regex: String): UiGlobalSelector {
|
||||||
mFilters.add(PackageNameFilter.matches(regex))
|
mSelector.add(PackageNameFilter.matches(regex))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bounds(l: Int, t: Int, r: Int, b: Int): UiGlobalSelector {
|
fun bounds(l: Int, t: Int, r: Int, b: Int): UiGlobalSelector {
|
||||||
mFilters.add(BoundsFilter(Rect(l, t, r, b), BoundsFilter.TYPE_EQUALS))
|
mSelector.add(BoundsFilter(Rect(l, t, r, b), BoundsFilter.TYPE_EQUALS))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun boundsInside(l: Int, t: Int, r: Int, b: Int): UiGlobalSelector {
|
fun boundsInside(l: Int, t: Int, r: Int, b: Int): UiGlobalSelector {
|
||||||
mFilters.add(BoundsFilter(Rect(l, t, r, b), BoundsFilter.TYPE_INSIDE))
|
mSelector.add(BoundsFilter(Rect(l, t, r, b), BoundsFilter.TYPE_INSIDE))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun boundsContains(l: Int, t: Int, r: Int, b: Int): UiGlobalSelector {
|
fun boundsContains(l: Int, t: Int, r: Int, b: Int): UiGlobalSelector {
|
||||||
mFilters.add(BoundsFilter(Rect(l, t, r, b), BoundsFilter.TYPE_CONTAINS))
|
mSelector.add(BoundsFilter(Rect(l, t, r, b), BoundsFilter.TYPE_CONTAINS))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun drawingOrder(order: Int): UiGlobalSelector {
|
fun drawingOrder(order: Int): UiGlobalSelector {
|
||||||
mFilters.add(object : DfsFilter() {
|
mSelector.add(object : Filter {
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && nodeInfo.drawingOrder == order
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && node.drawingOrder == order
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@@ -186,222 +170,222 @@ open class UiGlobalSelector {
|
|||||||
//// 第二类筛选条件 -able
|
//// 第二类筛选条件 -able
|
||||||
|
|
||||||
fun checkable(b: Boolean): UiGlobalSelector {
|
fun checkable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CHECKABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.CHECKABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checked(b: Boolean): UiGlobalSelector {
|
fun checked(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CHECKED, b])
|
mSelector.add(BooleanFilter[BooleanFilter.CHECKED, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun focusable(b: Boolean): UiGlobalSelector {
|
fun focusable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.FOCUSABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.FOCUSABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun focused(b: Boolean): UiGlobalSelector {
|
fun focused(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.FOCUSED, b])
|
mSelector.add(BooleanFilter[BooleanFilter.FOCUSED, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visibleToUser(b: Boolean): UiGlobalSelector {
|
fun visibleToUser(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.VISIBLE_TO_USER, b])
|
mSelector.add(BooleanFilter[BooleanFilter.VISIBLE_TO_USER, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun accessibilityFocused(b: Boolean): UiGlobalSelector {
|
fun accessibilityFocused(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.ACCESSIBILITY_FOCUSED, b])
|
mSelector.add(BooleanFilter[BooleanFilter.ACCESSIBILITY_FOCUSED, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selected(b: Boolean): UiGlobalSelector {
|
fun selected(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.SELECTED, b])
|
mSelector.add(BooleanFilter[BooleanFilter.SELECTED, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clickable(b: Boolean): UiGlobalSelector {
|
fun clickable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CLICKABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.CLICKABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun longClickable(b: Boolean): UiGlobalSelector {
|
fun longClickable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.LONG_CLICKABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.LONG_CLICKABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enabled(b: Boolean): UiGlobalSelector {
|
fun enabled(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.ENABLED, b])
|
mSelector.add(BooleanFilter[BooleanFilter.ENABLED, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun password(b: Boolean): UiGlobalSelector {
|
fun password(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.PASSWORD, b])
|
mSelector.add(BooleanFilter[BooleanFilter.PASSWORD, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scrollable(b: Boolean): UiGlobalSelector {
|
fun scrollable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.SCROLLABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.SCROLLABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun editable(b: Boolean): UiGlobalSelector {
|
fun editable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.EDITABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.EDITABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contentInvalid(b: Boolean): UiGlobalSelector {
|
fun contentInvalid(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CONTENT_INVALID, b])
|
mSelector.add(BooleanFilter[BooleanFilter.CONTENT_INVALID, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contextClickable(b: Boolean): UiGlobalSelector {
|
fun contextClickable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CONTEXT_CLICKABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.CONTEXT_CLICKABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun multiLine(b: Boolean): UiGlobalSelector {
|
fun multiLine(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.MULTI_LINE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.MULTI_LINE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dismissable(b: Boolean): UiGlobalSelector {
|
fun dismissable(b: Boolean): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.DISMISSABLE, b])
|
mSelector.add(BooleanFilter[BooleanFilter.DISMISSABLE, b])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkable(): UiGlobalSelector {
|
fun checkable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CHECKABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.CHECKABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checked(): UiGlobalSelector {
|
fun checked(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CHECKED, true])
|
mSelector.add(BooleanFilter[BooleanFilter.CHECKED, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun focusable(): UiGlobalSelector {
|
fun focusable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.FOCUSABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.FOCUSABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun focused(): UiGlobalSelector {
|
fun focused(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.FOCUSED, true])
|
mSelector.add(BooleanFilter[BooleanFilter.FOCUSED, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visibleToUser(): UiGlobalSelector {
|
fun visibleToUser(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.VISIBLE_TO_USER, true])
|
mSelector.add(BooleanFilter[BooleanFilter.VISIBLE_TO_USER, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun accessibilityFocused(): UiGlobalSelector {
|
fun accessibilityFocused(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.ACCESSIBILITY_FOCUSED, true])
|
mSelector.add(BooleanFilter[BooleanFilter.ACCESSIBILITY_FOCUSED, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selected(): UiGlobalSelector {
|
fun selected(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.SELECTED, true])
|
mSelector.add(BooleanFilter[BooleanFilter.SELECTED, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clickable(): UiGlobalSelector {
|
fun clickable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CLICKABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.CLICKABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun longClickable(): UiGlobalSelector {
|
fun longClickable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.LONG_CLICKABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.LONG_CLICKABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enabled(): UiGlobalSelector {
|
fun enabled(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.ENABLED, true])
|
mSelector.add(BooleanFilter[BooleanFilter.ENABLED, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun password(): UiGlobalSelector {
|
fun password(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.PASSWORD, true])
|
mSelector.add(BooleanFilter[BooleanFilter.PASSWORD, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scrollable(): UiGlobalSelector {
|
fun scrollable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.SCROLLABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.SCROLLABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun editable(): UiGlobalSelector {
|
fun editable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.EDITABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.EDITABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contentInvalid(): UiGlobalSelector {
|
fun contentInvalid(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CONTENT_INVALID, true])
|
mSelector.add(BooleanFilter[BooleanFilter.CONTENT_INVALID, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contextClickable(): UiGlobalSelector {
|
fun contextClickable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.CONTEXT_CLICKABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.CONTEXT_CLICKABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun multiLine(): UiGlobalSelector {
|
fun multiLine(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.MULTI_LINE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.MULTI_LINE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dismissable(): UiGlobalSelector {
|
fun dismissable(): UiGlobalSelector {
|
||||||
mFilters.add(BooleanFilter[BooleanFilter.DISMISSABLE, true])
|
mSelector.add(BooleanFilter[BooleanFilter.DISMISSABLE, true])
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//第三类 int
|
//第三类 int
|
||||||
fun depth(d: Int): UiGlobalSelector {
|
fun depth(d: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.DEPTH, d))
|
mSelector.add(IntFilter(IntFilter.DEPTH, d))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun row(d: Int): UiGlobalSelector {
|
fun row(d: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.ROW, d))
|
mSelector.add(IntFilter(IntFilter.ROW, d))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rowCount(d: Int): UiGlobalSelector {
|
fun rowCount(d: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.ROW_COUNT, d))
|
mSelector.add(IntFilter(IntFilter.ROW_COUNT, d))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rowSpan(d: Int): UiGlobalSelector {
|
fun rowSpan(d: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.ROW_SPAN, d))
|
mSelector.add(IntFilter(IntFilter.ROW_SPAN, d))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun column(d: Int): UiGlobalSelector {
|
fun column(d: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.COLUMN, d))
|
mSelector.add(IntFilter(IntFilter.COLUMN, d))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun columnCount(d: Int): UiGlobalSelector {
|
fun columnCount(d: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.COLUMN_COUNT, d))
|
mSelector.add(IntFilter(IntFilter.COLUMN_COUNT, d))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun columnSpan(d: Int): UiGlobalSelector {
|
fun columnSpan(d: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.COLUMN_SPAN, d))
|
mSelector.add(IntFilter(IntFilter.COLUMN_SPAN, d))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun indexInParent(index: Int): UiGlobalSelector {
|
fun indexInParent(index: Int): UiGlobalSelector {
|
||||||
mFilters.add(IntFilter(IntFilter.INDEX_IN_PARENT, index))
|
mSelector.add(IntFilter(IntFilter.INDEX_IN_PARENT, index))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun filter(filter: BooleanFilter.BooleanSupplier): UiGlobalSelector {
|
fun filter(filter: BooleanFilter.BooleanSupplier): UiGlobalSelector {
|
||||||
mFilters.add(object : DfsFilter() {
|
mSelector.add(object : Filter {
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
return filter[nodeInfo]
|
return filter[node]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return this
|
return this
|
||||||
@@ -416,14 +400,7 @@ open class UiGlobalSelector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findAndReturnList(node: UiObject, max: Int = Int.MAX_VALUE): List<UiObject> {
|
fun findAndReturnList(node: UiObject, max: Int = Int.MAX_VALUE): List<UiObject> {
|
||||||
var list: List<UiObject> = listOf(node)
|
return DFS(mSelector, max).search(node)
|
||||||
for (filter in mFilters) {
|
|
||||||
val oldMax = filter.maxCount
|
|
||||||
filter.maxCount = max
|
|
||||||
list = filter.filter(list)
|
|
||||||
filter.maxCount = oldMax
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findOneOf(node: UiObject): UiObject? {
|
fun findOneOf(node: UiObject): UiObject? {
|
||||||
@@ -433,19 +410,12 @@ open class UiGlobalSelector {
|
|||||||
} else collection[0]
|
} else collection[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addFilter(filter: ListFilter): UiGlobalSelector {
|
fun addFilter(filter: Filter): UiGlobalSelector {
|
||||||
mFilters.add(filter)
|
mSelector.add(filter)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
val str = StringBuilder()
|
return mSelector.toString()
|
||||||
for (filter in mFilters) {
|
|
||||||
str.append(filter.toString()).append(".")
|
|
||||||
}
|
|
||||||
if (str.isNotEmpty()) {
|
|
||||||
str.deleteCharAt(str.length - 1)
|
|
||||||
}
|
|
||||||
return str.toString()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
automator/src/main/java/com/stardust/automator/filter/BFS.kt
Normal file
10
automator/src/main/java/com/stardust/automator/filter/BFS.kt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package com.stardust.automator.filter
|
||||||
|
|
||||||
|
import com.stardust.automator.UiObject
|
||||||
|
|
||||||
|
class BFS(val filter: Filter, val limit: Int = Int.MAX_VALUE) {
|
||||||
|
|
||||||
|
fun search(node: UiObject) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import java.util.HashMap
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BooleanFilter(private val mBooleanSupplier: BooleanSupplier, private val mExceptedValue: Boolean) : DfsFilter() {
|
class BooleanFilter(private val mBooleanSupplier: BooleanSupplier, private val mExceptedValue: Boolean) : Filter {
|
||||||
|
|
||||||
interface BooleanSupplier {
|
interface BooleanSupplier {
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ class BooleanFilter(private val mBooleanSupplier: BooleanSupplier, private val m
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
return mBooleanSupplier[nodeInfo] == mExceptedValue
|
return mBooleanSupplier[node] == mExceptedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ import java.util.Locale
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BoundsFilter(private val mBounds: Rect, private val mType: Int) : DfsFilter() {
|
class BoundsFilter(private val mBounds: Rect, private val mType: Int) : Filter {
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
if (mType == TYPE_CONTAINS) {
|
if (mType == TYPE_CONTAINS) {
|
||||||
return AccessibilityNodeInfoHelper.getBoundsInScreen(nodeInfo).contains(mBounds)
|
return AccessibilityNodeInfoHelper.getBoundsInScreen(node).contains(mBounds)
|
||||||
}
|
}
|
||||||
val boundsInScreen = AccessibilityNodeInfoHelper.getBoundsInScreen(nodeInfo)
|
val boundsInScreen = AccessibilityNodeInfoHelper.getBoundsInScreen(node)
|
||||||
return if (mType == TYPE_EQUALS) boundsInScreen == mBounds else mBounds.contains(boundsInScreen)
|
return if (mType == TYPE_EQUALS) boundsInScreen == mBounds else mBounds.contains(boundsInScreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
object ClassNameFilter {
|
object ClassNameFilters {
|
||||||
|
|
||||||
private val CLASS_NAME_GETTER = object : KeyGetter {
|
private val CLASS_NAME_GETTER = object : KeyGetter {
|
||||||
override fun getKey(nodeInfo: UiObject): String? {
|
override fun getKey(nodeInfo: UiObject): String? {
|
||||||
@@ -19,27 +19,27 @@ object ClassNameFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun equals(text: String): ListFilter {
|
fun equals(text: String): Filter {
|
||||||
var text = text
|
var className = text
|
||||||
if (!text.contains(".")) {
|
if (!className.contains(".")) {
|
||||||
text = "android.widget.$text"
|
className = "android.widget.$className"
|
||||||
}
|
}
|
||||||
return StringEqualsFilter(text, CLASS_NAME_GETTER)
|
return StringEqualsFilter(className, CLASS_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contains(str: String): ListFilter {
|
fun contains(str: String): Filter {
|
||||||
return StringContainsFilter(str, CLASS_NAME_GETTER)
|
return StringContainsFilter(str, CLASS_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startsWith(prefix: String): ListFilter {
|
fun startsWith(prefix: String): Filter {
|
||||||
return StringStartsWithFilter(prefix, CLASS_NAME_GETTER)
|
return StringStartsWithFilter(prefix, CLASS_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun endsWith(suffix: String): ListFilter {
|
fun endsWith(suffix: String): Filter {
|
||||||
return StringEndsWithFilter(suffix, CLASS_NAME_GETTER)
|
return StringEndsWithFilter(suffix, CLASS_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun matches(regex: String): ListFilter {
|
fun matches(regex: String): Filter {
|
||||||
return StringMatchesFilter(regex, CLASS_NAME_GETTER)
|
return StringMatchesFilter(regex, CLASS_NAME_GETTER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
42
automator/src/main/java/com/stardust/automator/filter/DFS.kt
Normal file
42
automator/src/main/java/com/stardust/automator/filter/DFS.kt
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package com.stardust.automator.filter
|
||||||
|
|
||||||
|
import com.stardust.automator.UiObject
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/3/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DFS(val filter: Filter, val limit: Int = Int.MAX_VALUE) {
|
||||||
|
|
||||||
|
fun search(node: UiObject): List<UiObject> {
|
||||||
|
val list = ArrayList<UiObject>()
|
||||||
|
if (filter.filter(node)) {
|
||||||
|
list.add(node)
|
||||||
|
if (list.size >= limit) {
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterChildren(node, list)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun filterChildren(parent: UiObject, list: MutableList<UiObject>) {
|
||||||
|
for (i in 0 until parent.childCount) {
|
||||||
|
val child = parent.child(i) ?: continue
|
||||||
|
val included = filter.filter(child)
|
||||||
|
if (included) {
|
||||||
|
list.add(child)
|
||||||
|
if (list.size >= limit) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterChildren(child, list)
|
||||||
|
if (!included) {
|
||||||
|
child.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
object DescFilter {
|
object DescFilters {
|
||||||
|
|
||||||
private val DESC_GETTER = object : KeyGetter {
|
private val DESC_GETTER = object : KeyGetter {
|
||||||
override fun getKey(nodeInfo: UiObject): String? {
|
override fun getKey(nodeInfo: UiObject): String? {
|
||||||
@@ -19,23 +19,23 @@ object DescFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun equals(text: String): ListFilter {
|
fun equals(text: String): Filter {
|
||||||
return StringEqualsFilter(text, DESC_GETTER)
|
return StringEqualsFilter(text, DESC_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contains(str: String): ListFilter {
|
fun contains(str: String): Filter {
|
||||||
return StringContainsFilter(str, DESC_GETTER)
|
return StringContainsFilter(str, DESC_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startsWith(prefix: String): ListFilter {
|
fun startsWith(prefix: String): Filter {
|
||||||
return StringStartsWithFilter(prefix, DESC_GETTER)
|
return StringStartsWithFilter(prefix, DESC_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun endsWith(suffix: String): ListFilter {
|
fun endsWith(suffix: String): Filter {
|
||||||
return StringEndsWithFilter(suffix, DESC_GETTER)
|
return StringEndsWithFilter(suffix, DESC_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun matches(regex: String): ListFilter {
|
fun matches(regex: String): Filter {
|
||||||
return StringMatchesFilter(regex, DESC_GETTER)
|
return StringMatchesFilter(regex, DESC_GETTER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
package com.stardust.automator.filter
|
|
||||||
|
|
||||||
import com.stardust.automator.UiObject
|
|
||||||
|
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/9.
|
|
||||||
*/
|
|
||||||
|
|
||||||
abstract class DfsFilter : ListFilter(), Filter {
|
|
||||||
|
|
||||||
override fun filter(nodes: List<UiObject>): List<UiObject> {
|
|
||||||
val list = ArrayList<UiObject>()
|
|
||||||
for (node in nodes) {
|
|
||||||
if (isIncluded(node)) {
|
|
||||||
list.add(node)
|
|
||||||
}
|
|
||||||
if (list.size >= maxCount) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
filterChildren(node, list)
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun filter(node: UiObject): List<UiObject> {
|
|
||||||
val list = ArrayList<UiObject>()
|
|
||||||
if (isIncluded(node)) {
|
|
||||||
list.add(node)
|
|
||||||
}
|
|
||||||
if (list.size >= maxCount) {
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
filterChildren(node, list)
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun filterChildren(parent: UiObject, list: MutableList<UiObject>) {
|
|
||||||
for (i in 0 until parent.childCount) {
|
|
||||||
val child = parent.child(i) ?: continue
|
|
||||||
val included = isIncluded(child)
|
|
||||||
if (included) {
|
|
||||||
list.add(child)
|
|
||||||
}
|
|
||||||
if (list.size >= maxCount) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
filterChildren(child, list)
|
|
||||||
if (!included) {
|
|
||||||
child.recycle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun isIncluded(nodeInfo: UiObject): Boolean
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,6 @@ import com.stardust.automator.UiObject
|
|||||||
|
|
||||||
interface Filter {
|
interface Filter {
|
||||||
|
|
||||||
fun filter(node: UiObject): List<UiObject>
|
fun filter(node: UiObject): Boolean
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ object IdFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FullIdGetter {
|
|
||||||
fun getFullId(id: String): String
|
|
||||||
}
|
|
||||||
|
|
||||||
fun equals(id: String): StringEqualsFilter {
|
fun equals(id: String): StringEqualsFilter {
|
||||||
return StringEqualsFilter(id, ID_GETTER)
|
return StringEqualsFilter(id, ID_GETTER)
|
||||||
}
|
}
|
||||||
@@ -31,7 +27,7 @@ object IdFilter {
|
|||||||
return StringStartsWithFilter(prefix, ID_GETTER)
|
return StringStartsWithFilter(prefix, ID_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun endsWith(suffix: String): ListFilter {
|
fun endsWith(suffix: String): StringEndsWithFilter {
|
||||||
return StringEndsWithFilter(suffix, ID_GETTER)
|
return StringEndsWithFilter(suffix, ID_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/11/5.
|
* Created by Stardust on 2017/11/5.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class IntFilter(private val mIntProperty: IntProperty, private val mValue: Int) : DfsFilter() {
|
class IntFilter(private val mIntProperty: IntProperty, private val mValue: Int) : Filter {
|
||||||
|
|
||||||
interface IntProperty {
|
interface IntProperty {
|
||||||
operator fun get(`object`: UiObject): Int
|
operator fun get(`object`: UiObject): Int
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
return mIntProperty[nodeInfo] == mValue
|
return mIntProperty[node] == mValue
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.stardust.automator.filter
|
|
||||||
|
|
||||||
import com.stardust.automator.UiObject
|
|
||||||
|
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/9.
|
|
||||||
*/
|
|
||||||
|
|
||||||
abstract class ListFilter {
|
|
||||||
|
|
||||||
var maxCount: Int = Integer.MAX_VALUE
|
|
||||||
|
|
||||||
abstract fun filter(nodes: List<UiObject>): List<UiObject>
|
|
||||||
|
|
||||||
abstract class Default : Filter, ListFilter() {
|
|
||||||
|
|
||||||
override fun filter(nodes: List<UiObject>): List<UiObject> {
|
|
||||||
val list = ArrayList<UiObject>()
|
|
||||||
for (node in nodes) {
|
|
||||||
list.addAll(filter(node))
|
|
||||||
if (list.size >= maxCount) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -19,23 +19,23 @@ object PackageNameFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun equals(text: String): ListFilter {
|
fun equals(text: String): Filter {
|
||||||
return StringEqualsFilter(text, PACKAGE_NAME_GETTER)
|
return StringEqualsFilter(text, PACKAGE_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contains(str: String): ListFilter {
|
fun contains(str: String): Filter {
|
||||||
return StringContainsFilter(str, PACKAGE_NAME_GETTER)
|
return StringContainsFilter(str, PACKAGE_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startsWith(prefix: String): ListFilter {
|
fun startsWith(prefix: String): Filter {
|
||||||
return StringStartsWithFilter(prefix, PACKAGE_NAME_GETTER)
|
return StringStartsWithFilter(prefix, PACKAGE_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun endsWith(suffix: String): ListFilter {
|
fun endsWith(suffix: String): Filter {
|
||||||
return StringEndsWithFilter(suffix, PACKAGE_NAME_GETTER)
|
return StringEndsWithFilter(suffix, PACKAGE_NAME_GETTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun matches(regex: String): ListFilter {
|
fun matches(regex: String): Filter {
|
||||||
return StringMatchesFilter(regex, PACKAGE_NAME_GETTER)
|
return StringMatchesFilter(regex, PACKAGE_NAME_GETTER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.stardust.automator.filter
|
||||||
|
|
||||||
|
import com.stardust.automator.UiObject
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class Selector : Filter {
|
||||||
|
private val mFilters = LinkedList<Filter>()
|
||||||
|
|
||||||
|
override fun filter(node: UiObject): Boolean {
|
||||||
|
for (filter in mFilters) {
|
||||||
|
if (!filter.filter(node)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(filter: Filter) {
|
||||||
|
mFilters.add(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val str = StringBuilder()
|
||||||
|
for (filter in mFilters) {
|
||||||
|
str.append(filter.toString()).append(".")
|
||||||
|
}
|
||||||
|
if (str.isNotEmpty()) {
|
||||||
|
str.deleteCharAt(str.length - 1)
|
||||||
|
}
|
||||||
|
return str.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,10 +6,10 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StringContainsFilter internal constructor(private val mContains: String, private val mKeyGetter: KeyGetter) : DfsFilter() {
|
class StringContainsFilter internal constructor(private val mContains: String, private val mKeyGetter: KeyGetter) : Filter {
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
val key = mKeyGetter.getKey(nodeInfo)
|
val key = mKeyGetter.getKey(node)
|
||||||
return key != null && key.contains(mContains)
|
return key != null && key.contains(mContains)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StringEndsWithFilter(private val mSuffix: String, private val mKeyGetter: KeyGetter) : DfsFilter() {
|
class StringEndsWithFilter(private val mSuffix: String, private val mKeyGetter: KeyGetter) : Filter {
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
val key = mKeyGetter.getKey(nodeInfo)
|
val key = mKeyGetter.getKey(node)
|
||||||
return key != null && key.endsWith(mSuffix)
|
return key != null && key.endsWith(mSuffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StringEqualsFilter(private val mValue: String, private val mKeyGetter: KeyGetter) : DfsFilter() {
|
class StringEqualsFilter(private val mValue: String, private val mKeyGetter: KeyGetter) : Filter {
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
val key = mKeyGetter.getKey(nodeInfo)
|
val key = mKeyGetter.getKey(node)
|
||||||
return if (key != null) {
|
return if (key != null) {
|
||||||
key == mValue
|
key == mValue
|
||||||
} else false
|
} else false
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StringMatchesFilter internal constructor(private val mRegex: String, private val mKeyGetter: KeyGetter) : DfsFilter() {
|
class StringMatchesFilter internal constructor(private val mRegex: String, private val mKeyGetter: KeyGetter) : Filter {
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
val key = mKeyGetter.getKey(nodeInfo)
|
val key = mKeyGetter.getKey(node)
|
||||||
return key != null && key.matches(mRegex.toRegex())
|
return key != null && key.matches(mRegex.toRegex())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import com.stardust.automator.UiObject
|
|||||||
* Created by Stardust on 2017/3/9.
|
* Created by Stardust on 2017/3/9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StringStartsWithFilter(private val mPrefix: String, private val mKeyGetter: KeyGetter) : DfsFilter() {
|
class StringStartsWithFilter(private val mPrefix: String, private val mKeyGetter: KeyGetter) : Filter {
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
val key = mKeyGetter.getKey(nodeInfo)
|
val key = mKeyGetter.getKey(node)
|
||||||
return key != null && key.startsWith(mPrefix)
|
return key != null && key.startsWith(mPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
package com.stardust.automator.filter
|
|
||||||
|
|
||||||
import com.stardust.automator.UiObject
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/3/9.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TextFilter private constructor(private val mText: String) : ListFilter.Default() {
|
|
||||||
|
|
||||||
override fun filter(node: UiObject): List<UiObject> {
|
|
||||||
return node.findByText(mText)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private val TEXT_GETTER = object : KeyGetter {
|
|
||||||
override fun getKey(nodeInfo: UiObject): String? {
|
|
||||||
val charSequence = nodeInfo.text
|
|
||||||
return charSequence?.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "text"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun equals(text: String): ListFilter {
|
|
||||||
return StringEqualsFilter(text, TEXT_GETTER)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun contains(str: String): ListFilter {
|
|
||||||
return StringContainsFilter(str, TEXT_GETTER)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startsWith(prefix: String): ListFilter {
|
|
||||||
return StringStartsWithFilter(prefix, TEXT_GETTER)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun endsWith(suffix: String): ListFilter {
|
|
||||||
return StringEndsWithFilter(suffix, TEXT_GETTER)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun matches(regex: String): ListFilter {
|
|
||||||
return StringMatchesFilter(regex, TEXT_GETTER)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.stardust.automator.filter
|
||||||
|
|
||||||
|
import com.stardust.automator.UiObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/3/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
object TextFilters {
|
||||||
|
|
||||||
|
private val TEXT_GETTER = object : KeyGetter {
|
||||||
|
override fun getKey(nodeInfo: UiObject): String? {
|
||||||
|
val charSequence = nodeInfo.text
|
||||||
|
return charSequence?.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "text"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun equals(text: String): Filter {
|
||||||
|
return StringEqualsFilter(text, TEXT_GETTER)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun contains(str: String): Filter {
|
||||||
|
return StringContainsFilter(str, TEXT_GETTER)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startsWith(prefix: String): Filter {
|
||||||
|
return StringStartsWithFilter(prefix, TEXT_GETTER)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endsWith(suffix: String): Filter {
|
||||||
|
return StringEndsWithFilter(suffix, TEXT_GETTER)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun matches(regex: String): Filter {
|
||||||
|
return StringMatchesFilter(regex, TEXT_GETTER)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,11 +13,11 @@ import org.junit.Assert.*
|
|||||||
*/
|
*/
|
||||||
class DfsFilterTest {
|
class DfsFilterTest {
|
||||||
|
|
||||||
private class RandomDfsFilter : DfsFilter() {
|
private class RandomFilter : Filter {
|
||||||
|
|
||||||
private val mRandom = Random()
|
private val mRandom = Random()
|
||||||
|
|
||||||
override fun isIncluded(nodeInfo: UiObject): Boolean {
|
override fun filter(node: UiObject): Boolean {
|
||||||
return mRandom.nextBoolean()
|
return mRandom.nextBoolean()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,9 +25,9 @@ class DfsFilterTest {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun filter() {
|
fun filter() {
|
||||||
val filter = RandomDfsFilter()
|
val filter = RandomFilter()
|
||||||
val root = TestUiObject(10)
|
val root = TestUiObject(10)
|
||||||
val list = filter.filter(root)
|
val list = DFS(filter).search(root)
|
||||||
for (uiObject in list) {
|
for (uiObject in list) {
|
||||||
if (root !== uiObject)
|
if (root !== uiObject)
|
||||||
uiObject.recycle()
|
uiObject.recycle()
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":450,"versionName":"4.0.5 Alpha","enabled":true,"outputFile":"commonRelease-4.0.5 Alpha.apk","fullName":"commonRelease","baseName":"common-release"},"path":"commonRelease-4.0.5 Alpha.apk","properties":{}}]
|
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":451,"versionName":"4.1.0 Alpha","enabled":true,"outputFile":"commonRelease-4.1.0 Alpha.apk","fullName":"commonRelease","baseName":"common-release"},"path":"commonRelease-4.1.0 Alpha.apk","properties":{}}]
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"appVersionCode": 450,
|
"appVersionCode": 451,
|
||||||
"appVersionName": "4.0.5 Alpha",
|
"appVersionName": "4.1.0 Alpha",
|
||||||
"target": 28,
|
"target": 28,
|
||||||
"mini": 17,
|
"mini": 17,
|
||||||
"compile": 28,
|
"compile": 28,
|
||||||
"buildTool": "28.0.3"
|
"buildTool": "28.0.3"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user