[关闭]
@wangwangheng 2015-05-30T10:00:26.000000Z 字数 5060 阅读 3122

分享链接打开客户端功能实现逻辑

公司文档


版本 日期 作者 更新内容
1.0 2015-05-25 王恒 初稿

1.Android浏览器打开客户端原理

2.通过客户端分享出去的链接规范

2.1 Android客户端配置

  1. <activity
  2. android:name="com.hengeasy.guamu.droid.web.WebActivity"
  3. android:screenOrientation="portrait"
  4. android:theme="@android:style/Theme.NoTitleBar" >
  5. <intent-filter>
  6. <action android:name="android.intent.action.VIEW"/>
  7. <category android:name="android.intent.category.DEFAULT"/>
  8. <category android:name="android.intent.category.BROWSABLE"/>
  9. <data android:scheme="guamu" android:host="guamu"/>
  10. </intent-filter>
  11. </activity>

2.3 分享链接

2.3.1 分享链接的链接为不带有app_token和type的原生职位详情或者公司详情链接,并追加以下参数:

参数名 参数值 其他说明
type 1表示IOS;
2表示Android
和打开职位详情时传递的参数一致
share 1表示是分享出去的链接,其他值表示不是分享出去的链接 在客户端内打开详情的时候不会添加这个参数
url 服务端需要打开客户端的时候需要传递回来的参数 服务端打开客户端的时候,客户端加载这个链接并从这个链中获取必需的参数
需要对这个字符串做Base64加密
title 网页显示的标题 客户端职位详情页顶部的标题文字;
需要对这个字段做一下基于UTF-8编码的URLEncoder

url参数中应该包含网页的标题(职位的标题或者公司的标题)


特别注意:Base64编码或者解码的时候必须使用UTF-8编码并其使用Flag是Base64.NO_WRAP的那种方式(去除换行;Base64在进行转码的时候如果位数不是3的倍数会在字符串后面追加一个或者两个“=”)

例子:

  1. http://www.baidu.com/page?type=2&share=1&url=aHR0cHM6Ly96eWJ1bHVvLmNvbS93YW5nd2FuZ2hlbmcvbm90ZS85NTg0MQAC

2.3.2 追加参数的方法(待优化)

  1. /**
  2. *
  3. * getShareURL:得到分享链接. <br/>
  4. *
  5. * @author wangheng
  6. * @return
  7. */
  8. private String getShareURL(){
  9. String shareURL = mUrl;
  10. if(StringUtils.isNullOrEmpty(shareURL)){
  11. shareURL = mWebView.getUrl();
  12. }
  13. if(shareURL.contains("app_token=")){
  14. shareURL = shareURL.substring(0,shareURL.indexOf("app_token="));
  15. }
  16. String url = new String(shareURL);
  17. String title = mTopbarTitle.getText().toString();
  18. try{
  19. if(url.contains("?")){
  20. if(url.endsWith("?")){
  21. url = url + "title=" + URLEncoder.encode(title, "UTF-8");
  22. }else{
  23. if(url.endsWith("&")){
  24. url = url + "title=" + URLEncoder.encode(title, "UTF-8");
  25. }else{
  26. url = url + "&title=" + URLEncoder.encode(title, "UTF-8");
  27. }
  28. }
  29. }else{
  30. url = url + "?title=" + URLEncoder.encode(title, "UTF-8");
  31. }
  32. url = Base64.encodeToString(url.getBytes("UTF-8"), Base64.URL_SAFE);
  33. if(shareURL.contains("?")){
  34. if(shareURL.endsWith("?")){
  35. shareURL = shareURL + "type=2&share=1&title="
  36. + URLEncoder.encode(title, "UTF-8") + "&url=" + url;
  37. }else{
  38. if(shareURL.endsWith("&")){
  39. shareURL = shareURL + "type=2&share=1&title="
  40. + URLEncoder.encode(title, "UTF-8") + "&url=" + url;
  41. }else{
  42. shareURL = shareURL + "&type=2&share=1&title="
  43. + URLEncoder.encode(title, "UTF-8") + "&url=" + url;
  44. }
  45. }
  46. }else{
  47. shareURL = shareURL + "?type=2&share=1&title="
  48. + URLEncoder.encode(title, "UTF-8") + "&url=" + url;
  49. }
  50. }catch(Exception e){
  51. e.printStackTrace();
  52. }
  53. return shareURL;
  54. }

