扫二维码下载apk并统计被扫描次数(及微信屏蔽下载解决方案)
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5395715.html
需求:想让用户扫描一个二维码就能下载APP,并统计被扫描次数。
两种实现方法:
1.一般我们用草料生成二维码,如果没有注册的话只能生成一个包含下载网址的静态码,没有统计功能,而且出了自己截图保存外,草料是不会保存你的二维码的。
如果注册草料后,可以选择生成活码。所谓活码,就是一个指向页面,然后通过这个指向页面,再到你的下载链接。这个指向页面内嵌了统计代码。你可以通过草料的统计功能,看你的二维码相关的扫描数据。
2.你的App下载地址,自己内嵌一个统计代码,这样来统计扫描数据,这样,你只要一个静态码就够了。不需要在草料注册,用户扫描二维码后,直接进入下载界面,没有中间的指向页面。
由于不希望自己的app投放到应用市场,因此微下载行不通。比如,把你的APK文件上传到腾讯的开放平台,申请通过后,会拿到一个移动推广链接,然后替换原来的“android下载”的链接(直接此文件生成一个二维码也行),这样用户就可以在微信中扫一扫直接下载了。
同时,一般用户用扫一扫,大多都用微信自带“扫一扫”工具,而微信打开的二维码页面,会自动屏蔽apk文件,所有显然把apk的url生成一个二维码,让用户扫一扫后就能直接下载,这样是行不通的。微信做了限制除了和微信有合作关系的应用才能使用微信扫描后直接下载apk,其他的应用只能点击微信右上角的菜单跳转到普通浏览器下载apk。
尝试:
用草料生成二维码:
“文件”方式生成二维码:上传需要下载的文件,生成二维码,扫描二维码跳转到它默认的模板页面,点击可下载该文件。但是不支持.apk这样的特殊格式。
“网址”方式生成二维码:直接将.apk的下载地址url生成二维码,扫描下载行不通。微信将其屏蔽了(QQ中的“扫一扫”功能是可以的,易信、360也都可以扫出来)。
所以最终采用第二种方法。
实现方案:
直接判断微信的ua,然后弹出一个遮罩提示用户在新的浏览器中打开下载,并且加关闭的按钮,类似于如图。

(1)在你的服务器上写一个下载详情页面,将app下载链接放上去。这里设计的是:使用JS+HTML+CSS结合的方式,用移动h5技术适配了手机版网页,不会在已进入微信就弹出提示它在新浏览器中打开,因为你还可以在这个页面里做一些提交表单查看信息等操作。只有用户点击应用下载链接才弹出遮罩提示跳转至新的浏览器下载,如图:

(2)把下载页面的URL地址,通过"草料二维码"生成一个二维码,如图:

(3)如果是在微信里扫一扫打开的,当用户点击“安卓版下载”的时候,就提示用户要在默认浏览器中打开,如图:

