Android H5拉起 app

2024-05-28 11:38
文章标签 android app h5 拉起

本文主要是介绍Android H5拉起 app,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

工作较忙,暂做记录,稍后整理

需求:打开特定链接后能直接拉起本地 app,

实现效果:打开网页后,网页初始化时 js 代码 call native app, 系统显示是否打开相应 app 的弹窗

H5 拉起 App

  • 1. 参考 `openinstall` 实现方式:
  • 2. 最后采用的方案
  • 3. 参考链接

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>
  • 最后使用的 js 代码

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();elseroot["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>

3. 参考链接

  • APP唤起那点破事

  • h5唤起app – 三种唤起方案

  • H5唤起APP指南(附开源唤端库 – callapp-lib)

    • 不能在页面刚打开时自动唤醒,我已实现,回头建议加入此 lib
  • h5 唤起 APP

  • H5 唤醒 APP 解决方案

  • H5唤醒App方式汇总

  • 移动浏览器H5页面通过scheme打开本地应用

  • h5启动原生APP总结

  • 移动浏览器H5页面通过scheme打开本地应用

  • js 通过schema协议拉起本地app

  • 集成 openinstall 之后它们给的测试链接,可参考页面的 js 代码

这篇关于Android H5拉起 app的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1010461

相关文章

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

2025最新版Android Studio安装及组件配置教程(SDK、JDK、Gradle)

《2025最新版AndroidStudio安装及组件配置教程(SDK、JDK、Gradle)》:本文主要介绍2025最新版AndroidStudio安装及组件配置(SDK、JDK、Gradle... 目录原生 android 简介Android Studio必备组件一、Android Studio安装二、A

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class