如何在我的应用程序中打开Android的Web浏览器中的URL?

1605

如何在应用程序内以内置浏览器打开URL,而非在应用程序中打开?

我尝试了以下代码:

try {
    Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(download_link));
    startActivity(myIntent);
} catch (ActivityNotFoundException e) {
    Toast.makeText(this, "No application can handle this request."
        + " Please install a webbrowser",  Toast.LENGTH_LONG).show();
    e.printStackTrace();
}

但是我遇到了一个异常:

No activity found to handle Intent{action=android.intent.action.VIEW data =www.google.com

7
我认为这是因为这个原因:http://android-developers.blogspot.com/2009/12/hello-stack-overflow.html - Arutha
1
为什么有些设备无法正常工作?即使有网络浏览器,也会出现ActivityNotFoundException。 - user5259714
我看到和@Manu一样的问题。在Nexus 6上进行基本安装,有Chrome,但链接会导致异常。 - Brill Pappin
我可以隐藏地址栏吗?@Arutha - reza_khalafi
43个回答

2857

试试这个:

Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
startActivity(browserIntent);

对我来说,这个方案很好。
至于缺少的 "http://",我会简单地做如下处理:
if (!url.startsWith("http://") && !url.startsWith("https://"))
   url = "http://" + url;

我也可能会预先填充用户在EditText中输入URL的部分为"http://"。

在Kotlin中:
if (!url.startsWith("http://") && !url.startsWith("https://")) {
    url = "http://$url"
}

val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(browserIntent)

2
除了你的代码和mbaird的不同之外,从我所看到的发布内容来看。确保你的URL有http://的方案--显示的异常提示表明你的URL缺少方案。 - CommonsWare
5
是的!它错过了http://!用户输入URL,有没有自动格式化的方法? - Arutha
5
URLUtil是检查用户输入的“url”字符串的好方法。 - Dan
112
如果 url 不是以 "http://" 或 "https://" 开头,那么可能会出现一些错误的情况,例如 http://file:/// 这样的链接,这会破坏一些好的使用方式。尝试使用 URI 类解析 uri,并检查是否有方案(schema)。如果没有,就添加 "http://" ;) - tuxSlayer
29
你需要使用resolveCheck进行空值检查。请参考官方文档注意:如果设备上没有可以接收隐式意图的应用程序,则当调用startActivity()时,你的应用程序将崩溃。为了先验证是否存在一个应用程序可以接收该意图,请在你的Intent对象上调用resolveActivity()方法进行检查。 - kenju
显示剩余17条评论

148

实现这一目标的常见方法是使用以下代码:

String url = "http://www.stackoverflow.com";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url)); 
startActivity(i); 

可以更改为短代码版本的内容...

Intent intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse("http://www.stackoverflow.com"));      
startActivity(intent); 

或:

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.stackoverflow.com")); 
startActivity(intent);

最短! :

startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.stackoverflow.com")));

83

简单回答

您可以查看Android开发者官方示例

/**
 * Open a web page of a specified URL
 *
 * @param url URL to open
 */
public void openWebPage(String url) {
    Uri webpage = Uri.parse(url);
    Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}

工作原理

请看Intent的构造函数:

public Intent (String action, Uri uri)

您可以将android.net.Uri实例传递给第二个参数,基于给定的数据URL创建一个新的Intent。然后,只需调用startActivity(Intent intent)启动一个新的Activity,其中包含给定URL的Intent。
需要。docs中提到:如果设备上没有能够接收隐式意图的应用程序,则在调用startActivity()时,您的应用程序将崩溃。为了首先验证是否存在接收意图的应用程序,请在Intent对象上调用resolveActivity()。如果结果非空,则至少有一个可以处理意图的应用程序,并且可以安全地调用startActivity()。如果结果为空,则不应使用该意图,并且如果可能,应禁用调用该意图的功能。
奖励
您可以在创建Intent实例时像下面这样写一行代码:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

