Ошибка Listactivity с запущенным устройством jelly bean (SPAN_EXCLUSIVE_EXCLUSIVE spans не может иметь нулевую длину)

У меня есть приложение, начинающееся с экрана Splash, затем откройте строки listactivity, нажатие на любую строку откроет действие, содержащее текстовое представление, две кнопки (одна из которых открывает бесконечную галерею, другая открывает настраиваемый диалог) и пункты меню ( о, предпочтении, выходе).

Это приложение отлично работает на имбирном хлебе, но при тестировании на галактике s3, работающей на желе bean, оно открывается нормально, но когда вы нажимаете на одну из строк списка, это означает, что он игнорирует щелчок. Лог-кот на затмении показывает:

SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length 

Тем не менее, сила не закрывается (список активности обычно прокручивается, и пункты меню работают нормально и).

UPDATE:
Я заметил это приложение: я создал его с помощью eclipse, так как около месяца назад с именем можно сказать (trip), и сегодня тестирование (trip.apk) на обоих имбирном хлебе и желе bean отлично работает.

Но я хотел изменить имя от trip до travel, и я не использовал Рефакторинг. Вместо этого я создал новый проект с именем приложения travel, но все остальное, как и предыдущее приложение trip, включая классы, res, и при тестировании с желе bean показывает:

SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length 

ОБНОВЛЕНИЕ 3:

Я РЕШИЛ ПРОБЛЕМУ:

Я добавил эту строку ко всем TextViews в моем приложении:

 android:textIsSelectable="true"

и эта строка приводит к тому, что строки игнорируют щелчок,

поэтому я удалил его, и теперь как старые, так и новые приложения отлично работают с обоими API.

ОБНОВЛЕНИЕ 4:

вышеуказанные фразы, относящиеся к старой проблеме и уже решенные,

ВОПРОС СЕЙЧАС:

мое приложение отлично работает со всеми API-интерфейсами, но при тестировании:

галактика S3 работает желе bean отлично работает,

, но в eclipse log cat show error:

 SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero  length

, не влияя на производительность приложения, любую идею решить эту ошибку.

любое объяснение будет высоко оценено, спасибо.

код моего проекта:

Меню:

public class Menu extends ListActivity {