(4)其实扫描二维码,就是访问一个url,可以在后台统计url被访问的次数,就是扫描二维码的次数了。
贴出关键代码:
public class Counter{
private int count;
public Counter(){
this(0);
}
public Counter(int count){
this.count=count;
}
public void setCount(int count){
this.count=count;
}
public int getCount(){
return count;
}
public void add(int step){
count+=step;
}
}
/**
* 统计页面访问的次数,并在关闭应用时将其保存到文件,待下次启应用时读取次数。
* @author Joanna.Yan
*
*/
public class MyServletContextListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce){
System.out.println("====================helloapp application is Initialized.=========="); ServletContext context=sce.getServletContext(); try{
BufferedReader reader = new BufferedReader(
new InputStreamReader(context.getResourceAsStream("/count/count.txt"))); int count = Integer.parseInt(reader.readLine());
reader.close();
Counter counter = new Counter(count);
context.setAttribute("counter",counter);
}catch(IOException e){e.printStackTrace();}
} public void contextDestroyed(ServletContextEvent sce){
System.out.println("helloapp application is Destroyed.");
ServletContext context=sce.getServletContext();
Counter counter=(Counter)context.getAttribute("counter"); if(counter != null){
try{
String filepath = context.getRealPath("/count");
filepath = filepath+"/count.txt";
PrintWriter pw= new PrintWriter(filepath);
pw.println(counter.getCount());
pw.close();
}catch(IOException e){e.printStackTrace();};
}
}
}
web.xml中注册监听器:
<listener>
<listener-class>joanna.yan.listener.MyServletContextListener</listener-class>
</listener>
web.xml中注册servlet:
<servlet>
<servlet-name>QRCodeServlet</servlet-name>
<servlet-class>joanna.yan.servlet.QRCodeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>QRCodeServlet</servlet-name>
<url-pattern>/QRCode</url-pattern>
</servlet-mapping>
public class QRCodeServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("QRCodeServlet被访问了!");
ServletContext context=getServletContext();
Counter counter=(Counter) context.getAttribute("counter");
if(counter==null){
counter=new Counter(1);
context.setAttribute("counter", counter);
}
counter.add(1);
System.out.println("被扫描的次数:"+counter.getCount());
resp.sendRedirect(""+req.getContextPath()+"/apkdownload.jsp");
}
}
设置适配移动端屏幕,禁止浏览器的缩放功能:
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0">
CSS+JS:
<style type="text/css">
#weixin-tip{display:none;position:fixed;left:0;top:0;background:rgba(0,0,0,0.8);filter:alpha(opacity=80);width:100%;height:100%;z-index:100;}
#weixin-tip p{text-align:center;margin-top:10%;padding:0 5%;position:relative;}
#weixin-tip .close{color:#fff;padding:5px;font:bold 20px/24px simsun;text-shadow:0 1px 0 #ddd;position:absolute;top:0;left:5%;}
</style> <script type="text/javascript">
var is_weixin = (function(){return navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1;})();
window.onload = function() {
var winHeight = typeof window.innerHeight != 'undefined' ? window.innerHeight : document.documentElement.clientHeight; //兼容IOS,不需要的可以去掉
var btn = document.getElementById('J_weixin');
var tip = document.getElementById('weixin-tip');
var close = document.getElementById('close');
if (is_weixin) {
btn.onclick = function(e) {
tip.style.height = winHeight + 'px'; //兼容IOS弹窗整屏
tip.style.display = 'block';
return false;
};
close.onclick = function() {
tip.style.display = 'none';
};
}
};
</script>
....你的网页代码......
<div id="weixin-tip">
<p>
<img alt="微信打开" src="img/warn.png">
<span id="close" title="关闭" class="close">X</span>
</p>
</div>
如果此文对您有帮助,微信打赏我一下吧~

