Code Monkey home page Code Monkey logo

android-auto-api's Introduction

Android-Accessibility-Api

中文 | English

安卓无障碍服务Api, 为了简化无障碍服务使用,并使用 Kotlin 以提供简洁的Api。


由于4.0版本代码进行重构,之前接入的项目需要修改 import package, 并且 implementation 'com.github.Krosxx.Android-Accessibility-Api:accessibility-api:4.0.0'。UiAutomator 可参考 Demo App
最新 library : implementation 'com.github.Krosxx:Android-Auto-Api:Tag'

基础导航

(图片加载过慢可到 Gitee 查看)

查看代码
//无障碍服务声明 未开启会跳转设置页面提示开启服务,并抛出异常 终止执行
requireBaseAccessibility()
toast("下拉通知栏..")
delay(1000)
toast("快捷设置..")
//操作之间需要适当延时等待
delay(1000)
//下拉通知栏快捷设置
quickSettings()
delay(1000)
//返回操作
back()
delay(500)
//返回操作
back()
delay(1000)
//电源菜单
powerDialog()
delay(500)
back()
delay(1000)
//进入最近任务页面
recents()
delay(1000)
back()
delay(1000)
//Home 按键 / 返回桌面
home()
delay(100)

更多操作:

方法 说明
lockScreen() 锁屏,需要Android P
screenShot() 触发系统截屏,需要Android P
splitScreen() 触发系统分屏,需要Android P

视图检索

提取文字

requireBaseAccessibility()
//使用 ScreenTextFinder() 来搜索屏幕上的文字
val ts = ScreenTextFinder().find().joinToString("\n\n")

withContext(Dispatchers.Main) {
    AlertDialog.Builder(act).apply {
        setTitle("提取文字:")
        setMessage(ts)
        show()
    }
}

视图搜索

  1. 提供一个基础类 ViewFinder, 并封装一个 ViewFinderWithMultiCondition 来指定搜索条件,实现快速搜索;查看所有方法:view_finder_api.kt
  2. 最新添加 SmartFinder,支持多条件(AND, OR)搜索,扩展性极高

ViewFinder 主要方法:

注意:在3.0.0及之后版本,搜索方法需在协程作用域内使用,若需要java内调用请使用2.1.1版本

方法 说明
findFirst(includeInvisible: Boolean = false): ViewNode? 立即搜索,返回满足条件的第一个结果
includeInvisible: 是否包含不可见元素
findAll(includeInvisible: Boolean = false): Array<ViewNode> 立即搜索,返回满足条件的所有结果
waitFor(waitMillis: Long = 30000): ViewNode? 等待搜索,在指定时间内循环搜索(视图更新),超时返回null
require(waitMillis: Long = WAIT_MILLIS): ViewNode 等待超时抛出异常
findByDepths(vararg depths: Int): ViewNode? 指定深度索引搜索
exist(): Boolean 是否存在 (findFirst() != null)
attachCoroutine() 支持协程调用,支持cancel()打断搜索

示例1: 等待 Chrome 打开 > 展开菜单

//等待无障碍开启 默认时间30s,超时将抛出异常
waitBaseAccessibility()
toast("start chrome after 1s")
delay(1000)
//打开Chrome
val targetApp = "com.android.chrome"
act.startActivity(act.packageManager.getLaunchIntentForPackage(targetApp))
//等待页面
if (
    waitForApp(targetApp, 5000).also {
        toast("wait " + if (it) "success" else "failed")
    }
) {
    //id 搜索,点击打开菜单
    withId("menu_button").tryClick()
}

示例2: 文本操作

查看代码
requireBaseAccessibility()
//editor() 指定编辑框
editor().require().apply { // this is ViewNode
    repeat(5) {
        //追加文本
        appendText(".x")
        delay(500)
    }
    delay(1000)
    //清空文本
    text = ""
    delay(1000)
    //设置文本
    text = "123456"
    delay(1000)
    //选择文本
    setSelection(0, 5)
    delay(1000)
	//清除选择
    clearSelection()
    //失去焦点
    clearFocus()
}
  1. 提供自定义搜索条件