    String classes[] = { "Introduction", "DreamsTrip", "Day one", "Day Two",
            "Day Three", "Day Four", "Day Five", "Conclusion" };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        // create background for whole list as image
        ListView lv = getListView();
        lv.setCacheColorHint(0);
        lv.setSelector(android.R.color.transparent);
        lv.setPadding(30, 0, 30, 0);
        lv.setVerticalScrollBarEnabled(false);
        lv.setBackgroundResource(R.drawable.list_background);
        lv.setDivider(new ColorDrawable(0x00000000));
        setListAdapter(new MyArrayAdapter(this, classes));
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        String cheese = classes[position];
        try {
            Intent ourIntent;
            if (position > 1 && position < 25) {
                Class ourClass = Class.forName("com.test.demo.MyDay");
                ourIntent = new Intent(Menu.this, ourClass);
                ourIntent.putExtra("cheese", cheese);
            } else {
                Class ourClass = Class.forName("com.test.demo." + cheese);
                ourIntent = new Intent(Menu.this, ourClass);
            }
            startActivity(ourIntent);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public boolean onCreateOptionsMenu(android.view.Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.cool_menu, menu);
        getLayoutInflater().setFactory(new Factory() {

            public View onCreateView(String name, Context context,
                    AttributeSet attrs) {
                if (name.equalsIgnoreCase(
                        "com.android.internal.view.menu.IconMenuItemView")) {
                    try {
                        LayoutInflater li = LayoutInflater.from(context);
                        final View view = li.createView(name, null, attrs);
                        new Handler().post(new Runnable() {

                            public void run() {
                                view.setBackgroundResource(R.drawable.border3);
                                ((TextView) view).setTextSize(25);
                                ((TextView) view).setTypeface(FontFactory
                                        .getBFantezy(getBaseContext()));
                                ((TextView) view).setTextColor(Color.RED);
                            }
                        });
                        return view;
                    } catch (InflateException e) {
                    } catch (ClassNotFoundException e) {
                    }
                }
                return null;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.aboutUs:
            Intent i = new Intent("com.test.demo.ABOUT");
            startActivity(i);
            break;
        case R.id.preferences:
            Intent p = new Intent("com.test.demo.PREFS");
            startActivity(p);
            break;
        case R.id.exit:
            finish();
            break;
        }
        return false;
    }
}

MyArrayAdapter:

public class MyArrayAdapter extends ArrayAdapter<String> {

    private final Activity context;
    private final String[] classes;
    Typeface tf;

    static class ViewHolder {

        public TextView text;
        public ImageView image;
    }

    public MyArrayAdapter(Activity context, String[] classes) {
        super(context, R.layout.row, classes);
        this.context = context;
        this.classes = classes;
        tf = Typeface.createFromAsset(context.getAssets(), "BFantezy.ttf");
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        if (rowView == null) {
            LayoutInflater inflater = context.getLayoutInflater();
            rowView = inflater.inflate(R.layout.row, null);
            ViewHolder viewHolder = new ViewHolder();
            viewHolder.text = (TextView) rowView.findViewById(R.id.row_label);
            viewHolder.image = (ImageView) rowView.findViewById(R.id.row_image);
            viewHolder.text.setTypeface(FontFactory.getBFantezy(getContext()));
            rowView.setTag(viewHolder);
        }
        ViewHolder holder = (ViewHolder) rowView.getTag();
        String s = classes[position];
        holder.text.setText(s);
        if (s.equals("Day one")) {
            holder.image.setImageResource(R.drawable.day1);
        }
        if (s.equals("Day Two")) {
            holder.image.setImageResource(R.drawable.day2);
        }
        if (s.equals("Day Three")) {
            holder.image.setImageResource(R.drawable.day3);
        }
        if (s.equals("Day Four")) {
            holder.image.setImageResource(R.drawable.day4);
        }
        if (s.equals("Day Five")) {
            holder.image.setImageResource(R.drawable.day5);
        }
        if (s.equals("Conclusion")) {
            holder.image.setImageResource(R.drawable.day_concl);
        }
        if (s.equals("DreamsTrip")) {
            holder.image.setImageResource(R.drawable.day_trip);
        }
        if (s.equals("Introduction")) {
            holder.image.setImageResource(R.drawable.day_intr);
        }
        return rowView;
    }
}

MyDay:

public class MyDay extends Activity {

    final Context context = this;
    private Button button;
    TextView tv2, tv3, tv4;
    String day;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        Boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        setContentView(R.layout.day);
        if (customTitleSupported) {
            getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
                    R.layout.custom_title);
        }
        initializeTextViews();
    }

