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实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

Android逆向(反调,脱壳,过ssl证书脚本)

文章目录 总结 基础Android基础工具 定位关键代码页面activity定位数据包参数定位堆栈追踪 编写反调脱壳好用的脚本过ssl证书校验抓包反调的脚本打印堆栈bilibili反调的脚本 总结 暑假做了两个月的Android逆向,记录一下自己学到的东西。对于app渗透有了一些思路。 这两个月主要做的是代码分析,对于分析完后的持久化等没有学习。主要是如何反编译源码,如何找到