3
假定提供的URL中包含"http"。 - IgorGanapolsky
请查看以下内容,了解如何在API 30+上处理https链接:https://dev59.com/wXE95IYBdhLWcg3wrP-w - Alexander Zhukov
这在2015年可能是正确的,但现在即使在那些没有问题查看传入的 https:// URL 的设备上,intent.resolveActivity 也会返回 null。所以它有点无用。最好用 try/catch 包装起来。 - Al Ro
这在2015年可能是正确的,但是现在即使是那些可以正常查看传入的https:// URL的设备,intent.resolveActivity也会返回null。所以这种方法有点无用。最好还是用try/catch来包裹一下。 - undefined

68

在2.3版本中,我运气更好,使用了

final Intent intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(url));
activity.startActivity(intent);

两者之间的区别在于使用了 Intent.ACTION_VIEW 而不是字符串 "android.intent.action.VIEW"


1
什么是不同之处? - user1324936
1
这个答案对我帮助很大。我不知道区别在哪里,但我们遇到了一个2.3的问题,这个答案解决了问题。有人知道实现上的区别吗? - Innova
2
根据Android开发者:这个答案是“使用给定的操作创建一个意图。所有其他字段(数据,类型,类)都为null。”而被接受的答案是“使用给定的操作和给定的数据URL创建一个意图。” - Teo Inke

35

Kotlin的答案:

val browserIntent = Intent(Intent.ACTION_VIEW, uri)
ContextCompat.startActivity(context, browserIntent, null)

我已经在 Uri 上添加了一个扩展功能,以使这个过程更加简单易行

myUri.openInBrowser(context)

fun Uri?.openInBrowser(context: Context) {
    this ?: return // Do nothing if uri is null

    val browserIntent = Intent(Intent.ACTION_VIEW, this)
    ContextCompat.startActivity(context, browserIntent, null)
}
作为附加奖励,这里有一个简单的扩展函数,可以安全地将字符串转换为Uri。
"https://stackoverflow.com".asUri()?.openInBrowser(context)

fun String?.asUri(): Uri? {
    return try {
        Uri.parse(this)
    } catch (e: Exception) {
        null
    }
}

它并没有添加任何有趣的东西。如果没有应用程序处理URL,甚至不会起作用。会因为异常而崩溃。 - CoolMind
所有设备都应该有一个处理URL的应用程序。您可以根据需要添加自己的故障/异常处理。 - Gibolt
同意你的观点。 - CoolMind
如果 (intent.resolveActivity(context.packageManager) != null) { context.startActivity(intent) } - Codelaby
"".asUri()?.openInBrowser(requireContext()) //错误:没有找到处理意图的活动 {act=android.intent.action.VIEW dat=}。 - Codelaby

33

试试这个:

Uri uri = Uri.parse("https://www.google.com");
startActivity(new Intent(Intent.ACTION_VIEW, uri));

或者如果你想要在你的Activity中打开一个网页浏览器,那么可以按照以下方法操作:

WebView webView = (WebView) findViewById(R.id.webView1);
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
webView.loadUrl(URL);

如果您想在浏览器中使用缩放控件,可以使用以下代码:

settings.setSupportZoom(true);
settings.setBuiltInZoomControls(true);