    private void initializeTextViews() {
        tv2 = (TextView) findViewById(R.id.day_tv1);
        tv2.setTypeface(FontFactory.getBFantezy(getBaseContext()));
        tv3 = (TextView) findViewById(R.id.day_tv3);
        tv3.setTypeface(FontFactory.getDroidNaskh(getBaseContext()));
        day = getIntent().getStringExtra("cheese");
        if (day.equalsIgnoreCase("Day One")) {
            tv2.setText(Html.fromHtml(getString(R.string.beginning)));
            tv3.setText(Html.fromHtml(getString(R.string.day1)));
            button = (Button) findViewById(R.id.city_button);
            button.setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {
                    // custom dialog
                    final Dialog dialog = new Dialog(context,
                            R.style.cust_dialog);
                    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                    dialog.setContentView(R.layout.custom_dialog);
                    // set the custom dialog components - text, image and button
                    TextView text = (TextView) dialog
                            .findViewById(R.id.dialog_text);
                    text.setTypeface(FontFactory.getBFantezy(getBaseContext()));
                    text.setText(Html
                            .fromHtml(getString(R.string.torusim_places_1)));
                    Button dialogButton = (Button) dialog
                            .findViewById(R.id.dialog_Button);
                    dialogButton.setTypeface(FontFactory
                            .getBFantezy(getBaseContext()));
                    // if button is clicked, close the custom dialog
                    dialogButton.setOnClickListener(new OnClickListener() {

                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                    dialog.show();
                }
            });
        } else if (day.equalsIgnoreCase("Day Two")) {
            tv2.setText(Html.fromHtml(getString(R.string.beginning)));
            tv3.setText(Html.fromHtml(getString(R.string.day2)));
            button = (Button) findViewById(R.id.city_button);
            button.setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {
                    // custom dialog
                    final Dialog dialog = new Dialog(context,
                            R.style.cust_dialog);
                    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                    dialog.setContentView(R.layout.custom_dialog);
                    // set the custom dialog components - text, image and button
                    TextView text = (TextView) dialog
                            .findViewById(R.id.dialog_text);
                    text.setTypeface(FontFactory.getBFantezy(getBaseContext()));
                    text.setText(Html
                            .fromHtml(getString(R.string.torusim_places_2)));
                    Button dialogButton = (Button) dialog
                            .findViewById(R.id.dialog_Button);
                    dialogButton.setTypeface(FontFactory
                            .getBFantezy(getBaseContext()));
                    // if button is clicked, close the custom dialog
                    dialogButton.setOnClickListener(new OnClickListener() {

                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                    dialog.show();
                }
            });
        } else if (day.equalsIgnoreCase("Day Three")) {
            tv2.setText(Html.fromHtml(getString(R.string.beginning)));
            tv3.setText(Html.fromHtml(getString(R.string.day3)));
            button = (Button) findViewById(R.id.city_button);
            button.setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {
                    // custom dialog
                    final Dialog dialog = new Dialog(context,
                            R.style.cust_dialog);
                    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                    dialog.setContentView(R.layout.custom_dialog);
                    // set the custom dialog components - text, image and button
                    TextView text = (TextView) dialog
                            .findViewById(R.id.dialog_text);
                    text.setTypeface(FontFactory.getBFantezy(getBaseContext()));
                    text.setText(Html
                            .fromHtml(getString(R.string.torusim_places_3)));
                    Button dialogButton = (Button) dialog
                            .findViewById(R.id.dialog_Button);
                    dialogButton.setTypeface(FontFactory
                            .getBFantezy(getBaseContext()));
                    // if button is clicked, close the custom dialog
                    dialogButton.setOnClickListener(new OnClickListener() {

                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                    dialog.show();
                }
            });
        } else if (day.equalsIgnoreCase("Day Four")) {
            tv2.setText(Html.fromHtml(getString(R.string.beginning)));
            tv3.setText(Html.fromHtml(getString(R.string.day4)));
            button = (Button) findViewById(R.id.city_button);
            button.setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {
                    // custom dialog
                    final Dialog dialog = new Dialog(context,
                            R.style.cust_dialog);
                    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                    dialog.setContentView(R.layout.custom_dialog);
                    // set the custom dialog components - text, image and button
                    TextView text = (TextView) dialog
                            .findViewById(R.id.dialog_text);
                    text.setTypeface(FontFactory.getBFantezy(getBaseContext()));
                    text.setText(Html
                            .fromHtml(getString(R.string.torusim_places_4)));
                    Button dialogButton = (Button) dialog
                            .findViewById(R.id.dialog_Button);
                    dialogButton.setTypeface(FontFactory
                            .getBFantezy(getBaseContext()));
                    // if button is clicked, close the custom dialog
                    dialogButton.setOnClickListener(new OnClickListener() {

                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                    dialog.show();
                }
            });
        } else if (day.equalsIgnoreCase("Day Five")) {
            tv2.setText(Html.fromHtml(getString(R.string.beginning)));
            tv3.setText(Html.fromHtml(getString(R.string.day5)));
            button = (Button) findViewById(R.id.city_button);
            button.setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {
                    // custom dialog
                    final Dialog dialog = new Dialog(context,
                            R.style.cust_dialog);
                    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                    dialog.setContentView(R.layout.custom_dialog); // set the
                    // custom dialog components - text, image and button
                    TextView text = (TextView) dialog
                            .findViewById(R.id.dialog_text);
                    text.setTypeface(FontFactory.getBFantezy(getBaseContext()));
                    text.setText(Html
                            .fromHtml(getString(R.string.torusim_places_5)));
                    Button dialogButton = (Button) dialog
                            .findViewById(R.id.dialog_Button);
                    dialogButton.setTypeface(FontFactory
                            .getBFantezy(getBaseContext()));
                    // if button is clicked, close the custom dialog
                    dialogButton.setOnClickListener(new OnClickListener() {

                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                    dialog.show();
                }
            });
        }
    }