2.4 Android客户端接收服务端传递的参数

可以从getIntent().getData()拿到打开APP的完整的path,从这个Path中可以拿到我们需要的所有的参数

  1. Uri uri = intent.getData();
  2. if(uri == null){
  3. finish();
  4. return;
  5. }
  6. String schema = uri.getScheme();
  7. if(StringUtils.isNullOrEmpty(schema)){
  8. finish();
  9. return;
  10. }
  11. if("guamu".equals(schema)){
  12. mUrl = uri.getQueryParameter("url");
  13. if(mUrl != null){
  14. try {
  15. mUrl = new String(Base64.decode(mUrl.getBytes("UTF-8"), Base64.URL_SAFE),"UTF-8");
  16. title = URLDecoder.decode(Uri.parse(mUrl).getQueryParameter("title"),"UTF-8");
  17. isFromShared = Integer.parseInt(Uri.parse(mUrl).getQueryParameter("share")) == 1;
  18. } catch(Exception e) {
  19. title = App.getInstance().getString(R.string.web_topbar_title_detail);
  20. e.printStackTrace();
  21. }
  22. }
  23. }

3.服务端

3.1 业务逻辑

分享链接

3.2 协议和参数传递

例子:

  1. guamu://guamu?url=aHR0cHM6Ly96eWJ1bHVvLmNvbS93YW5nd2FuZ2hlbmcvbm90ZS85NTg0MQAC

3.3 跳转客户端以及跳转下载页面的逻辑代码(示例)

服务端判断操作系统的逻辑请参考:http://www.cnblogs.com/duanguyuan/p/3534470.html

3.3.1 创建不可见iframe

用户点击浏览器中的链接时,在动态创建一个不可见的iframe,并且让这个iframe去加载步骤1中的Schema,如下:

  1. var ifr = document.createElement('iframe');
  2. ifr.src="guamu://guamu?url=XXXXX"

3.3.2 跳转下载链接

如果在指定的时间内没有跳转成功,则当前页跳转到apk的下载地址(或下载页),如下:

window.location = download_url;

3.3.3 示例代码

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <meta name="apple-mobile-web-app-capable" content="yes">
  6. <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
  7. <title>this's a demo</title>
  8. <meta id="viewport" name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui">
  9. </head>
  10. <body>
  11. <div>
  12. <a id="J-call-app" href="javascript:;" class="label">立即打开&gt;&gt;</a>
  13. <input id="J-download-app" type="hidden" name="storeurl" value="http://m.chanyouji.cn/apk/chanyouji-2.2.0.apk">
  14. </div>
  15. <script>
  16. (function(){
  17. var ua = navigator.userAgent.toLowerCase();
  18. var t;
  19. var config = {
  20. /*scheme:必须*/
  21. scheme_IOS: 'guamu://',
  22. scheme_Adroid: 'guamu://guamu?url=XXXX',
  23. download_url: document.getElementById('J-download-app').value,
  24. timeout: 600
  25. };
  26. function openclient() {
  27. var startTime = Date.now();
  28. var ifr = document.createElement('iframe');
  29. ifr.src = ua.indexOf('os') > 0 ? config.scheme_IOS : config.scheme_Adroid;
  30. ifr.style.display = 'none';
  31. document.body.appendChild(ifr);
  32. var t = setTimeout(function() {
  33. var endTime = Date.now();
  34. if (!startTime || endTime - startTime < config.timeout + 200) {
  35. window.location = config.download_url;
  36. } else {
  37. }
  38. }, config.timeout);
  39. window.onblur = function() {
  40. clearTimeout(t);
  41. }
  42. }
  43. window.addEventListener("DOMContentLoaded", function(){
  44. document.getElementById("J-call-app")
  45. .addEventListener('click',openclient,false);
  46. }, false);
  47. })()
  48. </script>
  49. </body>
  50. </html>
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注