扫二维码下载apk并统计被扫描次数(及微信屏蔽下载解决方案)的更多相关文章
- 网页授权——扫二维码获取openid
最近做微信公众平台开发项目时遇到这样一个功能需求:生成一个特定url的二维码,用户扫描二维码后跳转到这个url指定的页面,并在这个页面获得用户的openid.这个功能主要涉及到两方面的技术:生成二维码 ...
- MISC-吹着贝斯扫二维码
题目 [安洵杯 2019]吹着贝斯扫二维码 解压附件,有36个文件和一个压缩包,压缩包带密码和备注 分析 文件类型 随便打开一个不明文件,是jpg图片啊(FF D8 FF) 改一个试试,有一个小块二维 ...
- android DialogFragment 实现Dialog展示扫二维码图片展示
近期开发项目,做个按钮点击弹出展示微信二维码关注微信公众号的展示框,于是想到DialogFragment,期间对Dialog的title的底框字体颜色做出相关设置,记录如下: 下面是 DialogFr ...
- 很多人很想知道怎么扫一扫二维码就能打开网站,就能添加联系人,就能链接wifi,今天说下这些格式,明天做个demo
有些功能部分手机不能使用,网站,通讯录,wifi基本上每个手机都可以使用. 在看之前你可以扫一扫下面几个二维码先看看效果: 1.二维码生成 网址 (URL) 包含网址的 二维码生成 是大家平时最常接触 ...
- vue 实现 扫二维码 功能
前段时间一直在研究,如何通过 vue 调用 相机 实现 扫一扫的功能,但是查看文档发现,需要获取 getUserMedia 的属性值,但存在兼容性问题. 退而求其次,通过 h5plus 来实现. 1. ...
- 扫二维码登录实现原理,php版
基础的逻辑图就是这样,但是实际情况还是有几种可能 比如QQ登录,微信登录,微博登录,基本设计都差不多,根据实际情况会有一些差异 问题是,如果设计合理的接口在保证数据的安全性和快速性 设计到的技术不复杂 ...
- Android二维码的生成,解析以及扫描功能
<1> 布局只有2个按钮,实现生成二维码和解析二维码 <Button android:layout_width="wrap_content" android:la ...
- uniapp 扫二维码跳转
在h5和wxapp中 生成qrcode的组件 https://ext.dcloud.net.cn/plugin?id=39 wx小程序扫二位码文档 生成链接时 computed: { ...mapSt ...
- Android | 教你如何开发扫二维码功能
前言 最近要做一个停车场扫码收费的app,在网上搜了一圈,首先接触到了ZXing,上手试了下,集成过程不复杂,但是感觉效果欠佳,比如距离稍微远点儿就扫不出来了,另外角度对的不好,反光或者光线比较暗 ...
随机推荐
- “.Net 社区虚拟大会”(dotnetConf) 2016 Day 3 Keynote: Scott Hanselman
美国时间 6月7日--9日,为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开,美国时间6.9 是第三天, Scott Hanselman 做Keynote.今天主题围绕的是.NET ...
- HTML5 sessionStorage会话存储
sessionStorage 是HTML5新增的一个会话存储对象,用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据.本篇主要介绍 sessionStorage(会话存储) ...
- Matlab 高脚杯模型切片
前言:此文为去年我替人做的一个课题,觉得比较简洁,图形也比较美观,因此放在博文里 数据源我放到了百度云盘高脚杯数据源 有兴趣的可以下载数据,跑程序试一下.也可以单独看看代码,看下实现过程. 主函数 % ...
- 两个 viewports 的故事-第二部分
原文链接:A tale of two viewports — part two 译者:nzbin 在这个迷你系列中,我将解释 viewports 和各种重要元素的宽度是如何工作的,比如说 <ht ...
- 读书笔记汇总 - SQL必知必会(第4版)
本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...
- trigger事件模拟
事件模拟trigger 在操作DOM元素中,大多数事件都是用户必须操作才会触发事件,但有时,需要模拟用户的操作,来达到效果. 需求:页面初始化时触发搜索事件并获取input控件值,并打印输出(效果图如 ...
- Linux设备管理(五)_写自己的sysfs接口
我们在Linux设备管理(一)_kobject, kset,ktype分析一文中介绍了kobject的相关知识,在Linux设备管理(二)_从cdev_add说起和Linux设备管理(三)_总线设备的 ...
- 搭建一套自己实用的.net架构(3)续 【ORM Dapper+DapperExtensions+Lambda】
前言 继之前发的帖子[ORM-Dapper+DapperExtensions],对Dapper的扩展代码也进行了改进,同时加入Dapper 对Lambda表达式的支持. 由于之前缺乏对Lambda的知 ...
- 微信小程序之用户数据解密(七)
[未经作者本人同意,请勿以任何形式转载] 经常看到有点的小伙伴在群里问小程序用户数据解密流程,所以打算写一篇关于小程序用户敏感数据解密教程: 加密过程微信服务器完成,解密过程在小程序和自身服务器完成, ...
- 【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持
前言 在之前介绍的流量劫持文章里,曾提到一种『HTTPS 向下降级』的方案 -- 将页面中的 HTTPS 超链接全都替换成 HTTP 版本,让用户始终以明文的形式进行通信. 看到这,也许大家都会想到一 ...