Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 562|回复: 0

Android平台的用户行为记录解决方案

[复制链接]
  • TA的每日心情
    奋斗
    3 天前
  • 签到天数: 789 天

    [LV.10]以坛为家III

    2049

    主题

    2107

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    722638
    发表于 2021-6-3 07:07:31 | 显示全部楼层 |阅读模式

    在我们展开讨论之前,首先要明白什么是用户行为记录?

    我的理解是 用户行为记录是针对使用我们软件的用户的信息统计,这些信息主要是 用户的操作信息 以及 其他一些相关感兴趣的日志信息,这些信息通常由用户的操作而产生,经我们包装处理后上传到服务器,以供数据分析员使用分析。不要小看这些信息,分析信息可以让我们了解软件的用户群,平台信息,以及用户的操作习惯等,现在已经有越来越多的开发者和公司重试并利用这一块。

    ok,既然我们是讨论解决方案的,闲话之后直入主题,怎么做?

    1.用户行为记录信息的组成 一条完整有价值的用户行为记录应该包含哪些内容呢?无疑,用户本身的点击代表的操作是主要信息,比如用户在支付页面点击了支付,这样的一个行为能提取出“支付页”和“支付”两个有价值的信息,此外,产生这个操作的时间戳信息,用户的机器信息(手机型号等),SDK版本号以及用户的网络类型信息等。

    2.用户行为记录从哪来?到哪去? 每一条用户行为记录都是由用户的操作产生的,这些信息最终会被上传到服务端保存分析。我们要做的工作就是将每条有价值的用户行为记录信息保存并上传至服务器。当然,出于应用耗电量以及程序效率的考虑,我们不可能在每次用户产生操作记录时,都发送服务将信息上传到服务器。所以我们可以采用 缓存--文件--上传服务器的策略。

    明白了上面这些信息,解决方案就出来了。

     1 /**
     2  * 用户行为记录
     3  * 
     4  * @author derson2388
     5  *
     6  */
     7 public class UserActionManager {
     8 
     9     private static UserActionManager manager;
    10 
    11     /**
    12      * 工作线程消息队列处理
    13      */
    14     private Handler mHandler;
    15     /**
    16      * 日志缓存
    17      */
    18     private ArrayList<String> mCache = new ArrayList<String>();
    19 
    20     /**
    21      * 单例访问,同步上锁
    22      * 
    23      * @return
    24      */
    25     public synchronized UserActionManager getInstance() {
    26         if (null == manager) {
    27             manager = new UserActionManager();
    28         }
    29         return manager;
    30     }
    31 
    32     private UserActionManager() {
    33         new Thread(new Runnable() {
    34 
    35             @Override
    36             public void run() {
    37                 // 新启动一个工作线程,启动Looper后创建handler处理写入请求
    38                 Looper.prepare();
    39                 mHandler = new Handler(Looper.myLooper());
    40                 Looper.loop();
    41             }
    42         }).start();
    43     }
    44 }
    UserActionManager

    上面的代码有几点值得注意:

    1.UserActionManager为全局程序提供了一个单例访问的实例,缓存cache用于缓存用户行为记录,当缓存到达一定的阀值时,才把缓存里的日志写入文件,当文件大小到达一定大小时,才将日志信息通过网络发送到服务器。

    2.构造函数里在新启的工作线程里启动了一个新的Looper并以此构造了一个专门处理该工作线程消息队列的handler,这样记录用户,写入文件,上传服务器等都可以通过这个handler分发/处理到工作线程的消息队列MessageQueue里,避免了主线程ANR的风险。

     1     /**
     2      * 用户行为记录
     3      * 
     4      * @param action
     5      */
     6     public synchronized void writeUserCode(String action) {
     7         // TODO 在这里对用户行为信息做格式化组装
     8         mCache.add(action);
     9         if (mCache.size() > MAXSIZE_CACHE) {
    10             if (null != mHandler) {
    11                 mHandler.post(new Runnable() {
    12 
    13                     @Override
    14                     public void run() {
    15                         if (!isSending) {
    16                             // 写日志到文件
    17                             pushToFile();
    18                             // 发送日志到服务端
    19                             sendActionToServer();
    20                         }
    21                     }
    22                 });
    23             }
    24         }
    25     }
    用户行为记录

    在监听到用户操作的时候调用记录方法,先将信息存入缓存,当缓存到达阀值时,清空缓存并写入文件。

     1     /**
     2      * 写入文件
     3      */
     4     private void pushToFile() {
     5         String logs = "";
     6         // 组装信息
     7         for (String str : mCache) {
     8             logs += str + "\n";
     9         }
    10         // 清空缓存日志
    11         mCache.clear();
    12         File file = new File(userActionFilePath);
    13         if (!file.exists()) {
    14             try {
    15                 file.createNewFile();
    16             } catch (IOException e) {
    17                 e.printStackTrace();
    18             }
    19         }
    20         BufferedWriter writer = null;
    21         try {
    22             writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
    23             writer.write(logs + "\n");
    24         } catch (Exception e) {
    25             e.printStackTrace();
    26         } finally {
    27             if (null != writer) {
    28                 try {
    29                     writer.close();
    30                 } catch (IOException e) {
    31                     // TODO Auto-generated catch block
    32                     e.printStackTrace();
    33                 }
    34             }
    35         }
    36     }
    写入日志文件
     1     private void sendActionToServer() {
     2         if (!isSending && null != mHandler) {
     3             mHandler.post(new Runnable() {
     4 
     5                 @Override
     6                 public void run() {
     7                     if (isSending) {
     8                         return;
     9                     }
    10                     File temp = new File(userActionFilePath);
    11                     if (null != temp) {
    12                         long length = temp.length();
    13                         if (length > MAXSIZE_FILE_CACHE) {
    14                             // 文件大于阀值,删除文件,重置重试次数
    15                             retryCount = 0;
    16                             return;
    17                         }
    18                         if (length > SIZE_FILE_CACHE && retryCount >= 3) {
    19                             // 文件大小大于设置值并失败次数大于3次,删除文件重置重试次数
    20                             retryCount = 0;
    21                             return;
    22                         }
    23                         // 开始发送服务
    24                         isSending = true;
    25                         new Thread(new Runnable() {
    26 
    27                             @Override
    28                             public void run() {
    29                                 if (sendService()) {
    30                                     // 发送服务成功,清空文件内容
    31                                     retryCount = 0;
    32                                 } else {
    33                                     // 发送服务失败,增加重试次数
    34                                     retryCount++;
    35                                 }
    36                                 // 服务发送完毕,重置标记位
    37                                 isSending = false;
    38                             }
    39                         }).start();
    40                     }
    41                 }
    42             });
    43         }
    44     }
    发送日志服务

    以上代码在文件大小大于阀值时会删除了文件,在发送服务次数到达了3次后删除文件。

     

     

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-9-9 13:31 , Processed in 0.062361 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表