搜索所有可点击的视图:

requireBaseAccessibility()
//自定义条件搜索
val s = findAllWith { it: AccessibilityNodeInfo -> 
    it.isClickable
}.joinToString("\n\n")

withContext(Dispatchers.Main) {
    AlertDialog.Builder(act).apply {
        setTitle("可点击节点:")
        setMessage(s)
        show()
    }
}
  1. SmartFinder

扩展性极高,支持多条件(AND, OR)搜索

更多已支持的条件见:SmartFinderConditions.kt

//SF 为 SmartFinder 缩写
SF.text("SmartFinder测试").findFirst()
//等效:
SF.where(_text eq "SmartFinder测试").findFirst()

//搜索 文本为123 或者 id为text1
SF.text("123").or().id("text1").findFirst()

原始AND,OR

//搜索 所有isChecked
SF.where { 
    it.isChecked
}.find()

SF.where(IdCondition("view_id")).or(RTextEqCondition("[0-9]+")).find()
//等效:
SF.id("view_id").or().matchText("[0-9]+").find()

支持Group

// (text=="111" && desc=="111") || (text=="222" && desc=="222")
SF.where(SF.text("111").desc("111"))
            .or(SF.text("222").desc("222"))
            .find()

中缀表达式

//使用中缀表达式
(SF where text("1111") or text("2222")
        and id("111") or longClickable()).findAll()
  1. 协程支持

添加 attachCoroutine 方法,搜索等待可及时中断

fun run(act: Activity) = runBlocking {
    val outterJob = coroutineContext[Job]
    val searchJob = GlobalScope.async {
        val t = SF.attachCoroutine()//attach当前协程上下文,需要主动调用
          .containsText("周三").waitFor(10000)
        AlertDialog.Builder(act).apply {
            setMessage(t.toString())
            withContext(Dispatchers.Main) {
                show()
            }
        }
    }
    searchJob.invokeOnCompletion {
        outterJob?.cancel()
    }
    delay(3000)
    //取消搜索测试
    searchJob.cancel()
}
  1. 条件扩展

封装自定义搜索条件,使调用起来更简洁 库中搜索条件全部实现位于 SmartFinderConditions.kt

例如 定义使用正则匹配Node文本

Step 1.
class TextMatcherCondition(private val regex: String) : MatchCondition {
	//此处注意直接创建Regex,防止在搜索时重复创建;另外可直接检查正则表达式有效性
    private val reg = regex.toRegex()
    override fun invoke(node: AcsNode) =
        node.text?.toString()?.let {
            reg.matches(it)
        } ?: false
}

此时,已经可以这样使用:

SF.where(TextMatcherCondition("[0-9]+")).findAll()

追究简洁,可进行扩展方法:

Step 2.
fun ConditionGroup.matchText(reg: String) = link(TextMatcherCondition(reg))

之后可简化调用

SF.matchText("[0-9]+").findAll()

视图节点(ViewNode)

根据ViewFinder搜索得到 ViewNode,可进行的操作详见接口:ViewOperation.kt

全局手势

全局手势可以点击/长按任意坐标,执行路径手势。

示例

查看代码
class DrawableAction : Action {
    override val name: String
        get() = "手势画图 - Rect - Circle - Oval"

    @RequiresApi(Build.VERSION_CODES.N)
    override suspend fun run(act: Activity) {
        requireBaseAccessibility()
        requireGestureAccessibility()
        act.startActivity(Intent(act, DrawableActivity::class.java))
        toast("1s后开始绘制,请不要触摸屏幕")
        delay(1000)

        //设置相对屏幕 非必须
        setScreenSize(500, 500)
        //指定点转路径手势
        gesture(
            2000L, arrayOf(
                100 t 100,
                100 t 200,
                200 t 200,
                200 t 100,
                100 t 100
            )
        )
        delay(800)
        //点击clear按钮
        withText("clear").tryClick()
        //使用Path
        drawCircle()
        delay(800)
        withText("clear").tryClick()
        drawOval()
    }

