Android 调用手机浏览器的正确方式

效果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

intent-filter详解

效果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.有什么不足之处,希望大家指正。谢谢

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容