扫二维码下载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,上手试了下,集成过程不复杂,但是感觉效果欠佳,比如距离稍微远点儿就扫不出来了,另外角度对的不好,反光或者光线比较暗 ...
随机推荐
- Shell碎碎念
1. 字符串如何大小写转换 str="This is a Bash Shell script." 1> tr方式 newstr=`tr '[A-Z]' '[a-z]' < ...
- Hbase的伪分布式安装
Hbase安装模式介绍 单机模式 1> Hbase不使用HDFS,仅使用本地文件系统 2> ZooKeeper与Hbase运行在同一个JVM中 分布式模式– 伪分布式模式1> 所有进 ...
- Anders Hejlsberg 技术理想架构开发传奇
Anders Hejlsberg(安德斯-海森博格) 坐在自己的办公室,双眼直直的盯着前方.他要做一个决定,决定自己未来的命运和理想.这是1996年一个普通的下午,几个小时前,他刚与比尔-盖茨结束了 ...
- JQuery(2)
JQuery下拉框操作: 取值赋值操作 body代码: <select id="sel"> <option value="北京">北京& ...
- 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)
建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...
- 手把手教你写一个RN小程序!
时间过得真快,眨眼已经快3年了! 1.我的第一个App 还记得我14年初写的第一个iOS小程序,当时是给别人写的一个单机的相册,也是我开发的第一个完整的app,虽然功能挺少,但是耐不住心中的激动啊,现 ...
- Harmonic Number(调和级数+欧拉常数)
题意:求f(n)=1/1+1/2+1/3+1/4-1/n (1 ≤ n ≤ 108).,精确到10-8 (原题在文末) 知识点: 调和级数(即f(n))至今没有一个完全正确的公式, ...
- Google软件构建工具Bazel原理及使用方法介绍
近期,Google开源了强大的自动化构建工具Bazel. 正好博主近期在使用china版的Bazel--腾讯自主开发的Blade,所以准备跟大家分享一下Google Bazel这个分布式构建系统的原理 ...
- Storm介绍(二)
作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是Storm系列之一,主要介绍Storm的架构设计,推荐读者在阅读 ...
- 1、利用蓝牙定位及姿态识别实现一个智能篮球场套件(一)——用重写CC2541透传模块做成智能手环
一.预言 要实现一个智能篮球场套件,需要设计一个佩戴在篮球运动员手臂上的可以检测投篮.记步的手环,以及一套可以根据RSSI定位运动员的蓝牙定位装置.下面是大致需要的步骤: 首先,需要用CC2541透传 ...