    @RequiresApi(Build.VERSION_CODES.N)
    fun drawCircle() {
        val p = Path().apply {
            //此处路径坐标为绝对坐标
            addOval(RectF(500f, 500f, 800f, 800f), Path.Direction.CW)
        }
        gesture(2000L, p) {
            toast("打断")
        }
    }

    //AdapterRectF 会根据设置的相对屏幕大小换算
    @RequiresApi(Build.VERSION_CODES.N)
    fun drawOval() {
        val p = Path().apply {
            //使用AdapterRectF 会根据设置的相对屏幕尺寸将坐标转换
            addOval(AdapterRectF(200f, 200f, 300f, 300f), Path.Direction.CW)
        }
        gesture(2000L, p)
    }

    infix fun <A, B> A.t(that: B): Pair<A, B> = Pair(this, that)
}

Api文档

手势Api全部需要Android N+;代码必须执行于非主线程

展开查看
方法 说明
fun setScreenSize(width: Int, height: Int) 设置屏幕相对坐标
fun gesture(
duration: Long,
points: Array<Pair<Int, Int>>,
onCancel: Function0? = null
): Boolean
根据点坐标生成路径 执行手势
fun gesture(
duration: Long,
path: Path,
onCancel: Function0? = null
): Boolean
根据Path执行手势
fun gestureAsync(
duration: Long,
points: Array<Pair<Int, Int>>
)
异步执行手势
fun gestures(
duration: Long,
ppss: Array<Array<Pair<Int, Int>>>,
onCancel: Function0? = null
): Boolean
多路径手势
fun click(x: Int, y: Int) 点击; x,y 相对坐标
fun longClick(x: Int, y: Int) 长按; x,y 相对坐标
fun swipe(x1: Int, y1: Int, x2: Int, y2: Int, dur: Int) 两点间滑动
fun scrollUp(): Boolean 向上滑动
fun scrollDown(): Boolean 向下滑动

使用

由于部分系统版本启动支持手势的无障碍服务会造成系统卡顿(掉帧),所以本库分为两个服务来设计(若无需手势功能,可不实现手势服务)。

引入 Android-Accessibility-Api

  1. Add it in your root build.gradle at the end of repositories:
allprojects {
	repositories {
		//...
		maven { url 'https://jitpack.io' }
	}
}
  1. Add the dependency
dependencies {
	implementation 'com.github.Krosxx:Android-Auto-Api:Tag'
}

the TAG is

注意:在3.0.0及之后版本,搜索方法需在协程作用域内使用,若需要java内调用请使用2.1.1版本

创建你的服务

基础服务

用来支持 布局检索,视图操作

  1. 定义你的 BaseAccessibilityService
展开查看 BaseAccessibilityService
class BaseAccessibilityService : AccessibilityApi() {

    //启用 页面更新 回调
    override val enableListenAppScope: Boolean = true
    
    //页面更新回调
    override fun onPageUpdate(currentScope: AppScope) {
        Log.d("TAG", "onPageUpdate: $currentScope")
    }
}
  1. 服务注册
<service
    android:name=".service.BaseAccessibilityService"
    android:description="@string/base_ser_desc"
    android:label="BaseService Demo"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/base_accessibility_config" />
</service>
  1. base_accessibility_config.xml
点击展开 res/xml/base_accessibility_config.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility"
    android:canRetrieveWindowContent="true"
    android:description="@string/base_ser_desc"
    android:notificationTimeout="10"
    android:canRequestEnhancedWebAccessibility="true"
    android:settingsActivity=".MainActivity"
    android:summary="基础导航/视图检索操作"/>
<!--    android:canRequestFilterKeyEvents="true"-->
<!--flagRequestFilterKeyEvents-->

