工作较忙,暂做记录,稍后整理
需求:打开特定链接后能直接拉起本地 app,
实现效果:打开网页后,网页初始化时 js 代码 call native app, 系统显示是否打开相应 app 的弹窗
1. 参考 openinstall
实现方式:
<script type="text/javascript">
//OpenInstall初始化时将与OpenInstall服务器交互,应尽可能早的调用
/*web页面向app传递的json数据(json string/js Object),应用被拉起或是首次安装时,通过相应的android/ios api可以获取此数据*/
var data = OpenInstall.parseUrlParams();///openinstall.js中提供的工具函数,解析url中的所有查询参数
new OpenInstall({
/*appKey必选参数,平台为每个应用分配的ID*/
appKey : "mo3xfe",
_pkgId:"3559314099997391369",
/*自定义遮罩的html*/
//mask:function(){
// return "<div id='_shadow' style='position:fixed;left:0;top:0;background:rgba(0,255,0,0.5);filter:alpha(opacity=50);width:100%;height:100%;z-index:10000;'></div>"
//},
/*初始化完成的回调函数,可选*/
onready : function() {
/*在app已安装的情况尝试拉起app*/
this.schemeWakeup();
/*用户点击某个按钮时(假定按钮id为downloadButton),安装app*/
var m = this, button = document.getElementById("downloadButton");
button.style.visibility = "visible";
button.onclick = function() {
m.wakeupOrInstall();
return false;
}
}
}, data);
</script>
2. 最后采用的方案
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0,viewport-fit=cover">
<title>Sample for app deep link</title>
<style>
body {
text-align: center;
}
.btn {
word-break: normal;
tab-size: 4;
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
overflow-wrap: break-word;
background-repeat: no-repeat;
box-sizing: inherit;
margin: 0;
font: inherit;
overflow: visible;
border-style: none;
cursor: pointer;
align-items: center;
border-radius: 4px;
display: inline-flex;
flex: 0 0 auto;
font-weight: 500;
letter-spacing: .0892857143em;
justify-content: center;
outline: 0;
position: relative;
text-decoration: none;
text-indent: .0892857143em;
text-transform: uppercase;
transition-duration: .28s;
transition-property: box-shadow, transform, opacity;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
user-select: none;
vertical-align: middle;
white-space: nowrap;
color: #fff !important;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12) !important;
font-size: .875rem;
will-change: box-shadow;
background-color: #6200ea !important;
border-color: #6200ea !important;
height: 36px;
min-width: 64px;
padding: 0 16px;
}
</style>
<script type="text/javascript">
(function webpackUniversalModuleDefinition(root, factory) {
if (typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd)
define([], factory);
else if (typeof exports === 'object')
exports["AppDeepLink"] = factory();
else
root["AppDeepLink"] = factory();
})(window, function () {
return /******/ (function (modules) { // webpackBootstrap
/******/ // The module cache
/******/
var installedModules = {};
/******/
/******/ // The require function
/******/
function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/
if (installedModules[moduleId]) {
/******/
return installedModules[moduleId].exports;
/******/
}
/******/ // Create a new module (and put it into the cache)
/******/
var module = installedModules[moduleId] = {
/******/
i: moduleId,
/******/
l: false,
/******/
exports: {}
/******/
};
/******/
/******/ // Execute the module function
/******/
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/
module.l = true;
/******/
/******/ // Return the exports of the module
/******/
return module.exports;
/******/
}
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/
__webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/
__webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/
__webpack_require__.d = function (exports, name, getter) {
/******/
if (!__webpack_require__.o(exports, name)) {
/******/
Object.defineProperty(exports, name, {
enumerable: true,
get: getter
});
/******/
}
/******/
};
/******/
/******/ // define __esModule on exports
/******/
__webpack_require__.r = function (exports) {
/******/
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/
Object.defineProperty(exports, Symbol.toStringTag, {
value: 'Module'
});
/******/
}
/******/
Object.defineProperty(exports, '__esModule', {
value: true
});
/******/
};
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/
__webpack_require__.t = function (value, mode) {
/******/
if (mode & 1) value = __webpack_require__(value);
/******/
if (mode & 8) return value;
/******/
if ((mode & 4) && typeof value === 'object' && value && value.__esModule)
return value;
/******/
var ns = Object.create(null);
/******/
__webpack_require__.r(ns);
/******/
Object.defineProperty(ns, 'default', {
enumerable: true,
value: value
});
/******/
if (mode & 2 && typeof value != 'string')
for (var key in value) __webpack_require__.d(ns, key, function (key) {
return value[key];
}.bind(null, key));
/******/
return ns;
/******/
};
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/
__webpack_require__.n = function (module) {
/******/
var getter = module && module.__esModule ?
/******/
function getDefault() {
return module['default'];
} :
/******/
function getModuleExports() {
return module;
};
/******/
__webpack_require__.d(getter, 'a', getter);
/******/
return getter;
/******/
};
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/
__webpack_require__.o = function (object, property) {
return Object.prototype.hasOwnProperty.call(object, property);
};
/******/
/******/ // __webpack_public_path__
/******/
__webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/
return __webpack_require__(__webpack_require__.s = 0);
/******/
})
/************************************************************************/
/******/
([
/* 0 */
/***/
(function (module, exports, __webpack_require__) {
const agent = __webpack_require__(1);
const tool = __webpack_require__(2);
const browserGuideTpl =
'<div style=\'position:fixed;left:0;top:0;background:rgba(0,0,0,0.5);filter:alpha(opacity=50);width:100%;height:100%;z-index:10000;\'><div style=\'text-align:right;margin-top:1%;margin-right:5%;\'><img style=\'width:70%; margin:0 auto;\' src=\'https://res.zijizhang.com/img/android-brower-tip.png\'/></div></div>';
const platformUnSupportMsg = 'Do not support this platform';
const err = (errorHandler, msg) => {
if (errorHandler) {
return errorHandler(msg)
}
throw msg
};
const wakeUpOrInstallIos = (ios, onError) => {
if (!ios) {
return err(onError, platformUnSupportMsg)
}
const {
ulink,
scheme,
downloadUrl
} = ios;
if (ulink) {
return tool.loc(ulink)
}
let delayTs = 100;
if (scheme) {
delayTs = 2000;
if (agent.isWechat) {
tool.createEl(browserGuideTpl);
return
}
tool.loc(scheme);
// if (downloadUrl) {
// const openTs = +new Date();
// let timer = setTimeout(() => {
// const now = +new Date();
// if (now - openTs < 2200) {
// tool.loc(downloadUrl);
// }
// clearTimeout(timer)
// }, 2000);
// }
// return;
}
if (downloadUrl) {
if (!/itms-app|apps.apple.com/.test(downloadUrl)) {
tool.createEl(browserGuideTpl);
return
}
tool.delayRun(() => {
tool.loc(downloadUrl)
}, delayTs)
}
};
const wakeUpOrInstallAndroid = (android, onError) => {
if (!android) {
return err(onError, platformUnSupportMsg)
}
const {
scheme,
downloadUrl
} = android;
if (!scheme && !downloadUrl) {
return
}
if (agent.isWechat) {
if (scheme || (downloadUrl && !/app.qq.com/.test(downloadUrl))) {
tool.createEl(browserGuideTpl);
return
}
}
if (downloadUrl) {
let delayTs = agent.isMiui ? 1000 : 300;
tool.delayRun(() => {
tool.loc(downloadUrl)
}, delayTs)
}
if (scheme) {
tool.elClick(scheme);
}
};
const wakeUpOrInstall = (param) => {
const {
android,
ios,
onError
} = param || {};
if (agent.isIOS) {
return wakeUpOrInstallIos(ios, onError)
}
if (agent.isAndroid) {
return wakeUpOrInstallAndroid(android, onError)
}
err(onError, platformUnSupportMsg);
};
module.exports = {
wakeUpOrInstall
};
/***/
}),
/* 1 */
/***/
(function (module, exports) {
const UA = window.navigator.userAgent.toLowerCase();
module.exports = {
UA,
isAndroid: UA && /android|miui/.test(UA),
isIOS: UA && /iphone|ipad|ipod|ios/.test(UA),
isPC: UA && !exports.isAndroid && !exports.isIOS,
isMiui: UA && /miui/.test(UA),
isAlipay: UA && /alipayclient/.test(UA),
isWechat: UA && /(micromessenger)/.test(UA),
isWeibo: UA && /weibo/.test(UA),
isQQ: UA && /qq\/([\d\\.]+)*/.test(UA),
isFacebook: UA && /fban|fbav/.test(UA),
isInstagram: UA && /instagram/.test(UA),
};
/***/
}),
/* 2 */
/***/
(function (module, exports) {
const elClick = (url) => {
const el = document.createElement("a");
el.style.display = "none";
el.href = url;
document.body.appendChild(el);
el.click()
};
const frm = (url) => {
const el = document.createElement("iframe");
el.style.display = "none";
el.style.visibility = "hidden";
el.src = url;
document.body.appendChild(el)
};
const loc = (url) => {
window.location.href = url
};
const open = (url) => {
window.open(url)
};
const delayRun = (callback, timeout) => {
let r, i;
void 0 !== document.hidden ?
(r = "hidden", i = "visibilitychange") :
void 0 !== document.msHidden ?
(r = "msHidden", i = "msvisibilitychange") :
void 0 !== document.webkitHidden && (r = "webkitHidden", i =
"webkitvisibilitychange");
let timeoutTask = setTimeout(() => {
null == timeoutTask || document[r] || (callback(), timeoutTask =
null)
}, timeout);
let logic = () => {
null != timeoutTask && document[r] && (clearTimeout(timeoutTask),
timeoutTask = null, document.removeEventListener(i, logic))
};
i && document.addEventListener(i, logic, !1)
};
const createEl = (elStr) => {
let el = document.createElement('div');
el.innerHTML = elStr;
let currEl = el.children[0];
const evt = () => {
document.body.removeChild(el);
};
if (currEl.addEventListener) {
currEl.addEventListener('click', evt);
} else {
currEl.onclick = evt;
}
document.body.appendChild(el)
};
module.exports = {
elClick,
frm,
loc,
open,
delayRun,
createEl
};
/***/
})
/******/
]);
});
</script>
</head>
<body>
<button class="btn" onclick="download()">Wake up or install</button>
</body>
<script>
(function () {
download()
})();
function download() {
AppDeepLink.wakeUpOrInstall({
android: {
scheme: 'scheme',
downloadUrl: 'downloadUrl'
}
});
}
</script>
</html>