【问题标题】:No Activity found (browser) with valid http:// prefix未找到具有有效 http:// 前缀的活动(浏览器)
【发布时间】:2015-01-01 00:05:37
【问题描述】:

所以我的应用程序出现以下异常:

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 的文本)。它是关于什么的?安卓设备怎么可能没有浏览器?如何绕过这个或至少捕捉(我需要在文本中点击 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>

【问题讨论】:

    标签: android android-activity activitynotfoundexception


    【解决方案1】:

    我假设这是一个设置了 android:autolink 的 TextView,或者以其他方式显示 HTML(例如,使用 Html.fromHtml())。

    问题在于这会为嵌入式 URI 创建 URLSpan 实例,并且此类“盲目地”使用提供的 URI 调用 startActivity()。只要 URI 与任何注册的活动不匹配,就会崩溃。对于“http” URL,当设备没有浏览器应用程序时,或者(更有可能)使用阻止访问它的 restricted profile 时,可能会发生这种情况。

    this CommonsWare post 很好地解释了这个问题及其解决方案。您可以使用拦截onClick() 的自定义派生类替换URLSpan 实例以避免异常。

    有关相关问题,另请参阅 this answer

    【讨论】:

    • 这几乎是答案。但是,我既不使用 URLSpan 也不使用 Linkify 而是使用 setMovementMethod(LinkMovementMethod.getInstance()) 并且我不知道如何将 CommonsWare 的文章应用于此。现在对我来说唯一可见的方法是按照 Jeff Mixon 的回答应用或不应用 setMovementMethod()。
    • @Stan 解决方案应该是一样的,因为URLSpan 在幕后使用(从异常堆栈中可以看到)。您应该可以照原样从帖子中复制fixTextView()
    • 实际上,我已经尝试将它与删除 setMovementMethod() 一起尝试,但结果链接仍然不可点击。我错过了什么?我会将代码添加到我的问题中。
    • @Stan 不要删除setMovementMethod(),没关系。只需在setText() 之后添加fixTextView() 就足够了。
    【解决方案2】:

    Android 设备可能没有浏览器。据说,这不是必需的,但显然非常罕见。我会想到 Kindles 之类的 Android 设备,尽管它们仍然会有浏览器......

    不过,您可以在 TextView 中禁用 URL 链接,如下所示:

    textView.setLinksClickable(false);
    

    另外,related question

    编辑

    this answer:

    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 上的链接。

    【讨论】:

    • 是的,但我需要它可点击,它适用于大多数设备。我的意思是我有点惊讶(好吧,它的 android,它总是充满了一堆错误)但我希望处理这种情况,如果它可能避免应用程序崩溃......所以它不是关于禁止点击它的 url 关于如何避免在这种情况下应用崩溃。
    • 查看我的编辑。您只需检查用户是否有任何适用于该Intent 签名的有效应用程序,如果没有则禁用链接。
    • 这适用于我的情况,因为我可以决定应用或不应用 setMovementMethod()。但是对于 URLSpan,matiash 的答案是更好的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 2012-03-05
    • 2016-01-21
    • 2020-04-07
    • 1970-01-01
    • 2019-03-18
    相关资源
    最近更新 更多