Нет активности (браузер) с действующим префиксом http://

Поэтому я получил исключение из моего приложения следующим образом:

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=http://google.com (has extras) }
    at  android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1512)
    at  android.app.Instrumentation.execStartActivity(Instrumentation.java:1384)
    at  android.app.Activity.startActivityForResult(Activity.java:3248)
    at  android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:839)
    at  android.app.Activity.startActivity(Activity.java:3359)
    at  android.text.style.URLSpan.onClick(URLSpan.java:62)
    at  android.text.method.LinkMovementMethod.onTouchEvent(LinkMovementMethod.java:212)
    at  android.widget.TextView.onTouchEvent(TextView.java:8704)
    at  android.view.View.dispatchTouchEvent(View.java:5556)
    at  android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
    at  android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
    at  android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
    at  android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
    at  android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
    at  android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
    at  android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
    at  android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
    at  android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
    at  android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
    at  android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
    at  android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
    at  com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1940)
    at  com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1390)
    at  android.app.Activity.dispatchTouchEvent(Activity.java:2414)
    at  com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1888)
    at  android.view.View.dispatchPointerEvent(View.java:5736)
    at  android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3017)
    at  android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2582)
    at  android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:887)
    at  android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2591)
    at  android.os.Handler.dispatchMessage(Handler.java:99)
    at  android.os.Looper.loop(Looper.java:137)
    at  android.app.ActivityThread.main(ActivityThread.java:4697)
    at  java.lang.reflect.Method.invokeNative(Native Method)
    at  java.lang.reflect.Method.invoke(Method.java:511)
    at  com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
    at  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
    at  dalvik.system.NativeStart.main(Native Method)

Это не приводит к моему коду. Я предполагаю, что это происходит, когда пользователь нажимает URL в тексте (а в приложении есть тексты с URL). О чем это? Как могло случиться, что на устройстве Android нет браузера? Как обойти это или хотя бы поймать (мне нужно, чтобы URL были кликабельными в тексте)?

ОБНОВИТЬ
На самом деле я обнаружил, что это исключение происходит в TextView, который предназначен для пустой заглушки представления списка:

listView = (ListView) findViewById(R.id.listView);
// empty pass list with clickable url inside
final TextView listEmptyView = (TextView) findViewById(R.id.txtNoPasses);
listEmptyView.setMovementMethod(LinkMovementMethod.getInstance());
listView.setEmptyView(listEmptyView);

Так что я попробовал это (следуя статье CommonsWare), но мой URL в этом случае остается совершенно неприкосновенным:

    listView = (ListView) findViewById(R.id.listView);
    // empty pass list with clickable url inside
    final TextView listEmptyView = (TextView) findViewById(R.id.txtNoPasses);
    fixTextView(listEmptyView);
    listView.setEmptyView(listEmptyView);
}

private void fixTextView(TextView textView) {
    final SpannableString current = new SpannableString(textView.getText());
    final URLSpan[] spans = current.getSpans(0, current.length(), URLSpan.class);
    int start, end;
    for (URLSpan span : spans) {
        start = current.getSpanStart(span);
        end = current.getSpanEnd(span);
        current.removeSpan(span);
        current.setSpan(new DefensiveURLSpan(span.getURL()), start, end, 0);
    }
}

private static class DefensiveURLSpan extends URLSpan {
      public DefensiveURLSpan(String url) {
        super(url);
      }

      @Override
      public void onClick(View widget) {
        try {
          android.util.Log.d(getClass().getSimpleName(), "Got here!");
          super.onClick(widget);
        }
        catch (ActivityNotFoundException e) {
          // do something useful here
          // android.text.SpannedString cannot be cast to android.text.SpannableString
        }
      }
}

И TextView:

<TextView
        android:id="@+id/txtNoPasses"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:visibility="gone"
        android:gravity="center"
        android:padding="15dp"
        android:text="@string/no_passes"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

А также no_passes строка следующая:

<string name="no_passes">Currently you have no cards to use.\n<a href="http://cardz.website.com">You could add some cards from our website</a></string>

2 ответа

Решение

Я предполагаю, что это TextView с android:autolink установить, или что в противном случае отображает HTML (например, используя Html.fromHtml()).

Проблема в том, что это создает URLSpan экземпляры для встроенных URI, и этот класс вызывает "вслепую" startActivity() с предоставленным URI. Это происходит сбой всякий раз, когда URI не совпадает ни с одной зарегистрированной активностью. Для "http" URL-адресов это может произойти, когда на устройстве нет приложения для браузера или (что более вероятно), когда используется ограниченный профиль, который блокирует доступ к нему.

Проблема и ее решение хорошо объяснены в этом сообщении CommonsWare. Вы можете заменить URLSpan экземпляры с пользовательским производным классом, который перехватывает onClick() чтобы избежать исключения.

Смотрите также этот ответ для связанной проблемы.

Устройство Android может не иметь браузера. Это не обязательно, скажем так, но, очевидно, довольно редко. Вспоминаются Android-устройства, такие как Kindles, хотя у них все еще был бы браузер...

Тем не менее, вы можете отключить URL-ссылки в вашем TextView следующее:

textView.setLinksClickable(false);

Также связанный вопрос.

редактировать

Смотрите этот ответ:

String url = "http://www.example.com";
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
PackageManager manager = mContext.getPackageManager();
List<ResolveInfo> list = manager.queryIntentActivities(intent, 0);

if (list != null && list.size() > 0) {
    //You have at least one activity to handle the intent
} else {
    //No activity to handle the intent.
}

Создать новое намерение с ACTION_VIEW и URL-адрес и используйте этот шаблон, чтобы определить, есть ли на устройстве какие-либо приложения, которые могут обрабатывать URL-адрес. Если этого не произойдет, то вы отключите переход по ссылкам на TextView для этого пользователя.

Другие вопросы по тегам