其中 android:accessibilityEventTypes="typeWindowStateChanged" 可能会在视图搜索有延迟刷新视图树的问题, 可使用 android:accessibilityEventTypes="typeAllMask" 替换

手势服务

用于执行手势,Android N+可用

  1. 定义 GestureAccessibilityService
展开查看 GestureAccessibilityService
class GestureAccessibilityService : AccessibilityService() {
    override fun onCreate() {
        super.onCreate()
        //must call
        AccessibilityApi.gestureService = this
    }
    override fun onDestroy() {
        super.onDestroy()
        //must call
        AccessibilityApi.gestureService = null
    }
    override fun onInterrupt() {}
    override fun onAccessibilityEvent(event: AccessibilityEvent?) {}
}
  1. 服务注册
<service
    android:name=".service.GestureAccessibilityService"
    android:description="@string/ges_ser_desc"
    android:label="Gesture Service Demo"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/gesture_accessibility_config" />
</service>
  1. gesture_accessibility_config.xml
点击展开 res/xml/gesture_accessibility_config.xml

和基础服务配置区别仅为 android:canPerformGestures="true"

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes=""
    android:accessibilityFeedbackType=""
    android:accessibilityFlags=""
    android:canPerformGestures="true"
    android:canRetrieveWindowContent="false"
    android:description="@string/ges_ser_desc"
    android:notificationTimeout="10"
    android:packageNames=""
    android:settingsActivity=".MainActivity"
    android:summary="执行手势" />

额外配置

在 Application 中初始化:

指定 BASE_SERVICE_CLSGESTURE_SERVICE_CLS

override fun onCreate() {
    super.onCreate()
    AccessibilityApi.init(this,
        BaseAccessibilityService::class.java,
        GestureAccessibilityService::class.java)
}

合并服务

如果你想使用一个服务来完成,可使用如下配置

  1. 创建服务
class AppAccessibilityService : AccessibilityApi() {
    //启用 页面更新 回调
    override val enableListenAppScope: Boolean = true

    //页面更新回调
    override fun onPageUpdate(currentScope: AppScope) {
        Log.d("TAG", "onPageUpdate: $currentScope")
    }
}
  1. 清单注册
<service
    android:name=".service.AppAccessibilityService"
    android:description="@string/ser_desc"
    android:label="Service Demo"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_config" />
</service>
  1. res/xml/accessibility_config.xml
点击展开 accessibility_config.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:accessibilityFlags="flagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestEnhancedWebAccessibility"
    android:canRetrieveWindowContent="true"
    android:description="@string/base_ser_desc"
    android:notificationTimeout="10"
    android:canPerformGestures="true"
    android:canRequestEnhancedWebAccessibility="true"
    android:settingsActivity=".MainActivity"
    android:summary="基础导航/视图检索操作"/>
<!--    android:canRequestFilterKeyEvents="true"-->
<!--flagRequestFilterKeyEvents-->
  1. Application 初始化配置

在 Application 中初始化:

override fun onCreate() {
    super.onCreate()
    AccessibilityApi.init(this, AppAccessibilityService::class.java)
}

更多 Api 可在下列文件查看

android-auto-api's People

Contributors

krosxx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-auto-api's Issues

测试demo报错了

报错信息:

com.android.tools.r8.internal.sd: Method name '' in class 'cn.vove7.andro_accessibility_api.api.View_finder_apiKt$sam$cn_vove7_auto_core_viewfinder_MatchCondition$0' cannot be represented in dex format.

demo是从项目的app中复制出来,原封不动
以下是build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'org.jetbrains.kotlin.android'

android {
signingConfigs {
debug {
storeFile file('KEY')
storePassword '1234567890'
keyAlias 'key'
keyPassword '1234567890'
}
}
compileSdk 33

defaultConfig {
    applicationId "cn.vove7.andro_accessibility_api.demo"
    minSdkVersion 21
    targetSdkVersion 33
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
    debug {
        signingConfig signingConfigs.debug
    }
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.debug
    }
}
buildFeatures {
    viewBinding true
}

}

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.jakewharton.timber:timber:5.0.1'

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'

