Play商店预发布报告中的Android应用程序崩溃但在真实设备中工作

标签 android android-edittext indexoutofboundsexception

无法跟踪项目中的崩溃,我在 Play 商店预发布部分收到此错误,它在单击 EditText 时显示,它得到了错误。但在真实设备上没有任何崩溃。

问题:java.lang.IndexOutOfBoundsException: setSpan (4 ... 4) 结束于长度 0

Fatal Exception: java.lang.IndexOutOfBoundsException: setSpan (4 ... 4) ends beyond length 0
       at android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.java:1096)
       at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:671)
       at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:664)
       at android.text.Selection.setSelection(Selection.java:76)
       at android.text.Selection.setSelection(Selection.java:87)
       at android.widget.EditText.setSelection(EditText.java:98)
       at android.widget.EditText.performAccessibilityActionInternal(EditText.java:138)
       at android.view.View.performAccessibilityAction(View.java:8892)
       at android.view.AccessibilityInteractionController.performAccessibilityActionUiThread(AccessibilityInteractionController.java:668)
       at android.view.AccessibilityInteractionController.-wrap6(AccessibilityInteractionController.java)
       at android.view.AccessibilityInteractionController$PrivateHandler.handleMessage(AccessibilityInteractionController.java:1194)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:5459)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

最佳答案

在发布前报告和 FireBase 测试实验室中,我都看到了他同样的错误。我花了几个小时研究这个问题,我确信这是一个只影响 SDK <= 23 并且由 AccessibilityNodeInfo#performAction(ACTION_SET_TEXT) 触发的错误。
似乎此方法完全忽略了 maxLength 属性,这又导致了 IndexOutOfBoundsException。

您可以使用以下代码复制相同的异常,确保字符串“1234”比您的 maxLength 长:

 Bundle arguments = new Bundle();
 arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, "1234");
 mEditText.performAccessibilityAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);

那么,该怎么办呢?

一种选择是忽略它,因为它可能会影响一小部分用户。除非您认为您可能有许多用户使用辅助功能来输入文本,并且他们也使用较旧的 SDK (<= 23)。

另一种选择是将 build.gradle 中的 minSDKVersion 设置为 24。如果您有很多用户使用 SDK <= 23,这可能会造成伤害

第三种选择是使用我想出的这个非常丑陋的解决方法:
if(Build.VERSION.SDK_INT <= 23){
        ViewGroup rootView = findViewById(R.id.your_layout_that_contains_edittexts);
        ArrayList<View> views = rootView.getTouchables();
        for(View view : views){
            if(view instanceof EditText){
                EditText mEditText = (EditText)view;
                mEditText.setAccessibilityDelegate(new View.AccessibilityDelegate() {
                    @Override
                    public boolean performAccessibilityAction(View host, int action, Bundle arguments) {

                        if (action == AccessibilityNodeInfo.ACTION_SET_TEXT) {
                            //do something here to make sure index out of bounds does not occur
                            int maxLength = 0;
                            for(InputFilter filter : mEditText.getFilters()){
                                if(filter instanceof InputFilter.LengthFilter)  {
                                    maxLength = ((InputFilter.LengthFilter)filter).getMax();
                                }
                            }

                            Set<String> keys  = arguments.keySet();
                            for(String key : keys){
                                if(arguments.get(key) instanceof  CharSequence){
                                    if(arguments.get(key) != null) {
                                        arguments.putCharSequence(key, ((CharSequence) arguments.get(key)).subSequence(0, maxLength));
                                        mEditText.setText(arguments.getCharSequence(key));
                                    }
                                }
                            }
                        }
                        return true;
                    }
                });

            }
        }

    }

好的,所以我确实说它很丑,但它确实有效。将 your_layout_that_contains_edittexts 替换为包含所有 EditText 的布局的 id。

基本上,如果 SDK <= 23,它会循环遍历 ViewGroup 中的所有 EditText,并且对于每一个,通过 AccessibilityDelegate 覆盖 performAccessibilityAction 并确保输入的文本永远不会超过 EditText 的 maxLength 值。

关于Play商店预发布报告中的Android应用程序崩溃但在真实设备中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54779200/

相关文章:

android - Android 上的 USB 音频类设备

java - 如何像这样频繁地发送短信(每天、每周、每 5 分钟、每小时)

java - ArrayIndexOutOfBoundsException : 2 >= 1 on for each

java - 如何修复 Jama 中的 ArrayIndexOutOfBounds 错误?

Android 将数据从 ListView 传递到弹出窗口

具有透明背景的Android小部件: added image should not be transparent

android - 如何使用 DialogFragment 在 EditText 中显示选定日期

android - 如何针对大量文本(代码)优化自定义 EditText?

java - 如何加速 Android 多行 Edittext 中的平滑滚动?

java - java 获取 ArrayIndexOutOfBoundsException