setSpan 报错 IndexOutOfBounds
程序员文章站
2022-03-24 22:04:58
近期在项目开发中发现如下报错之前一直以为是SpanString的问题 一直用try - catch来处理。 @Override public void setSpan(Object what, int start, int end, int flags) { if (start == -1 || end == -1 || end > mCharSequence.length()) { return; } try...
近期在项目开发中发现如下报错
之前一直以为是SpanString的问题 一直用try - catch来处理。
@Override
public void setSpan(Object what, int start, int end, int flags) {
if (start == -1 || end == -1 || end > mCharSequence.length()) {
return;
}
try {
super.setSpan(what, start, end, flags);
} catch (Exception e) {
e.printStackTrace();
}
}
但在实际项目中并不凑效,bugly后台一直在报错,跟进Accessiblity源码,其中有setSpan的调用,查询相关资料发现是clickSpan和无障碍的TalkBack不能同时使用,这两者有冲突,用了clickSpan会让TalkBack读取文字的时候读不到下标 进而导致IndexOutOfBounds的报错。
解决方法是判断是否开启屏幕阅读器 TalkBack。
public final static String SCREEN_READER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService";
public final static String SCREEN_READER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN";
public static boolean isScreenReaderActive(Context context) {
// 通过Intent方式判断是否存在以语音播报方式提供服务的Service,还需要判断开启状态
Intent screenReaderIntent = new Intent(SCREEN_READER_INTENT_ACTION);
screenReaderIntent.addCategory(SCREEN_READER_INTENT_CATEGORY);
List<ResolveInfo> screenReaders = context.getPackageManager().queryIntentServices(screenReaderIntent, 0);
// 如果没有,返回false
if (screenReaders == null || screenReaders.size() <= 0) {
return false;
}
boolean hasActiveScreenReader = false;
if (Build.VERSION.SDK_INT <= 15) {
ContentResolver cr = context.getContentResolver();
Cursor cursor = null;
int status = 0;
for (ResolveInfo screenReader : screenReaders) {
cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName
+ ".providers.StatusProvider"), null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
status = cursor.getInt(0);
cursor.close();
// 状态1为开启状态,直接返回true即可
if (status == 1) {
return true;
}
}
}
} else if (Build.VERSION.SDK_INT >= 26) {
// 高版本可以直接判断服务是否处于开启状态
for (ResolveInfo screenReader : screenReaders) {
hasActiveScreenReader |= isAccessibilitySettingsOn(context, screenReader.serviceInfo.packageName + "/" + screenReader.serviceInfo.name);
}
} else {
// 判断正在运行的Service里有没有上述存在的Service
List<String> runningServices = new ArrayList<String>();
android.app.ActivityManager manager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (android.app.ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
runningServices.add(service.service.getPackageName());
}
for (ResolveInfo screenReader : screenReaders) {
if (runningServices.contains(screenReader.serviceInfo.packageName)) {
hasActiveScreenReader = true;
break;
}
}
}
return hasActiveScreenReader;
}
public static boolean isAccessibilitySettingsOn(Context context, String service) {
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
String settingValue = Settings.Secure.getString(
context.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next();
if (accessibilityService.equalsIgnoreCase(service)) {
return true;
}
}
}
return false;
}
每次使用clickSpan之前 判断isScreenReaderActive(),如果开启了TB,就不设置clickSpan。不会影响正常使用,但是对开启了TB的用户有一点影响。 目前还没有更好的解决方法。
本文地址:https://blog.csdn.net/Dullyoung/article/details/108978215
上一篇: SmartRefreshLayout自定义下拉刷新动画
下一篇: 笔记本端口测试经验谈
推荐阅读
-
QQ音乐打不开一运行就报错的解决办法
-
解决Maven 项目报错 java.httpservlet和synchronized使用方法
-
C#中SQL参数传入空值报错解决方案
-
Android开发解决popupWindow重叠报错问题
-
安装cad提示1606错误怎么办 autocad报错1606的解决方法
-
vue 中使用 watch 出现了如下的报错的原因分析
-
MySQL5.7 group by新特性报错1055的解决办法
-
C#中Convert.ToDecimal()报错问题的解决
-
Android模拟器无法启动,报错:Cannot set up guest memory ‘android_arm’ Invalid argument的解决方法
-
myeclipse和eclipse查看server面板报错该怎么办?