技术实现
直接用window.location.href的方法解决,这个方法的前提条件是需要知道自己app对应的打开协议,如贴吧APP,协议为:com.baidu.tieba://(下边以百度贴吧为例)
1 | <!-- a标签点击打开的动作,在click事件中注册 --> |
2 | <a href="javascript:;" id="openApp">贴吧客户端</a> |
3 | <script type="text/javascript"> |
4 | document.getElementById('openApp').onclick = function(e){ |
5 | window.location.href = "com.baidu.tieba://"; |
6 | window.setTimeout(function(){ |
7 | window.location.href = "https://itunes.apple.com/cn/app/id477927812";//打开app下载地址,由app开发人员提供 |
8 | },2000) |
9 | }; |
10 | </script> |
因为Android和iOS的下载包和协议是不同的所以需要判断一下用户的系统类型
1 | <body> |
2 | <a href="javascript:;" id="openApp">贴吧客户端</a> |
3 | </body> |
4 | |
5 | <script type="text/javascript"> |
6 | document.getElementById('openApp').onclick = function(e){ |
7 | if(navigator.userAgent.match(/(iPhone|iPod|iPad);?/i)) |
8 | { |
9 | window.location.href = "com.baidu.tieba://";//ios app协议 |
10 | window.setTimeout(function() { |
11 | window.location.href = "https://itunes.apple.com/cn/app/id477927812"; |
12 | }, 2000) |
13 | } |
14 | if(navigator.userAgent.match(/android/i)) |
15 | { |
16 | window.location.href = "com.baidu.tieba://app";//android app协议 |
17 | window.setTimeout(function() { |
18 | window.location.href = "https://****.apk";//android 下载地址 |
19 | }, 2000) |
20 | } |
21 | }; |
22 | </script> |
但是用window.location.href方法的话当手机中有目标应用时,应用打开,但是浏览器也会跳转到下载页面,而且微信浏览器不支持打开、下载第三方app,所以做微信活动页的coder们当遇到需要实现该需求时所考虑的就更多了。
京东针对于这个问题的解决方案。如下
1 | (function(){ |
2 | // 判断浏览器 |
3 | var Navigator = navigator.userAgent; |
4 | var ifChrome = Navigator.match(/Chrome/i) != null && Navigator.match(/Version\/\d+\.\d+(\.\d+)?\sChrome\//i) == null ? true : false; |
5 | var ifAndroid = (Navigator.match(/(Android);?[\s\/]+([\d.]+)?/)) ? true : false; |
6 | var ifiPad = (Navigator.match(/(iPad).*OS\s([\d_]+)/)) ? true : false; |
7 | var ifiPhone = (!ifiPad && Navigator.match(/(iPhone\sOS)\s([\d_]+)/)) ? true : false; |
8 | var ifSafari = (ifiPhone || ifiPad) && Navigator.match(/Safari/); |
9 | var version = 0; |
10 | ifSafari && (version = Navigator.match(/Version\/([\d\.]+)/)); |
11 | |
12 | version = parseFloat(version[1], 10); |
13 | // 是否从微信打开 |
14 | var ifWeixin = navigator.userAgent.indexOf("MicroMessenger") >= 0; // weixin |
15 | var j = false; |
16 | var iframe = "plugIn_downloadAppPlugIn_loadIframe"; |
17 | var t = false; |
18 | var i = 0; |
19 | var B = {}; |
20 | var b = {}; |
21 | var selector = null; |
22 | var Hquery = {}; |
23 | // 判断当前使用的js框架是zepto还是jquery |
24 | var Query = window.Zepto || window.jQuery ? true : false; |
25 | var g = []; |
26 | // 是否存在html5的localStorage 存储 |
27 | var v = window.localStorage ? true : false; |
28 | var o = "mdownloadAppPlugInskip"; |
29 | var p = null; |
30 | |
31 | function m() { // 打印时间 例如:2016-5-18 |
32 | var M = new Date(); |
33 | var N = M.getFullYear(); |
34 | var O = M.getMonth() + 1; |
35 | var L = M.getDate(); |
36 | strDate = N + "-" + O + "-" + L; |
37 | return strDate |
38 | } |
39 | // 微信相关操作 |
40 | function r() { // weixin api |
41 | WeixinJSBridge.invoke("getInstallState", { |
42 | packageName: "com.jingdong.app.mall", |
43 | packageUrl: "openApp.jdMobile://" |
44 | }, function(M) { |
45 | var N = M.err_msg, |
46 | L = 0; |
47 | if (N.indexOf("get_install_state:yes") > -1) { |
48 | j = true |
49 | } |
50 | }) |
51 | } |
52 | // 根据是否存在js框架进行dom和时间的绑定 |
53 | function bind(dom, event, fun) { // bind event |
54 | if (Query) { |
55 | selector("#" + dom).bind(event, fun) |
56 | } else { |
57 | selector("#" + dom).addEventListener(event, fun, !1) |
58 | } |
59 | } |
60 | |
61 | function z(L) { |
62 | var M = (L || "mGen") + (++i); |
63 | return M |
64 | } |
65 | // 微信操作 |
66 | if (ifWeixin) { // if navigitor is weixin |
67 | if (window.WeixinJSBridge && WeixinJSBridge.invoke) { |
68 | r() |
69 | } else { |
70 | document.addEventListener("WeixinJSBridgeReady", r, !1) |
71 | } |
72 | } |
73 | |
74 | // 如果存在js框架 |
75 | if (Query) { |
76 | selector = window.$; |
77 | Hquery = window.$ |
78 | } else { |
79 | selector = function(obj) { |
80 | if (typeof obj == "object") { |
81 | return obj |
82 | } |
83 | return document.querySelector(obj); |
84 | }; |
85 | if (!window.$) { |
86 | window.$ = Hquery = selector |
87 | } else { |
88 | Hquery = window.$ |
89 | } |
90 | } |
91 | window.onblur = function() { |
92 | for (var L = 0; L < g.length; L++) { |
93 | clearTimeout(g[L]) |
94 | } |
95 | }; |
96 | // 设置cookie。 |
97 | function e(N) { |
98 | var M = document.cookie.indexOf(N + "="); |
99 | if (M == -1) { |
100 | return "" |
101 | } |
102 | M = M + N.length + 1; |
103 | var L = document.cookie.indexOf(";", M); |
104 | if (L == -1) { |
105 | L = document.cookie.length |
106 | } |
107 | return document.cookie.substring(M, L) |
108 | } |
109 | // 设置cookie |
110 | function l(N, P, L, Q, O) { |
111 | var R = N + "=" + escape(P); |
112 | if (L != "") { |
113 | var M = new Date(); |
114 | M.setTime(M.getTime() + L * 24 * 3600 * 1000); |
115 | R += ";expires=" + M.toGMTString() |
116 | } |
117 | if (Q != "") { |
118 | R += ";path=" + Q |
119 | } |
120 | if (O != "") { |
121 | R += ";domain=" + O |
122 | } |
123 | document.cookie = R |
124 | } |
125 | |
126 | // 打开的链接集合 |
127 | function F(L) { |
128 | var url = { |
129 | downAppURl: "http://h5.m.jd.com/active/download/download.html?channel=jd-m", |
130 | downAppIos: "http://union.m.jd.com/download/go.action?to=http%3A%2F%2Fitunes.apple.com%2Fcn%2Fapp%2Fid414245413&client=apple&unionId=12532&subunionId=m-top&key=e4dd45c0f480d8a08c4621b4fff5de74", |
131 | downWeixin: "http://a.app.qq.com/o/simple.jsp?pkgname=com.jingdong.app.mall&g_f=991850", |
132 | downIpad: "https://itunes.apple.com/cn/app/jing-dong-hd/id434374726?mt=8", |
133 | inteneUrl: "openApp.jdMobile://360buy?type=1", |
134 | inteneUrlParams: null, |
135 | openAppBtnId: "", |
136 | closePanelBtnId: "", |
137 | closePanelId: "", |
138 | closeCallblack: null, |
139 | closeCallblackSource: null, |
140 | cookieFlag: null, |
141 | noRecord: false, |
142 | sourceType: "JSHOP_SOURCE_TYPE", |
143 | sourceValue: "JSHOP_SOURCE_VALUE", |
144 | openAppEventId: "MDownLoadFloat_OpenNow", |
145 | closePanelEventId: "MDownLoadFloat_Close" |
146 | }; |
147 | if (L) { |
148 | for (var M in L) { |
149 | if (M && L[M]) { |
150 | url[M] = L[M] |
151 | } |
152 | } |
153 | } |
154 | return url |
155 | } |
156 | // 敲黑板 重点内容。看京东是怎么解决兼容问题的。 |
157 | function openApp(N, L) { // openApp |
158 | var R = h(N); //获取相对应的url |
159 | var O = null; |
160 | if (ifWeixin) { // 如果是微信端 |
161 | var M = null; |
162 | if (j) { |
163 | M = R |
164 | } else { |
165 | M = N.downWeixin |
166 | } |
167 | location.href = M; // 直接使用location.href打开 |
168 | return |
169 | } |
170 | if (ifiPad) { // 如果是ipad |
171 | O = N.downIpad |
172 | } else { |
173 | if (ifiPhone) { // 如果是iphone |
174 | O = N.downAppIos |
175 | } else { |
176 | O = N.downAppURl |
177 | } |
178 | } |
179 | |
180 | if (ifChrome) { // 如果是chrome |
181 | if (ifAndroid) { //安卓浏览器 |
182 | var Q = R; |
183 | R = y(Q); |
184 | // 延后50毫秒 |
185 | setTimeout(function() { |
186 | window.location.href = R |
187 | }, 50) |
188 | } |
189 | } |
190 | if (ifSafari && version >= 9) { // 判断safari版本 如果大于9 |
191 | setTimeout(function() { // 必须要使用settimeout |
192 | var S = document.createElement("a"); //创建a元素 |
193 | S.setAttribute("href", R), S.style.display = "none", document.body.appendChild(S); |
194 | var T = document.createEvent("HTMLEvents"); // 返回新创建的 Event 对象,具有指定的类型。 |
195 | T.initEvent("click", !1, !1)// 初始化新事件对象的属性, S.dispatchEvent(T) // 绑定事件 |
196 | }, 0) |
197 | } else { |
198 | document.querySelector("#" + iframe).src = R // 将iframe增加src |
199 | } |
200 | var P = Date.now(); |
201 | setTimeout(function() { |
202 | if (L) { |
203 | var S = setTimeout(function() { |
204 | x(P, O) |
205 | }, 1500); |
206 | g.push(S) |
207 | } |
208 | }, 100) |
209 | } |
210 | // x方法 |
211 | function x(N, downUrl) { |
212 | var L = Date.now(); |
213 | if (N && (L - N) < (1500 + 200)) { |
214 | window.location.href = downUrl |
215 | } |
216 | } |
217 | |
218 | function h(N) { |
219 | var V = []; |
220 | var P = N.inteneUrlParams; |
221 | var T = { |
222 | category: "jump", |
223 | des: "productDetail" |
224 | }; |
225 | if (N.sourceType && N.sourceValue) { |
226 | T.sourceType = N.sourceType; |
227 | T.sourceValue = N.sourceValue; |
228 | if (P && !P.sourceType && !P.sourceValue) { |
229 | P.sourceType = N.sourceType; |
230 | P.sourceValue = N.sourceValue |
231 | } |
232 | } |
233 | if (P) { |
234 | for (var U in P) { |
235 | if (U && P[U]) { |
236 | V.push('"' + U + '":"' + P[U] + '"') |
237 | } |
238 | } |
239 | } else { |
240 | for (var U in T) { |
241 | if (U && T[U]) { |
242 | V.push('"' + U + '":"' + T[U] + '"') |
243 | } |
244 | } |
245 | } |
246 | try { |
247 | var Q = MPing.EventSeries.getSeries(); |
248 | if (Q) { |
249 | var W = JSON.parse(Q); |
250 | W.jdv = encodeURIComponent(e("__jdv")); |
251 | W.unpl = encodeURIComponent(e("unpl")); |
252 | W.mt_xid = encodeURIComponent(e("mt_xid")); |
253 | W.mt_subsite = encodeURIComponent(e("mt_subsite")) |
254 | } |
255 | var S = { |
256 | mt_subsite: encodeURIComponent(e("mt_subsite")), |
257 | __jdv: encodeURIComponent(e("__jdv")), |
258 | unpl: encodeURIComponent(e("unpl")), |
259 | __jda: encodeURIComponent(e("__jda")) |
260 | }; |
261 | Q = JSON.stringify(W); |
262 | V.push('"m_param":' + Q); |
263 | V.push('"SE":' + JSON.stringify(S)) |
264 | } catch (R) { |
265 | V.push('"m_param":null') |
266 | } |
267 | var M = "{" + V.join(",") + "}"; |
268 | var O = N.inteneUrl.split("?"); |
269 | var L = null; |
270 | if (O.length == 2) { |
271 | L = O[0] + "?" + O[1] + "¶ms=" + M |
272 | } else { |
273 | L = O[0] + "?params=" + M |
274 | } |
275 | return L |
276 | } |
277 | |
278 | function y(L) { |
279 | return "intent://m.jd.com/#Intent;scheme=" + L + ";package=com.jingdong.app.mall;end" |
280 | } |
281 | |
282 | function n(L) { |
283 | if (L.openAppBtnId) { |
284 | B[L.openAppBtnId] = L; |
285 | G(L.openAppBtnId, L.openAppEventId); |
286 | bind(L.openAppBtnId, "click", function() { |
287 | var P = this.getAttribute("id"); |
288 | var M = B[P]; |
289 | if (!t) { |
290 | var N = document.createElement("iframe"); |
291 | N.id = iframe; |
292 | document.body.appendChild(N); |
293 | document.getElementById(iframe).style.display = "none"; |
294 | document.getElementById(iframe).style.width = "0px"; |
295 | document.getElementById(iframe).style.height = "0px"; |
296 | t = true |
297 | } |
298 | var O = M.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + M.cookieFlag : "downloadAppPlugIn_downCloseDate"; |
299 | l(O, Date.now() + "_2592000000", 60, "/", "m.jd.com"); |
300 | l(O, Date.now() + "_2592000000", 60, "/", "m.jd.hk"); |
301 | openApp(M, true) |
302 | }) |
303 | } |
304 | } |
305 | |
306 | function D(M) { |
307 | if (M.closePanelBtnId && M.closePanelId) { |
308 | B[M.closePanelBtnId] = M; |
309 | G(M.closePanelBtnId, M.closePanelEventId); |
310 | var Q = M.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + M.cookieFlag : "downloadAppPlugIn_downCloseDate"; |
311 | var O = e(Q); |
312 | var P = null; |
313 | if (O) { |
314 | P = O.split("_"); |
315 | if (P.length == 2) { |
316 | P[0] = parseInt(P[0], 10); |
317 | P[1] = parseInt(P[1], 10) |
318 | } else { |
319 | P = null |
320 | } |
321 | } |
322 | var L = Date.now(); |
323 | if (Html5Plus() || (!M.noRecord && P && P.length == 2 && (L - P[0]) < P[1])) { |
324 | document.querySelector("#" + M.closePanelId).style.display = "none"; |
325 | if (M.closeCallblack) { |
326 | var N = M.closeCallblackSource ? M.closeCallblackSource : null; |
327 | M.closeCallblack.call(N) |
328 | } |
329 | return |
330 | } else { |
331 | document.querySelector("#" + M.closePanelId).style.display = "block" |
332 | } |
333 | bind(M.closePanelBtnId, "click", function() { |
334 | var U = this.getAttribute("id"); |
335 | var R = B[U]; |
336 | var T = R.cookieFlag ? "downloadAppPlugIn_downCloseDate_" + R.cookieFlag : "downloadAppPlugIn_downCloseDate"; |
337 | if (!R.noRecord) { |
338 | l(T, Date.now() + "_259200000", 60, "/", "m.jd.com"); |
339 | l(T, Date.now() + "_259200000", 60, "/", "m.jd.hk") |
340 | } |
341 | document.querySelector("#" + R.closePanelId).style.display = "none"; |
342 | if (R.closeCallblack) { |
343 | var S = R.closeCallblackSource ? R.closeCallblackSource : null; |
344 | R.closeCallblack.call(S) |
345 | } |
346 | }) |
347 | } |
348 | } |
349 | |
350 | function Html5Plus() { // htmlplus |
351 | if (Navigator.indexOf("Html5Plus") >= 0) { |
352 | return true |
353 | } else { |
354 | return false |
355 | } |
356 | } |
357 | |
358 | function G(P, M) { |
359 | try { |
360 | var O = document.getElementById(P); |
361 | var L = O.className; |
362 | if (L) { |
363 | L = L + " J_ping" |
364 | } else { |
365 | L = "J_ping" |
366 | } |
367 | O.className = L; |
368 | O.setAttribute("report-eventid", M) |
369 | } catch (N) {} |
370 | } |
371 | |
372 | function C(L) { |
373 | var M = F(L); |
374 | n(M); |
375 | D(M) |
376 | } |
377 | Hquery.downloadAppPlugIn = C; |
378 | Hquery.downloadAppPlugInOpenApp = function(L) { |
379 | var M = F(L); |
380 | openApp(M); |
381 | } |
382 | }); |
这个虽然看起来比较繁琐,而且得着实的理解一下,但是一个比较全面的解决办法