无法跟踪项目中的崩溃,我在Play商店预启动部分中收到此错误,点击public static void main(String[] args) {
final int SIZE = 95; // total # of ascii vals being used
int[] availableChars = new int[SIZE];
int[] ePhrase = new int[SIZE];
int[] dePhrase = new int[SIZE];
for(int i = 0; i < SIZE; i++){
availableChars[i] = (i + 32);
}
for(int i = 0; i < SIZE; i++){
ePhrase[i] = encrypt(availableChars[i] - 32);
}
for(int i = 0; i < SIZE; i++){
dePhrase[i] = decrypt(ePhrase[i] - 32);
}
System.out.print("\n");
for(int i = 0; i < SIZE; i++){
System.out.print(i + " ");
}
System.out.print("\n");
for(int i = 0; i < SIZE; i++){
System.out.print((char)availableChars[i] + " ");
if(i >= 10){
System.out.print(" ");
}
}
System.out.print("\n");
for(int i = 0; i < SIZE; i++){
System.out.print((char)ePhrase[i] + " ");
if(i >= 10){
System.out.print(" ");
}
}
System.out.print("\n");
for(int i = 0; i < SIZE; i++){
System.out.print((char)dePhrase[i] + " ");
if(i >= 10){
System.out.print(" ");
}
}
}
public static int encrypt(int val){
return ((val + 9) % 94) + 32;
}
public static int decrypt(int val){
return ((val - 9) % 94) + 32;
}
时显示此错误,并得到了错误。但在真实设备上没有崩溃。
问题:java.lang.IndexOutOfBoundsException:setSpan(4 ... 4)结束于长度0之外
EditText
答案 0 :(得分:6)
受@ smitty1的solution的启发,我做了这个。我在自定义EditText中处理它,而不是在视图中检查所有EditText:
open class MaxLengthEditText : AppCompatAutoCompleteTextView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
/*
* On Android API versions <= 23 the app crashes if a text that is longer than the max length of the EditText
* is set using an accessibility action. To avoid this we cut the text down to the maximum allowed length.
*/
override fun performAccessibilityAction(action: Int, arguments: Bundle?): Boolean {
if (Build.VERSION.SDK_INT <= 23 && action == AccessibilityNodeInfo.ACTION_SET_TEXT) {
filters.forEach { filter ->
if (filter is InputFilter.LengthFilter) {
val maxLength = filter.max
arguments?.keySet()?.forEach { key ->
if (arguments[key] is CharSequence) {
val shorterText =
arguments.getCharSequence(key)?.subSequence(0, maxLength)
setText(shorterText)
return true
}
}
}
}
}
return super.performAccessibilityAction(action, arguments)
}
}
答案 1 :(得分:0)
在发布前的报告和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值。
答案 2 :(得分:0)
在我的情况下,EditText没有设置maxLength
。但是,我们使用了一些自定义InputFilter
。如下所示:
private val textFilter = object : InputFilter {
override fun filter(source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int): CharSequence? {
return when {
good -> null // just allow change as is
bad -> "" // ignore change totally[*].
else -> magic // return a calculated value
}
}
}
问题[*]通过返回空字符串完全忽略了该值,这在Marshmellow及以下设备上导致崩溃。这是我解决此问题的方法:
private val textFilter = object : InputFilter {
override fun filter(source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int): CharSequence? {
return when {
good -> null // just allow change as is
bad -> (dest.toString() + source.subSequence(start, end)).subSequence(dstart, dstart + (end - start)) // ignore change totally[*].
else -> magic // return a calculated value
}
}
}
关键点不得返回小于更改(end-start)
(在M及以下设备上)的任何内容。
我仍然感谢以前的回答,这些问题可以帮助我确定根本原因。