    public void handleClick(View v) {
        // Create an intent to start the new activity.
        Intent intent = new Intent();
        intent.setClass(this, DayGallery.class);
        intent.putExtra("dayname", day);
        startActivity(intent);
    }
}

LogCat:

D/AbsListView(14159): Get MotionRecognitionManager
D/dalvikvm(14159): GC_FOR_ALLOC freed 81K, 9% free 12164K/13315K, paused 13ms, total  
13ms
I/dalvikvm-heap(14159): Grow heap (frag case) to 14.306MB for 1555216-byte allocation
D/dalvikvm(14159): GC_CONCURRENT freed 2K, 8% free 13681K/14855K, paused 12ms+1ms, 
total 20ms
D/dalvikvm(14159): GC_FOR_ALLOC freed 0K, 8% free 13681K/14855K, paused 10ms, total 
10ms
I/dalvikvm-heap(14159): Grow heap (frag case) to 16.941MB for 2764816-byte allocation
D/dalvikvm(14159): GC_CONCURRENT freed 0K, 7% free 16381K/17607K, paused 12ms+2ms, 
total 23ms
D/libEGL(14159): loaded /system/lib/egl/libEGL_mali.so
D/libEGL(14159): loaded /system/lib/egl/libGLESv1_CM_mali.so
D/libEGL(14159): loaded /system/lib/egl/libGLESv2_mali.so
D/(14159): Device driver API match
D/(14159): Device driver API version: 10
D/(14159): User space API version: 10 
D/(14159): mali: REVISION=Linux-r2p4-02rel0 BUILD_DATE=Tue Oct 16 15:37:13 KST 2012 
D/OpenGLRenderer(14159): Enabling debug mode 0
D/dalvikvm(14159): GC_FOR_ALLOC freed 1732K, 16% free 15672K/18439K, paused 19ms, 
total 19ms
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
D/dalvikvm(14159): GC_CONCURRENT freed 691K, 13% free 16102K/18439K, paused 13ms+2ms, 
total 27ms
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
W/OpenGLRenderer(14159): Shape round rect too large to be rendered into a texture 
(680x12472, max=4096x4096)
W/OpenGLRenderer(14159): Shape round rect too large to be rendered into a texture 
(688x12480, max=4096x4096)
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length
E/SpannableStringBuilder(14159): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero 
length

Ответ 1

Чтобы понять, что здесь происходит, все начинается с дизайнерского решения о том, что a TextView должно и не должно быть. Согласно источник android для TextView:

