Android 调用手机浏览器的正确方式
2016-09-28 本文已影响3718人
5c7e9c07cd43
效果1
效果1.png参考 - 程序亦非猿 - Android 调用手机浏览器的正确方式
代码实现
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);、intent.setData(Uri.parse("http://www.baidu.com"));
// 注意此处的判断intent.resolveActivity()可以返回显示该Intent的Activity对应的组件名
// 官方解释 : Name of the component implementing an activity that can display the intent
if (intent.resolveActivity(getPackageManager()) != null) {
final ComponentName componentName = intent.resolveActivity(getPackageManager());
// 打印Log ComponentName到底是什么
Log.e(TAG, "componentName = " + componentName.getClassName());
startActivity(Intent.createChooser(intent, "请选择浏览器"));
} else {
Toast.makeText(getApplicationContext(), "没有匹配的程序", Toast.LENGTH_SHORT).show();
}
不太严谨的实现方式
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri content_url = Uri.parse(url);
intent.setData(content_url);
startActivity(intent);
这里出现问题的原因有2个:
1. 如果手机没有浏览器 - 程序崩溃。
2. 即便是有浏览器 - 也会使用默认的浏览器打开。我想使用Android的同学都用的是第三方的浏览器吧,都不给用户选择的权利,体验很差。
深入学习
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);intent.setData(Uri.parse("http://www.baidu.com"));
if (intent.resolveActivity(getPackageManager()) != null) {
final ComponentName componentName = intent.resolveActivity(getPackageManager());
Log.e(TAG, "componentName = " + componentName.getClassName());
}
Log-ComponentName
ComponentName : 原来是 BrowserActivity !
大家可以查看Android 源码找到这个类,本人能力有限,就不再献丑了!
参考 - SuShine的博客 - Android Browser学习二 BrowserActivity 的初始化 --其他重要模块
效果2
效果2.png代码实现
// 1.Button注册了点击事件
mRequstBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
if (intent.resolveActivity(getPackageManager()) != null) {
final ComponentName componentName = intent.resolveActivity(getPackageManager());
Log.e(TAG, "componentName = " + componentName.getClassName());
startActivity(Intent.createChooser(intent, "请选择浏览器"));
}
// 给需要调起的Activity增加 intent-filter
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
</intent-filter>
解读:
1. Button 注册了点击事件,打开浏览器访问 http://www.baidu.com,注意这里是Http协议
2. 需要被调起的Activity 注册 <intent-filter> 注意这里的约束scheme 是http协议,如果需要访问的网址是https协议,此处约束应该是scheme=https
字段 | 解释 |
---|---|
action | 指定 ACTION_VIEW Intent 操作,以便能够从 Google 搜索中访问该 Intent 过滤器 |
category | 定义了 BROWSABLE 和 DEFAULT 这两种 Intent 的 Activity-BROWSABLE:若要能够从 Web 浏览器执行该 Intent,则必须将其设为 BROWSABLE。如果未设置,点击浏览器中的链接将无法解析到您的应用(在这种情况下,只有当前的移动 Web 浏览器能响应该 URL)。DEFAULT:只有当您希望自己的 Android 应用能够响应任何引用网站中的 HTTP 链接时,才需要设为 DEFAULT。在 Google 搜索结果中使用的 Intent 包含您的应用标识信息,以便将您的应用明确指定为接收方。指向您的网站的其他链接不知道您的应用标识,因此 DEFAULT 类别声明了您的应用可以对隐式 Intent 做出响应。 |
data | Activity 接受的每种 URI 格式都有一个这样的标记。此 <data> 标记必须至少包括 android:scheme 属性。您可以添加额外的属性,以进一步细化 Activity 接受的 URI 类型。例如,您可能有多个接受类似 URI 的 Activity,但其不同之处只是在于路径名。在这种情况下,可以使用 android:path 属性或者其变体(pathPattern 或 pathPrefix)来区分对于不同的 URI 路径,系统应打开哪个 Activity |
效果3
前提: 本人通过手机默认浏览器及html查看器都可以成功调起本地app
步骤1-打开测试的网页.png
// 网页的源码,很简单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> 通过浏览器调起本地App </title>
</head>
<body>
<a href="cmc://test/name/familyname/?name=Wankaz&family_name=Arale">open app</a>
</body>
</html>
调起App效果图.png
// AndroidManifest.xml文件中的设置
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="test"
android:path="/name/familyname/"
android:scheme="cmc" />
</intent-filter>
// 获取到的数据
// 常量的定义
private final static String NAME = "name";
private final static String LASTNAME = "family_name";
// 解析intent中的数据
Intent intent = getIntent();
if (intent != null) {
Uri uri = intent.getData();
if (uri != null) {
Log.e("uri", uri.toString());
if ("cmc".equals(uri.getScheme())) {
List<String> list = uri.getPathSegments();
if (list != null && list.size() == 2) {
mShowWebContentTv.setText("获取到了浏览器数据,姓=" + uri.getQueryParameter(NAME) + ", 名=" + uri.getQueryParameter(LASTNAME));
}
} else {
Log.e("intent", "uri = null");
}
} else {
Log.e("intent", "intent = null");
}
// 代码解读
1. Html页面中只有一个超链接,<a href="cmc://test/name/familyname/?name=Wankaz&family_name=Arale">open app</a>
2. 设置 AndroidManifest.xml ,为需要调起的页面设置<intent-filter>,我们发现 <intent-filter>里面设置的<data>中的scale,host,path正好对应超链接中的 cmc://test/name/familyname/;而name=Wankaz&family_name=Arale则是对应的数据。
3. 代码中解析数据- 从html页面中获取到的数据见下图
调起App时,获取到html中的内容如下,该内容被封装到Intent中,并通过 intent.getData()获取(使用Uri表示),我们通过uri.getQueryParameter()获取具体字段的值。
Log-Uri.jpeg
问题
1.当App已启动时,也可以调起app,只是获取不到Intent中的数据。我的大概理解是Android中Activity启动时通过Intent在传递数据,如果我们的Activity已经启动,没有再次获取Intent对象,android:launchMode="singleInstance";这个需要其它同学解答下。
2.为什么我把Activity启动模式设置为android:launchMode="singleInstance"?因为如果我们使用默认的standard模式,会发现被调起的app的Activity运行在浏览器的任务栈中了。这是Activity启动模式对调起App的影响。
3.有什么不足之处,希望大家指正。谢谢