implementation 'me.panavtec:drawableview:0.6.0'

testImplementation 'junit:junit:4.13.2'
implementation 'com.github.Krosxx:Android-Auto-Api:4.0.0'

}

获取的节点不全

image
biao标题栏的节点无法点击 获取当前界面的text标题栏的也获取不到只能获取标题栏以下的
image

请教下MyInstrumentation里的代码如何使用

对自动化测试接触的不多,看到Instrumentation相关的代码好像都没用到,使用 adb shell am instrument -w cn.vove7.andro_accessibility_api.demo.MyInstrumentation 。报错 No instrumentation found,有人知道怎么用吗

关于手势控制的问题

想问博主一个问题,就是我们现在想模拟用户在微信语音聊天中取消发送的操作,但是经过尝试发现这个功能好像实现不了。因为当我们用dispatchGesture模拟长按的操作时,如果这时加了一个上滑的操作那么之前的操作就会在GestureResultCallback被监听到取消了,然后微信那边就直接发送出去了。请问这个有解吗?

相同节点获取问题

/**
 * 深搜遍历
 *
 * @param node AccessibilityNodeInfo?
 * @param all Boolean true 搜索全部返回list else return first
 * @param includeInvisible Boolean 是否包含不可见元素
 * @return ViewNode?
 */
private suspend fun traverseAllNode(
    node: ViewNode?, list: MutableList<ViewNode>? = null,
    includeInvisible: Boolean = false, depth: Int = 0,
    nodeSet: MutableSet<AcsNode> = mutableSetOf()
): ViewNode? {
    ensureActive()
    node ?: return null
    if (node.node in nodeSet) return null
    nodeSet.add(node.node)
    node.children.forEach { childNode ->
        ensureActive()
        if (childNode == null) {
            return@forEach
        }
        if (!includeInvisible && !childNode.isVisibleToUser) {
            return@forEach
        }
        if (findCondition(childNode.node)) {
            if (list != null) {
                list.add(childNode)
            } else return childNode
        }
        val r = traverseAllNode(childNode, list, includeInvisible, depth + 1)
        if (list == null && r != null) {
            return r
        }
    }
    return null
}如果连续两次使用相同的 ID 调用 traverseAllNode() 方法,由于 nodeSet 会记录已访问的节点,因此会检查节点是否已经存在于 nodeSet 中。如果已经存在,则直接返回上次找到的节点信息,并且不会重新获取这样如果我有俩不同的界面存在一样的id他会返回第一次获取的信息

截屏咨询

截屏函数看来只是向系统发起截屏的请求,按函数理解,应该截屏后把图截了以后保存到截屏目录,这样存在不能建立调用截屏和保存的文件名称的关系,而且访问也比较麻烦,我网上看好像无障碍是提供截屏的api,但是资料不是很多,不知道作者是否可以配套,要是能截屏后返回BitMap就好了。

发现了一个问题

 //适应 多窗口 分屏
    val rootNodeOfAllWindows
        get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ViewNode.withChildren(
                windows?.mapNotNull {
                    it.root?.let { r -> ViewNode(r) }
                } ?: emptyList()
            )
        } else {
            rootViewNode ?: ViewNode.withChildren(emptyList())
        }

Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP 以上的系统手机,

界面变化后,findFirst还是获取到上一帧的界面数据。

只有分屏的时候,界面才进行刷新。 (通过划出任务栏,无障碍才能获取到当前界面的数据)

同样的代码,在Android10(华为) 上面获取到的是上一帧的数据,在Android7(小米)上是正常的。

2.0

大佬,请问2.0看起来是简化了很多,遇到有几个问题请教 如何查询全部 SF.where{}.find() . where条件是必须的吗。还有如何从某个指定的节点开始查询他的所有。 之前的版本是可以现在改2.0不知道怎么写了一直抛出这个 has no conditions 求赐教

