zoukankan      html  css  js  c++  java
  • 扫二维码下载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>

    如果此文对您有帮助,微信打赏我一下吧~

  • 相关阅读:
    MySQL 操作命令梳理(5)-执行sql语句查询即mysql状态说明
    MySQL 主从同步(5)-同步延迟状态考量(seconds_behind_master和pt-heartbea)
    MySQL 操作命令梳理(4)-中文乱码问题
    WebAssembly 介绍
    Android MVP
    Android Data Binding(数据绑定)用户指南
    认知心理学告诉你什么才是高效学习
    Android O新特性和行为变更总结zz
    音视频不同步问题的原因和解决方案
    当程序员写不出代码了,该怎么办?
  • 原文地址:https://www.cnblogs.com/Joanna-Yan/p/5395715.html
Copyright © 2011-2022 走看看