通过浏览器判断是否安装APP
场景
求在分享出来的h5页面中,有一个立即打开的按钮,如果本地安装了我们的app,那么点击就直接唤本地app,如果没有安装,则跳转到下载。
移动端
判断本地是否安装了app
首先我们可以确认的是,在浏览器中无法明确的判断本地是否安装了app。因此我们必须采取一些取巧的思路来解决这个问题。
我们能够很容易想到,采用设置一个延迟定时器setTimeout的方式,第一时间尝试唤起app,如果200ms没有唤起成功,则默认本地没有安装app,200ms以后,将会触发下载行为。
结合这个思路,我们来全局考虑一下这个需求应该采用什么样的方案来实现它。
使用location.href的同学可能会面临一个担忧,在有的浏览器中,当我们尝试激活schema link的时候,若本地没有安装app,则会跳转到一个浏览器默认的错误页面去了。因此大多数人采用的解决方案都是使用iframe
后来观察了网易新闻,今日头条,YY等的实现方案,发现大家都采用的是iframe来实现。好吧,面对这种情况,只能屈服。
整理一下目前的思路,得到下面的解决方案
var url = {open: 'app://xxxxx',down: 'xxxxxxxx'};var iframe = document.createElement('iframe');
var body = document.body;
iframe.style.cssText='display:none;width=0;height=0';
var timer = null;// 立即打开的按钮
var openapp = document.getElementById('openapp');
openapp.addEventListener('click', function() {if(/MicroMessenger/gi.test(navigator.userAgent) {// 引导用户在浏览器中打开}) else{body.appendChild(iframe);iframe.src = url.open;timer = setTimeout(function() {wondow.location.href = url.down;}, 500);}
}, false)
一测试,就发现简单的这样实现有许多的问题。
第一个问题
当页面成功唤起app之后,我们再切换回来浏览器,发现跳转到了下载页面。
为了解决这个问题,发现各个公司都进行了不同方式的尝试。
也是历经的很多折磨,发现了几个比较有用的事件。
pageshow: 页面显示时触发,在load事件之后触发。需要将该事件绑定到window上才会触发
pagehide: 页面隐藏时触发
visibilitychange: 页面隐藏没有在当前显示时触发,比如切换tab,也会触发该事件
document.hidden 当页面隐藏时,该值为true,显示时为false
由于各个浏览器的支持情况不同,我们需要将这些事件都给绑定上,即使这样,也不一定能够保证所有的浏览器都能够解决掉这个小问题,实在没办法的事情就不管了。
因此需要扩充一下上面的方案,当本地app被唤起,则页面会隐藏掉,就会触发pagehide与visibilitychange事件
$(document).on('visibilitychange webkitvisibilitychange', function() {var tag = document.hidden || document.webkitHidden;if (tag) {clearTimeout(timer);}
}) $(window).on('pagehide', function() {clearTimeout(timer);
})
第二个问题
ios9的Safari,根本不支持通过iframe跳转到其他页面去。也就是说,在safari下,我的整体方案被全盘否决!
于是我就只能尝试使用location.href的方式,这个方式能够唤起app,但是有一个坑爹的问题,使用schema协议唤起app会有弹窗而不会直接跳转去app!甚至当本地没有app时,会被判断为链接无效,然后还有一个弹窗。
这个弹窗会造成什么问题呢?如果用户不点确认按钮,根据上面的逻辑,这个时候就会发现页面会自动跳转到下载去了。而且无效的弹窗提示在用户体验上是不允许出现的。
好吧,继续扒别人的代码,看看别人是如何实现的。然后我又去观摩了其他公司的实现结果,发现网易新闻,今日头条都可以在ios直接从微信中唤起app。真是神奇了,可是今日头条在Android版微信上也没办法直接唤起的,他们在Android上都是直接到腾讯应用宝的下载里去。所以按道理来说这不是添加了白名单。
为了找到这个问题的解决方案,我在网易新闻的页面中扒出了他们的代码,并整理如下,添加了部分注释
window.NRUM = window.NRUM || {};
window.NRUM.config = {key:'27e86c0843344caca7ba9ea652d7948d',clientStart: +new Date()
};
(function() {var n = document.getElementsByTagName('script')[0],s = document.createElement('script'); s.type = 'text/javascript';s.async = true;s.src = '//nos.netease.com/apmsdk/napm-web-min-1.1.3.js';n.parentNode.insertBefore(s, n);
})();(function(window,doc){ // http://apm.netease.com/manual?api=webNRUM.mark && NRUM.mark('pageload', true) var list = []var config = null// jsonpfunction jsonp(a, b, c) {var d;d = document.createElement('script');d.src = a;c && (d.charset = c);d.onload = function() {this.onload = this.onerror = null;this.parentNode.removeChild(this);b && b(!0);};d.onerror = function() {this.onload = this.onerror = null;this.parentNode.removeChild(this);b && b(!1);};document.head.appendChild(d);};function localParam(search,hash){search = search || window.location.search;hash = hash || window.location.hash;var fn = function(str,reg){if(str){var data = {};str.replace(reg,function( $0, $1, $2, $3 ){data[ $1 ] = $3;});return data;}}return {search: fn(search,new RegExp( "([^?=&]+)(=([^&]*))?", "g" ))||{},hash: fn(hash,new RegExp( "([^#=&]+)(=([^&]*))?", "g" ))||{}};} jsonp('http://active.163.com/service/form/v1/5847/view/1047.jsonp')window.search = localParam().searchwindow._callback = function(data) {window._callback = nulllist = data.listif(search.s && !!search.s.match(/^wap/i)) {config = list.filter(function(item){return item.type === 'wap'})[0]return}config = list.filter(function(item){return item.type === search.s})[0]}var isAndroid = !!navigator.userAgent.match(/android/ig),isIos = !!navigator.userAgent.match(/iphone|ipod/ig),isIpad = !!navigator.userAgent.match(/ipad/ig),isIos9 = !!navigator.userAgent.match(/OS 9/ig),isYx = !!navigator.userAgent.match(/MailMaster_Android/i),isNewsapp = !!navigator.userAgent.match(/newsapp/i),isWeixin = (/MicroMessenger/ig).test(navigator.userAgent),isYixin = (/yixin/ig).test(navigator.userAgent),isQQ = (/qq/ig).test(navigator.userAgent),params = localParam().search,url = 'newsapp://',iframe = document.getElementById('iframe');var isIDevicePhone = (/iphone|ipod/gi).test(navigator.platform);var isIDeviceIpad = !isIDevicePhone && (/ipad/gi).test(navigator.platform);var isIDevice = isIDevicePhone || isIDeviceIpad;var isandroid2_x = !isIDevice && (/android\s?2\./gi).test(navigator.userAgent);var isIEMobile = !isIDevice && !isAndroid && (/MSIE/gi).test(navigator.userAgent);var android_url = (!isandroid2_x) ? "http://3g.163.com/links/4304" : "http://3g.163.com/links/6264";var ios_url = "http://3g.163.com/links/3615";var wphone_url = "http://3g.163.com/links/3614";var channel = params.s || 'newsapp'// 判断在不同环境下app的urlif(params.docid){if(params['boardid'] && params['title']){url = url + 'comment/' + params.boardid + '/' + params.docid + '/' + params.title}else{url = url + 'doc/' + params.docid}}else if(params.sid){url = url + 'topic/' + params.sid}else if(params.pid){var pid = params.pid.split('_')url = url + 'photo/' + pid[0] + '/' + pid[1]}else if(params.vid){url = url + 'video/' + params.vid}else if(params.liveRoomid){url = url + 'live/' + params.liveRoomid}else if(params.url){url = url + 'web/' + decodeURIComponent(params.url)}else if(params.expertid){url = url + 'expert/' + params.expertid}else if(params.subjectid){url = url + 'subject/' + params.subjectid}else if(params.readerid){url = url + 'reader/' + params.readerid}else{url += 'startup'}if(url.indexOf('?') >= 0){url += '&s=' + (params.s || 'sps')}else{url += '?s=' + (params.s || 'sps')} // ios && 易信 用iframe 打开if((isIos||isIpad) && navigator.userAgent.match(/yixin/i)) {document.getElementById('iframe').src = url;}var height = document.documentElement.clientHeight;// 通常情况下先尝试使用iframe打开document.getElementById('iframe').src = url;// 移动端浏览器中,将下载页面显示出来if(!isWeixin && !isQQ && !isYixin && !isYx){document.querySelector('.main-body').style.display = 'block'if(isIos9){document.querySelector('.main-body').classList.add('showtip')}setTimeout(function(){document.body.scrollTop = 0},200)}else{document.getElementById('guide').style.display = 'block'} // Forward To Redirect Url// Add by zhanzhixiang 12/28/2015if (params.redirect) {var redirectUrl = decodeURIComponent(params.redirect);if ( typeof(URL) === 'function' && new URL(redirectUrl).hostname.search("163.com") !== -1) {window.location.href = redirectUrl;} else if (redirectUrl.search("163.com") !== -1){window.location.href = redirectUrl;};}// Forward To Redirect Url Endif ((isWeixin || isQQ) && isAndroid) {window.location.href = 'http://a.app.qq.com/o/simple.jsp?pkgname=com.netease.newsreader.activity&ckey=CK1331205846719&android_schema=' + url.match(/(.*)\?/)[1]}if(isIos||isIpad){document.getElementById("guide").classList.add('iosguideopen')}else if (isAndroid){document.getElementById("guide").classList.add('androidguideopen')}else{// window.location.href = 'http://www.163.com/newsapp'}document.getElementById('link').addEventListener('click', function(){// 统计neteaseTracker && neteaseTracker(false,'http://sps.163.com/func/?func=downloadapp&modelid='+modelid+'&spst='+spst+'&spsf&spss=' + channel,'', 'sps' ) if (config) {android_url = config.android}if (config && config.iOS) {ios_url = config.iOS}if(isWeixin || isQQ){return}var msg = isIDeviceIpad ? "检测到您正在使用iPad, 是否直接前往AppStore下载?" : "检测到您正在使用iPhone, 是否直接前往AppStore下载?";if (isIDevice){window.location = ios_url;return;}else if(isAndroid){// uc浏览器用iframe唤醒if(navigator.userAgent.match(/ucbrowser|yixin|MailMaster/i)){document.getElementById('iframe').src = url;} else {window.location.href = url;}setTimeout(function(){if(document.webkitHidden) {return}if (confirm("检测到您正在使用Android 手机,是否直接下载程序安装包?")) {neteaseTracker && neteaseTracker(false,'http://sps.163.com/func/?func=downloadapp_pass&modelid='+modelid+'&spst='+spst+'&spsf&spss=' + channel,'', 'sps' )window.location.href = android_url;} else {neteaseTracker && neteaseTracker(false,'http://sps.163.com/func/?func=downloadapp_cancel&modelid='+modelid+'&spst='+spst+'&spsf&spss=' + channel,'', 'sps' )}},200)return;}else if(isIEMobile){window.location = wphone_url;return;}else{window.open('http://www.163.com/special/00774IQ6/newsapp_download.html');return;}}, false)setTimeout(function(){if(isIDevice && params.notdownload != 1 && !isNewsapp && !isIos9){document.getElementById('link').click()}}, 1000)
})(window,document);
虽然有一些外部的引用,和一些搞不懂是干什么用的方法和变量,但是基本逻辑还是能够看明白。好像也没有什么特别的地方。研究了许久,看到了一个jsonp请求很奇特。这是来干嘛用的?
于是费尽千辛万苦,搜索了很多文章,最终锁定了一个关键的名词 Universal links。
如果我早知道这个名词,那么问题就不会变的那么束手无策。所以这个东西是什么呢?
Apple为iOS 9发布了一个所谓的通用链接的深层链接特性,即Universal links。虽然它并不完美,但是这一发布,让数以千计的应用开发人员突然意识到自己的应用体验被打破。
Universal links,一种能够方便的通过传统的HTTP/HTTPS 链接来启动App,使用相同的网址打开网站和App。
关于这个问题的提问与universal links的介绍 点击这里查看
ios9推行的一个新的协议!
关于本文的这个问题,国内的论坛有许许多多的文章来解决,但是提到universal links的文章少之又少,而我想吐槽的是,我们的ios开发也尼玛不知道这个名词,搞什么鬼。他改变了用户体验的关键在于,微信没有屏蔽这个协议。因此如果我们的app注册了这个协议,那么我们就能够从微信中直接唤起app。
这个时候我就发现,上面贴的网易新闻代码中的jsonp请求的内容,就是这个协议必须的一个叫做apple-app-site-association
的JSON文件
{"applinks": {"apps": [ ],"details": {"TEAM-IDENTIFIER.YOUR.BUNDLE.IDENTIFIER": {"paths": ["*"]}}}
}
大家可以直接访问这个链接,查看里面的内容
http://active.163.com/service/form/v1/5847/view/1047.jsonp
至于universal links具体如何实现,让ios的同学去搞定吧,这里提供两个参考文章
http://www.cocoachina.com/bbs/read.php?tid-1486368.html
https://blog.branch.io/how-to-setup-universal-links-to-deep-link-on-apple-ios-9
支持了这个协议之后,我们又可以通过iframe来唤起app了,因此基本逻辑就是这样了。最终的调研结果是
没有完美的解决方案
就算是网易新闻,这个按钮在使用过程中也会有一些小bug,无法做到完美的状态。
因为我们面临许多没办法解决的问题,比如无法真正意义上的判断本地是否安装了app,pageshow,pagehide并不是所有的浏览器都支持等。很多其他博客里面,什么计算时间差等方案,根!本!没!有!用!我还花了很久的时间去研究这个方案。
老实说,从微信中跳转到外部浏览器,并不是一个好的解决方案,这样会导致很多用户流失,因此大家都在ios上实现了universal links,而我更加倾向的方案是知乎的解决,他们从设计上避免了在一个按钮上来判断这个逻辑,而采用了两个按钮的方式。
网易新闻的逻辑是,点击打开会调整到一个下载页面,这个下载页面一加载完成就尝试打开app,如果打开了就直接跑到app里面去了,如果没有就在页面上有一个立即下载的按钮,按钮行只有下载处理。
如何唤起本地app
想要实现这个需求,肯定是必须要客户端同学的配合才行,因此我们不用知道所有的实现细节,我们从前端角度思考看这个问题,需要知道的一点是,ios与Android都支持一种叫做schema协议的链接。比如网易新闻客户端的协议为
newsapp://xxxxx
当然,这个协议不需要我们前端去实现,我们只需要将协议放在a标签的href属性里,或者使用location.href与iframe来实现激活这个链接。而location.href与iframe是解决这个需求的关键。
在ios中,还支持通过smart app banner
来唤起app,即通过一个meta标签,在标签里带上app的信息,和打开后的行为,代码形如
<meta name="apple-itunes-app" content="app-id=1023600494, app-argument=tigerbrokersusstock://com.tigerbrokers.usstock/post?postId=7125" />
我们还需要知道的一点是,微信里屏蔽了schema协议。除非你是微信的合作伙伴之类的,他们专门给你配置进白名单。否则我们就没办法通过这个协议在微信中直接唤起app。
因此我们会判断页面场景是否在微信中,如果在微信中,则会提示用户在浏览器中打开。
转载自浏览器判断是否安装APP - 你我博客
PC端
如果想在web网页中判断PC客户端是否安装了某个软件,可以试用标准的浏览器特性:检查浏览器是否支持自定义协议处理程序。
根据网上各路大神的代码总结了一下在IE和360浏览器下的靠谱方案,chrome,firefox需要插件配合目前无法有效解决。
IE内核可以判断ActiveXObject对象存在时,去new window.ActiveXObject("TimwpDll.TimwpCheck"),用try catch包裹,如果没有安装QQ,会走catch
360浏览器,首先要判断是谷歌内核,然后navigator.mimeTypes属性有一个特定值"application/vnd.chromium.remoting-viewer")只在360浏览器有,检测出360浏览器之后,遍历navigator.plugins对象,取item的name属性值等于"Tencent QQ"
下面贴出代码,由于只能检测IE/360 ,其他浏览器一律忽略返回true
function checkQQInstall() {if ('ActiveXObject' in window) {try {//IE判断是否安装QQnew window.ActiveXObject('TimwpDll.TimwpCheck');console.log('QQ已安装!');return true;} catch (e) {console.warn('没有可支持的插件!');return false;}}let isChrome = window.navigator.userAgent.toLowerCase().indexOf('chrome') > 0;if (!isChrome) return true;// 360function findPlugins() {var res = false;var plugins = navigator.plugins;for (var i = 0; i < plugins.length; i++) {var plugin_name = plugins[i].name;// console.log(plugin_name);if (plugin_name == 'Tencent QQ') {// alert(plugin_name+" 已找到");res = true;break;}}return res;}function _mime(option, value) {var mimeTypes = navigator.mimeTypes;for (var mt in mimeTypes) {if (mimeTypes[mt][option] == value) {return true;}}return false;}var is360 = _mime('type', 'application/vnd.chromium.remoting-viewer');if (isChrome && is360) {console.log('检测到是360浏览器');if (findPlugins()) {console.log('QQ已安装!');return true;} else {console.warn('请安装QQ!');return false;}}//既不是IE也不是360也返回truereturn true;
}
相关文章:
通过浏览器判断是否安装APP
场景 求在分享出来的h5页面中,有一个立即打开的按钮,如果本地安装了我们的app,那么点击就直接唤本地app,如果没有安装,则跳转到下载。 移动端 判断本地是否安装了app 首先我们可以确认的是,在浏览器中无…...

vivado Revision Control
2020.2 只需要git 管理 prj.xpr 和 prj.srcs/ https://china.xilinx.com/video/hardware/ip-revision-control.html Using Vivado Design Suite with Revision Control https://www.xilinx.com/video/hardware/vivado-design-suite-revision-control.html http://www.xi…...

【AI视野·今日Robot 机器人论文速览 第七十三期】Tue, 9 Jan 2024
AI视野今日CS.Robotics 机器人学论文速览 Tue, 9 Jan 2024 Totally 40 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers Digital Twin for Autonomous Surface Vessels for Safe Maritime Navigation Authors Daniel Menges, Andreas Von Brandis, A…...
java解析json复杂数据的第四种思路
文章目录 一、概述二、数据预览1. 接口json数据 三、代码实现1. 核心代码2. 字符串替换结果3. 运行结果 一、概述 接前两篇 java解析json复杂数据的两种思路 java解析json复杂数据的第三种思路 我们已经有了解析json数据的几种思路,下面介绍的方法是最少依赖情况下…...

【不用找素材】ECS 游戏Demo制作教程(1) 1.15
一、项目设置 版本:2022.2.0f1 (版本太低的话会安装不了ECS插件) 模板选择3D URP 进来后移除URP(因为并不是真的需要,但也不是完全不需要) Name: com.unity.entities.graphics Version: 1.0.0-exp.8 点击…...
Mysql的in与exits
Mysql的in与exits IN和EXISTS是MySQL中用于子查询的两种不同的条件操作符。它们在使用和实现上有一些区别。 IN 操作符: IN操作符用于判断一个值是否在一个集合内。它可以用于子查询中,检查主查询的某一列是否在子查询返回的结果集中。 SELECT colum…...

浅谈对Maven的理解
一、什么是Maven Maven——是Java社区事实标准的项目管理工具,能帮你从琐碎的手工劳动中解脱出来,帮你规范整个组织的构建系统。不仅如此,它还有依赖管理、自动生成项目站点等特性,已经有无数的开源项目使用它来构建项目并促进团队…...

【算法实验】实验2
实验2-1 二分搜索 【问题描述】给定一个包含 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,要求实现搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。题目保证nums中的所有元素都不重复。 【…...
杂记:使用 mac 和 windows 以及编辑器的总结
Chrome 扩展 Grammarly 语法检查 DM Integration Module idm 下载扩展 JSON Formatter json 格式化查看 uBlock Origin Ad block 油猴 任意网站都可以使用的脚本管理工具 Mac 快捷键整理 截图到剪贴板 shift command control 4 (不按 shift 存储为文件) 切换输入法…...

vue2使用qiankun微前端(跟着步骤走可实现)
需求:做一个vue2的微前端,以vue2为主应用,其他技术栈为子应用,比如vue3,本文章只是做vue2一套的微前端应用实现,之后解决的一些问题。vue3子应用可以看我另一篇vue3vitets实现qiankun微前端子应用-CSDN博客…...

1.C语言基础知识
这里写目录标题 1.第一个C语言程序2.注释3.标识符4.关键字5.数据类型6.变量7.常量8.运算符9.输入输出输入输出 1.第一个C语言程序 C语言的编程框架 #include <stdio.h> int main() {/* 我的第一个 C 程序 */printf("Hello, World! \n");return 0; }2.注释 单行…...

路由黑洞和黑洞路由的区别
路由黑洞: 路由黑洞是一种现象,一般是在网络边界做汇总回程路由的时候产生的一种不太愿意出现的现象,就是汇总的时候有时会有一些不在内网中存在的网段,但是又包含在汇总后的网段中,如果在这个汇总的边界设备上同时还配…...
Golang 如何基于现有的 context 创建新的 context?
目录 基于现有的 context 创建新的 context 现有创建方法的问题 Go 1.21 中的 context.WithoutCancel 函数 Go 版本低于 1.21 该怎么办? 在 Golang 中,context 包提供了创建和管理上下文的功能。当需要基于现有的 context.Context 创建新的 context …...
【学习笔记】[AGC063E] Child to Parent
提供一个多项式做法。 分别设 f u , i , g u , i f_{u,i},g_{u,i} fu,i,gu,i表示以 u u u为根时, a u i a_ui aui和 a u ≥ i a_u\ge i au≥i的方案数,合并子树 v v v时,转移如下: f u , i ∑ f u , i − k r g v . k…...
sar 运行出错
手机上使用sar 使用sar工具报错 / # sar -I SUM 1 1 Cannot find the data collector (sadc) exec: No such file or directory Inconsistent input data解决方法:需要将 sadc sadf sar 三个bin同时推到/usr/bin/目录下 / # sar -I SUM 1 2 Linux 5.15.104-ab558…...
UE5 C++的TCP服务器与客户端
客户端.h 需要在Build.cs中加入模块:"Networking","Sockets","Json","JsonUtilities" // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include…...

nginx+lua配置,一个域名配置https,docker集群使用
没安装kua的先安装lua 没有resty.http模块的,许配置 nginxlua配置,一个域名配置https,docker集群使用,一个域名配置https管理整个集群 lua做转发(方向代理) 1、ad_load.lua文件 ngx.header.content_typ…...
jQuery 正则表达式 验证表单
文章目录 简介:什么是正则表达式以及作用:●文本框内容的验证:代码演示示例: 简介: jQuery Form插件是一个优秀的Ajax表单插件,可以非常容易地、无侵入地升级HTML表单以支持Ajax。jQuery Form有两个核心方法…...

如何使用SVN查看旧版本
和目录 第一步:打开SVN客户端 第二步:浏览历史版本 第三步:还原历史版本 结论 Subversion (缩写为SVN)是一种常用的版本控制系统,它可以帮助团队协作开发软件项目。除了基本的版本控制功能外,SVN还提供了许多其他功…...

使用 GitHub 远程仓库
使用 GitHub 远程仓库 GitHub 是最大的 Git 版本库托管商,是成千上万的开发者和项目能够合作进行的中心。 大部分 Git 版本库都托管在 GitHub,很多开源项目使用 GitHub 实现 Git 托管、问题追踪、代码审查以及其它事情。本篇文章主要带大家上手 GitHub …...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...

算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...

Element-Plus:popconfirm与tooltip一起使用不生效?
你们好,我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip,产品要求是两个需要结合一起使用,也就是鼠标悬浮上去有提示文字,并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...

python可视化:俄乌战争时间线关键节点与深层原因
俄乌战争时间线可视化分析:关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一,自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具,系统分析这场战争的时间线、关键节点及其背后的深层原因,全面…...