gesture()、click()无返回

首先感谢作者造的轮子,减轻了很多的工作量。而且稍微翻了下源码,代码逻辑看着很舒服。

今天刚找到该库,引用后尝试使用click()和gesture()做坐标点击操作,但坐标点击后会卡在方法体内,无返回值,导致不能进行下一次操作。而使用gestureAsync()可以正常执行。
翻了下demo,似乎也是直接执行gesture(),没有做其它操作。

环境:Huawei Mate10 Pro(Android10)
感谢。

exist()一直返回false

image image 这个自己创建搜索条件返回的好想没法用这个来判断是否存在节点一直是false

自定义查找有的节点查找不到

image ![image](https://github.com/Krosxx/Android-Auto-Api/assets/108533707/20bb4355-3a47-40dd-9d22-6feee3adf30a) 为啥向下面的免费去水印和清空内容等文本都搜找不到 只能搜到去水印最上面那个文字

如何监听界面变化啊?

只看到一个切换不同页面会走onPageUpdate回调。
能不能监听页面元素变化?比如新来了一条消息有个小红点出来

有没有一直搜索的API?

waitFor是搜索一定的时间,有没有一直搜索的API,我想实现一个 当某一个按钮 出现后就点击的功能。

问题

2个问题,经常会遇到弹个框程序无响应,查找我是运行在IO线程里的。还有一个就是 查找的时候会抛出这个RuntimeException("无障碍服务未运行: $name") ,这个不知道是什么引起的

华为出现这种问题 "old interaction Id is: -1"

华为荣耀x8
操作节点会不断地出现以下日志
W/AccessibilityInteractionClient: old interaction Id is: -1,current interaction Id is:0
W/AccessibilityInteractionClient: old interaction Id is: -1,current interaction Id is:1
W/AccessibilityInteractionClient: old interaction Id is: -1,current interaction Id is:2
W/AccessibilityInteractionClient: old interaction Id is: -1,current interaction Id is:3
W/AccessibilityInteractionClient: old interaction Id is: -1,current interaction Id is:4
W/AccessibilityInteractionClient: old interaction Id is: -1,current interaction Id is:5
W/AccessibilityInteractionClient: old interaction Id is: -1,current interaction Id is:6

选择文本setSelection()方法异常

setSelection 函数执行的时候,系统报错:

E/TextClassifierImpl: Error getting assist info. java.io.FileNotFoundException: No file for null locale at android.view.textclassifier.TextClassifierImpl.getSmartSelection(TextClassifierImpl.java:192) at android.view.textclassifier.TextClassifierImpl.classifyText(TextClassifierImpl.java:146) at android.widget.SelectionActionModeHelper$TextClassificationHelper.classifyText(SelectionActionModeHelper.java:463) at android.widget.SelectionActionModeHelper.-android_widget_SelectionActionModeHelper-mthref-1(SelectionActionModeHelper.java:83) at android.widget.-$Lambda$tTszxdFZ0V9nXhnBpPsqeBMO0fw$5.$m$0(Unknown Source:4) at android.widget.-$Lambda$tTszxdFZ0V9nXhnBpPsqeBMO0fw$5.get(Unknown Source:0) at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.doInBackground(SelectionActionModeHelper.java:369) at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.doInBackground(SelectionActionModeHelper.java:364) at android.os.AsyncTask$2.call(AsyncTask.java:333) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at java.lang.Thread.run(Thread.java:764)

自带的demo,也是报错,烦请检查下呢。

想问下有Java版本的么

想问下有Java版本的么 因为项目是老项目 都是Java代码,引入新东西的话,担心存在兼容性问题,想问下有Java版本的代码没 或者直接把这份kotlin 代码转成Java代码 会 不会有什么问题

引入后,根本没法使用

按照文档引入后,根本没法使用,代码跟他的示例不对应,头大。 哎,改了好多文档不对应了

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.