前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android scheme呼起App

Android scheme呼起App

作者头像
ayqy贾杰
发布2023-03-15 18:48:27
1.5K0
发布2023-03-15 18:48:27
举报
文章被收录于专栏:黯羽轻扬黯羽轻扬

一.自定义Scheme

Android应用/组件间通信有一种方式是intent,应用可以注册intent filter声明自己对什么样的intent感兴趣,其它应用发送intent时通过系统级广播传递过来,如果与预先注册的intent filter匹配,应用将收到该intent(无论应用是否正在运行,都会被“唤醒”,也就是隐式启动Activity),取出intent携带的数据,做进一步处理

就是这样,通过系统广播拿到一次起来的机会,例如在manifest里静态注册intent filter声明自定义scheme

代码语言:javascript
复制
<activity android:name=".MainActivity">
   <intent-filter>
       <action android:name="android.intent.action.MAIN" />       <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>   <!--注册scheme-->
   <intent-filter>
       <action android:name="android.intent.action.VIEW"/>
       <category android:name="android.intent.category.DEFAULT"/>
       <!--BROWSABLE指定该Activity能被浏览器安全调用-->
       <category android:name="android.intent.category.BROWSABLE"/>
       <!--声明自定义scheme,类似于http, https-->
       <data android:scheme="hoho"/>
   </intent-filter>
</activity>

actioncategorydata都必须完全匹配才能获得intent,这里声明了2个category,只有在intent同时含有这2个category时才算匹配,而android.intent.category.DEFAULT是默认的,有实际意义的是android.intent.category.BROWSABLE,表示允许通过浏览器启动该activity(呼起App)。后续的data限定了触发条件,当schemehoho时才匹配,例如浏览器访问hoho://abc,能够匹配成功,App就起来了

二.取出数据

onCreate里拿到intent,取出uri

代码语言:javascript
复制
@Override
protected void onCreate(Bundle savedInstanceState) {
   //...   // 获取uri参数
   Intent intent = getIntent();
   String scheme = intent.getScheme();
   Uri uri = intent.getData();
   String str = "";
   if (uri != null) {
       String host = uri.getHost();
       String dataString = intent.getDataString();
       String from = uri.getQueryParameter("from");
       String path = uri.getPath();
       String encodedPath = uri.getEncodedPath();
       String queryString = uri.getQuery();       //...根据uri判断打开哪个页,或者打开哪个功能
   }
}

这里的URI就是标准的URI,有协议、主机名、端口号、路径、查询字符串等等,但一般自定义scheme不需要这么麻烦,只用path/query做简单区分就行,比如:

代码语言:javascript
复制
// 通过path区分
hoho://toFeature/login
// 通过query区分
hoho://open?feature=login

当然,也可以通过端口号等区分,没什么区别

三.在线页面呼起App

浏览器先发出自定义scheme请求,系统广播收到后再分发给各应用,那么页面发送请求的方式就多了:

代码语言:javascript
复制
location.href
iframe.src
a.href
img.src
...其它能发出请求的方式

这些方式在强弱上有区别,比如location.href是强的,而img.src很弱,至少要强到浏览器决定把这个请求交给系统广播才行,比如img请求自定义scheme,浏览器认为没有必要交给系统广播。一般只用前2种最强的方式:location.hrefiframe.src,隐藏iframe偷偷请求自定义scheme相对用得更多,因为不会有未知的副作用(location方式或许可能被记入历史栈或者unload当前页,但iframe绝对没有太严重的副作用

但无论哪种方式,都无法得知App被呼起了没,可能没安装App,也可能intent没匹配成功,但页面肯定没有办法得知。所以一般呼起App的页面都会延迟自动跳转下载页,无论有没有成功呼起App,这也是迫不得已

除了页面发出请求,还有一种更强的方式:通过应用发出请求,例如:

代码语言:javascript
复制
// 通过webview发出请求
webview.loadUrl(mySchemeUri);

这个起点就是应用级,比WebView中页面请求要强一些。所以一般Hybrid App中,客户端会提供这样的接口,用来跳转第三方,比页面请求更强

四.Intent Scheme URL攻击

自定义Scheme存在安全风险,比如:

  • 注册优先级更高的相同intent filter,窃取scheme uri
  • 如果知道跳转的自定义scheme格式,可以跳向钓鱼页面(确实是在App里打开的页面,但它是第三方做的假的)
  • …其它风险

一般自定义scheme都是不公开的,但难免会泄漏出去(反编译App等方式),scheme接口本身要做好防范,接收intent时可以这样做:

代码语言:javascript
复制
    // forbid launching activities without BROWSABLE category
   intent.addCategory("android.intent.category.BROWSABLE");
   // forbid explicit call
   intent.setComponent(null);
   // forbid intent with selector intent
   intent.setSelector(null);

不信任所有来自自定义scheme的输入,对于跳转接口,还要有白名单限制

五.WebView Scheme白名单

WebView作为页面容器,可以过滤/拦截页面请求

代码语言:javascript
复制
class MyWebClient extends WebViewClient {   @Override
   public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
       if (url.startsWith("hoho://")) {
           return null;
       }       return super.shouldInterceptRequest(view, url);
   }   @Override
   public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
       String scheme = request.getUrl().getScheme();
       if (scheme.equals("hoho")) {
           return null;
       }       return super.shouldInterceptRequest(view, request);
   }
}

上面的用于API[11-20],21弃用String url,新增了WebResourceRequest request,在API21+只触发WebResourceRequest request形式的,所以兼容考虑,两个都要重写一遍

对于满足过滤条件的,拦截掉,所以在微信里无法呼起App,因为不在白名单里,被拦截下来,没有交给系统广播

在被拦截的情况下,iframe方式的优势就体现出来了,a.hreflocation.href都会导致页面跳转,显示“网页无法打开…因为net::ERR_UNKNOWN_URL_SCHEME”,而iframe方式不影响当前页

六.Demo

apk下载地址:http://ayqy.net/apk/android-scheme.apk

测试页面:http://ayqy.net/temp/android-scheme.html

写在最后

Android Studio实在太慢了,怀念eclipse,

参考资料

  • Android 通过网页打开自己的APP(scheme)
  • Android安全开发之浅谈网页打开APP
  • 附iOS通过自定义的URL Scheme启动你的App
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-01-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端问问 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二.取出数据
  • 三.在线页面呼起App
  • 四.Intent Scheme URL攻击
  • 五.WebView Scheme白名单
  • 六.Demo
    • 写在最后
      • 参考资料
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档