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中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