4
请注意,WebView中已禁用插件等功能,并且需要INTERNET权限。【参考】(http://developer.android.com/reference/android/webkit/WebView.html) - user1544337

23

如果您想向用户展示所有浏览器列表并让他选择首选项,这是样例代码:

private static final String HTTPS = "https://";
private static final String HTTP = "http://";

public static void openBrowser(final Context context, String url) {

     if (!url.startsWith(HTTP) && !url.startsWith(HTTPS)) {
            url = HTTP + url;
     }

     Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
     context.startActivity(Intent.createChooser(intent, "Choose browser"));// Choose browser is arbitrary :)

}

6
如果有多个应用程序可以处理该意图,系统将自动提供选择器,对吗? - Jeffrey Blattman
@xmen-w-k 因为 URL 可以以 httphttps 开头,在 Java 中,将“魔法字符串”声明为常量是一个好习惯。 - Dmytro Danylyk
谢谢,我不知道context.startActivity。当从外部类调用它时非常有用。 - WuerfelDev

21

像其他人写的解决方案一样(它们都很好用),我想回答同样的问题,但是提供一个我认为大多数人更愿意使用的提示。

如果您希望您启动的应用程序在新任务中打开,独立于您自己的任务栈,而不是留在同一堆栈上,您可以使用此代码:

final Intent intent=new Intent(Intent.ACTION_VIEW,Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY|Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET|Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);

还有一种方法可以在Chrome自定义标签页中打开URL。 Kotlin示例:

@JvmStatic
fun openWebsite(activity: Activity, websiteUrl: String, useWebBrowserAppAsFallbackIfPossible: Boolean) {
    var websiteUrl = websiteUrl
    if (TextUtils.isEmpty(websiteUrl))
        return
    if (websiteUrl.startsWith("www"))
        websiteUrl = "http://$websiteUrl"
    else if (!websiteUrl.startsWith("http"))
        websiteUrl = "http://www.$websiteUrl"
    val finalWebsiteUrl = websiteUrl
    //https://github.com/GoogleChrome/custom-tabs-client
    val webviewFallback = object : CustomTabActivityHelper.CustomTabFallback {
        override fun openUri(activity: Activity, uri: Uri?) {
            var intent: Intent
            if (useWebBrowserAppAsFallbackIfPossible) {
                intent = Intent(Intent.ACTION_VIEW, Uri.parse(finalWebsiteUrl))
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_HISTORY
                        or Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
                if (!CollectionUtil.isEmpty(activity.packageManager.queryIntentActivities(intent, 0))) {
                    activity.startActivity(intent)
                    return
                }
            }
            // open our own Activity to show the URL
            intent = Intent(activity, WebViewActivity::class.java)
            WebViewActivity.prepareIntent(intent, finalWebsiteUrl)
            activity.startActivity(intent)
        }
    }
    val uri = Uri.parse(finalWebsiteUrl)
    val intentBuilder = CustomTabsIntent.Builder()
    val customTabsIntent = intentBuilder.build()
    customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_HISTORY
            or Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
    CustomTabActivityHelper.openCustomTab(activity, customTabsIntent, uri, webviewFallback)
}

创建一个新任务能否保护源应用程序免受错误和崩溃的影响,以防万一网络浏览器出现问题? - The Original Android
@TheOriginalAndroid,我不明白它与崩溃和Web浏览器有什么关系。请解释一下你想做什么。 - android developer
谢谢您的回复。您的帖子很有趣。特别是为了网站启动,开设新任务有什么好处? - The Original Android
3
为了让用户能够在你的应用和Web浏览器之间切换,你需要这样做。如果你打开最近任务屏幕,你会看到两个任务而不是一个。此外,在属于你的应用任务的单个任务中,你将看到两个缩略图:一个是你的应用,另一个是Web浏览器。我认为这样做会更清晰明了。 - android developer
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 已被弃用。 - Pratik Butani

18

在同一应用程序中使用Webview加载URL的另一个选项

webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://www.google.com");

请注意,在 WebView 中禁用了插件等功能,并且需要 INTERNET 权限。 (参考:http://developer.android.com/reference/android/webkit/WebView.html) - user1544337
还要注意,.setJavaScriptEnabled(true); 是很危险的。 - dan1st

12

你也可以这样做

在xml中:

<?xml version="1.0" encoding="utf-8"?>
<WebView  
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
在Java代码中:
public class WebViewActivity extends Activity {

private WebView webView;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.webview);

    webView = (WebView) findViewById(R.id.webView1);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.loadUrl("http://www.google.com");

 }

}

在 Manifest 文件中不要忘记添加网络权限...


1
这很有趣而且不同寻常。我猜这样用户就可以在我的应用程序中看到一个网页浏览器。是这样吗?我点赞。 - The Original Android

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接