/**
 * Displays text to the user and optionally allows them to edit it.  A TextView
 * is a complete text editor, however the basic class is configured to not
 * allow editing; see {@link EditText} for a subclass that configures the text
 * view for editing.

Это означает, что даже если все, что вы делаете, это наложение части текста на экран, скрытый позади, это объекты полного выделения текста, выбора и редактирования. Что здесь произошло, так это то, что небольшая настройка для решения проблемы в них, по-видимому, повлияла на некоторые другие функции и создала несколько строк журнала. То, что это имеет место, получают больше веса, скажем, Ошибка Nexus 7" SPAN_EXCLUSIVE_EXCLUSIVE охватывает не может иметь нулевую длину, в которой казалось бы, что на некоторых андроидах версии этой ситуации можно устранить, отключив автозаполнение в текстовых (вводных) полях:

View.setInputType( InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS );

Это также можно сделать в XML, используя соответствующие теги для TextView:

android:inputType="none"

Кажется, что строки появились в Android 4.1 (Jelly Bean), в setSpan функции SpannableStringBuilder (например, 2.2.3 источник vs 4.1.1 источник). Строка журнала инициируется попыткой установить диапазон в строке нулевой длины. Вот почему его следует устанавливать так, чтобы не нужно выбирать (суб) раздел текста, чтобы избежать этой ошибки либо с помощью вышеприведенного совета, либо с помощью:

android:textIsSelectable="false"
android:editable="false"

Более спекулятивное решение может гарантировать, что в TextView никогда не будет пустой строки, добавив символ "\ u200b" (не показан пустой символ нулевой ширины) для каждой строки, помещенной в ваш TextView s, либо переопределив setText (чтобы просто добавить его в конец строки) в пользовательский TextView, либо поместив его в свой код для каждой строки, отправленной на TextView s.

Для тех, кто любит вникать в систему Android и переделывать ее, согласно этот фрагмент источника android, похоже, что это mght можно решить проблему следующим образом. Однако нет никаких гарантий, что он работает. Действительно храбрый (безрассудный) может написать для себя полный SpannableStringBuilder....

  • Создание вашей собственной формы SpannableStringBuilder, которая перехватывает условие. Этот пример просто останавливается тихо, а не останавливается громко, согласно оригиналу:

    import android.text.SpannableStringBuilder;
    
    public class MySpannableStringBuilder extends SpannableStringBuilder {
        // Taken from SpannableStringBuilder.java
        private static final int MARK = 1;
        private static final int POINT = 2;
        private static final int START_MASK = 0xF0;
        private static final int END_MASK = 0x0F;
        private static final int START_SHIFT = 4;
    
        MySpannableStringBuilder() {
            super();
        }
    
        MySpannableStringBuilder(CharSequence text) {
            super(text);
        }
    
        MySpannableStringBuilder(CharSequence text, int start, int end) {
            super(text, start, end);
        }
    
        @Override
        public void setSpan(Object what, int start, int end, int flags) {
            // Determine if the error is going to be triggered, if so fail silently
            int flagsStart = (flags & START_MASK) >> START_SHIFT;
            int flagsEnd = flags & END_MASK;
            if (flagsStart == POINT && flagsEnd == MARK && start == end) {
                return;
            }
    
            // All good, so call the real routine
            super.setSpan(what, flagsStart, end, flagsEnd);
        }
    }
    
  • Создание MyEditableFactory extends Editable.Factory и установка его для возврата SpannableStringBuilder:

    import android.text.Editable;
    
    public class MyEditableFactory extends Editable.Factory {
        private static MyEditableFactory sInstance = new MyEditableFactory();
    
        /**
          * Returns this Editable Factory.
          */
        public static Editable.Factory getInstance() {
            return sInstance;
        }
    
        public Editable newEditable(CharSequence source) {
            return new MySpannableStringBuilder(source);
        }
    }
    

Помимо написания пользовательской версии ОС и помещения ее в телефон, я не уверен, что еще возможно.

Все предложения по улучшению приветствуются, а также отзывы об использовании этого кода в различных ситуациях ОС.

Ответ 3

Компилятор, возможно, не сможет проанализировать/использовать текст на арабском языке (исправить меня, если я ошибаюсь).

Вы можете попробовать, явно устанавливая каждый String под UTF-8:

String[] classes = 
    {
        new String("example1".getBytes(), "UTF-8"),
        new String("example2".getBytes(), "UTF-8")
    };

Сделайте то же самое для вызовов equals в onListItemClick

String cheese = new String(classes[position].getBytes(), "UTF-8");

    if(cheese.equals(new String("المقدمة".getBytes(), "UTF-8")))
    {
        cheese = new String("Introduction".getBytes(), "UTF-8");
    }

Еще лучше, просто сделайте метод.

private Object stringUTF8(final Object string)
{
    try
    {
        return new String(((String) string).getBytes(), "UTF-8");
    }
    catch(UnsupportedEncodingException e)
    {
        e.printStackTrace();

        return "error";
    }
}