我是靠谱客的博主 感动大象,最近开发中收集的这篇文章主要介绍setSpan 报错 IndexOutOfBounds,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

近期在项目开发中发现如下报错
在这里插入图片描述
之前一直以为是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的用户有一点影响。 目前还没有更好的解决方法。

最后

以上就是感动大象为你收集整理的setSpan 报错 IndexOutOfBounds的全部内容,希望文章能够帮你解决setSpan 报错 IndexOutOfBounds所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(30)

评论列表共有 0 条评论

立即
投稿
返回
顶部