Android 无埋点从入门到放弃:了解 Java 字节码

58无埋点数据采集技术在Android端实践 外链图片转存中…(img-F89zStuX-1725871600848)] 阅读详情

                                                                                      

作者:李嘉辉

GrowingIO 大前端开发工程师。负责 GrowingIO Android 和 iOS 无埋点 SDK 的设计和开发,目前专注在 Android AOP 开发。

 

引言

 

Android 无埋点的本质是通过技术手段来改写 Java 字节码,达到“自动写代码”的目的,从而实现业务目标,简单来说就是一种 Hook 形式。但是在进行之前,我们需要了解下 Java 字节码,以免出现错误的修改,导致无埋点变成“crash 点”。这就好比我们写文档前,需要先识字一样。

 

本文讲述的内容虽然比较难懂和枯燥,但是我们尽量用生动的对话形式和例子来描述。如果您一次阅读后无法消化,请收藏,之后可以多次阅读,跟着文章中的步骤动手操作。相信这篇文章会对您接触 Android 无埋点的实践有所帮助。

 

本文涉及到的工具如下(mac/windows)

  • IntelliJ IDEA

  • jclasslib Bytecode viewer

  • 010 Editor

 

场景还原

 

今天是小 O 到 G 公司上班的第一天,公司决定让老 I 带小 O 熟悉公司的代码。

 

老 I:可以先熟悉一下公司的代码。

 

小 O:好的,我这就去。

 

1.字节码

 

小 O:我看到代码中很多常量都来自于 ASM,这个框架有什么作用呢?

 

int ACC_PUBLIC = 0x0001; // class, field, methodint ACC_PRIVATE = 0x0002; // class, field, methodint ACC_PROTECTED = 0x0004; // class, field, methodint ACC_STATIC = 0x0008; // field, methodint ACC_FINAL = 0x0010; // class, field, method, parameterint ACC_SUPER = 0x0020; // class...

 

老 I:ASM 是一个通用的 Java 字节码操控和分析框架。

 

小 O:操作 Java 字节码?

 

老 I:用《Java 虚拟机规范》上的说法,Java 字节码就是编译后被 Java 虚拟机所执行的代码,使用了一种平台中立(不依赖特定硬件及操作系统)的二进制格式来表示,并且经常(但并非绝对)以文件的形式存储,因此这种格式称为 class 文件格式。

 

小 O:那我要学会 ASM,应该先了解字节码吗?

 

老 I:是的,我先跟你介绍一下字节码的基本结构,以下面的代码为例。​​​​​​​

 

public class Main{  public static void main(String[] args) {    System.out.println("Hello World!");  }}

 

老 I:一个标准的 ClassFile 结构如下:​​​​​​

 

ClassFile {        u4              magic;        u2              minor_version;        u2              major_version;        u2              constant_pool_count;        cp_info         constant_pool[constant_pool_count-1];        u2              access_flags;        u2              this_class;        u2              super_class;        u2              interfaces_count;        u2              interfaces[interfaces_count];        u2              fields_count;        filed_info      fields[fields_count];        u2              methods_count;        method_info     methods[methods_count];        u2              attributes_count;        attribute_info  attributes[attributes_count]; }

 

老 I:让我们通过一个更加易懂的方式继续,我们通过 010Editor 打开上述代码编译后的 class 文件可以看到如下信息。

 

 

2.magic

 

小 O:这个开头的数字 0xCAFEBABE 很有意思,是有某种特殊含义吗?

 

老 I:这是一个魔数,用于判断是否是一个 class 文件,是一个固定值,也就是 0xCAFEBABE(魔数背后的故事 https://en.wikipedia.org/wiki/Java_class_file),至于为什么使用这个魔数,可以看一下文章里 James Gosling 的描述。

 

3.minor_version

 

小 O:紧跟着魔数的 0x00000034 看图好像分为了 minor 和 major,是表示版本号吗?

 

老 I:对的,minor 表示本地 java 环境副版本号,你可以通过 java -version 查看本地 java 版本,比如我的本地版本,1.8 为主版本号,0 为副版本号,如图所示 0x0000,171 为 update。

 

 

4.major_version

 

老 I:major 表示本地 java 环境主版本号,0x0034 即 52 对应 1.8,0x0033 即 51 对应 1.7,依此类推。

 

5.constant_pool_count

 

小 O:下面这个 constant_pool_count 有 34 个, 010Editor 中显示的 0-32 就是他的成员了吗,那为什么 count 是 34 个呢?

 

老 I:这是因为 010Editor 默认使用的 class 解析模版(template)是从 0-32,但是实际上常量池使用 1 ~ constant_pool_count-1 作为索引,count 则为常量池中成员数 +1,0 用于保留作为其他用途,这个可以使用 IDEA 的 jclasslib Bytecode viewer 插件查看,它是符合从 1 开始计数的规范的,并且提供了对各种类型的过滤。

 

                                                       

 

小 O:那 0 的保留用途具体是什么呢?

 

老 I:这是一个好问题,0 的保留用途可以参照一些例子, 比如说:

  • java/lang/Object时的superclass

  • 表示捕获所有异常(等价于catch java/lang/Throwable)时的catch_type

  • 类为顶层类、顶层接口、本地类、匿名类时的outer_class_info_index

  • 匿名类时的inner_name_index

  • 当前类不是直接包含在某个方法或构造器时的method_index

     

6.constant_pool[constant_pool_count-1]

 

小 O:那后面紧跟着的就是所谓的常量池成员了吗?

 

老 I:对的,常量池包含所有字符串常量、类或接口名、字段名和其它常量,常量池数组中不同元素类型不同,结构不同,但是均使用第一个字节作为类型标记(tag byte),涉及的内容比较多,我们先整体上了解一下,跳过常量池继续往下看。

 

 

7.access_flags

 

小 O:这个 flag 是 0x0021,这是什么意思呢?

 

老 I:还记得最初你在 ASM 框架中看到的常量吗,这个 flag 定义如下。

 

              标志名                 值                含义

ACC_PUBLIC

0x0001

public
ACC_FINAL0x0010final
ACC_SUPER0x0020

JDK1.0.2 前需要对父类方法特殊处理,1.0.2 后带有以区分

ACC_INTERFACE0x0200interface
ACC_ABSTRACT0x0400abstract
ACC_SYNTHETIC0x1000synthetic,非 Java 源代码生成
ACC_ANNOTATION0x2000annotation
ACC_ENUM0x4000enum

   

老 I:你图中看到的 0x0021 即 ACC_SUPER & ACC_PUBLIC。

 

8.this_class

 

小 O:那这个 this_class(0x0005) 也是某种常量吗?

 

老 I:不是的,这里的 0x0005 是一个指向常量池中某个成员的有效索引,常量池中该索引处成员必须为 CONSTANT_Class_info 类型结构体,表示这个 class 文件所定义的类或接口。

 

老 I:在图中可以看到 0x0005 指向常量池中如下位置,你应该还记得 010Editor中template 解析常量池数组的 name 显示是从 0 开始,而实际常量池的索引从 1 开始,所以 0x0005 在 010Editor 中对应 constant_pool[4]),即下面图中这个位置。

 

 

老 I:然后根据该常量池成员结构的 name_index,继续查找常量池中对应 index,0x001A。

 

 

老 I:如果觉得 010Editor 不够清晰或者不好查找,可以使用 Intellij 的插件 jclasslib Bytecode viewer,支持直接跳转,方便快速查找。

 

 

9.super_class

 

小 O:那后面这个 0x0006 也是一个指向常量池的索引吗?

 

老 I:对的,父类索引,常量池中该索引处成员必须为 CONSTANT_Class_info 类型结构,表示这个 class 文件所定义的类的直接超类,如果为 0,即当前类为 java/lang/Object。

 

老 I:由图中可以看到 0x0006 指向常量池中如下位置。

 

 

老 I:根据 name_index,继续查找常量池中对应 index,0x001B。

 

 

老 I:这里我们可以通过 jclasslib 插件查看,支持直接跳转查看父类,还记得我们之前说过常量池 0 的保留用途吗?

 

 

老 I:从这里我们可以看到 Object 的 super_class 指向常量池中 0 这个位置(即无效索引)。

 

10.interfaces_count

 

小 O:我知道了,那这个 0x0000,表示当前类或接口的直接超接口数量,即 interfaces 表中成员个数是 0。

 

老 I:没错,就是这个道理。

 

11.interfaces[interfaces_count]

 

老 I:因为我们之前的类是没有超接口的,所以在原 class 文件增加两个接口,则可以看到:

 

老 I:在这个数组中,每个成员的值必须是一个有效索引,常量池中该索引处成员必须为 CONSTANT_Class_info 类型结构体,表示这个 class 文件所定义的类或接口的直接超接口,与源码定义接口从左往右顺序一致。

 

12.fields_count

 

小 O:那后面这个 0x0000 表示当前 class 文件 fields表中成员个数为 0。

 

老 I:对的。

 

13.fields[fields_count]

 

老 I:在这个数组中,每一个成员都是由 filed_info 结构所定义。​​​​​​​

 

field_info {    u2             access_flags;    u2             name_index;    u2             descriptor_index;    u2             attributes_count;    attribute_info attributes[attributes_count]; }

 

老 I:之前的代码没有定义成员,所以我们使用如下代码来看这个结构。

​​​​​​​

public class Main {    int i = 0;}

 

(1)access_flags

小 O:我知道,这个 flag 也是一些常量标识。

 

老 I:对的,这些常量标识的定义如下。

 

              标志名                 值                含义
ACC_PUBLIC0x0001public
ACC_PRIVATE0x0002private
ACC_PROTECTED0x0004protected
ACC_STATIC0x0008static
ACC_FINAL0x0010final
ACC_VOLATILE0x0040volatile
ACC_TRANSIENT0x0080transient
ACC_SYNTHETIC0x1000字段由编译器生成
ACC_ENUM0x4000enum

 

老 I:因为我们代码中使用的是默认 access_flags,所以在 010Editor 中显示为 0x0000。

 

(2)name_index

小 O:那这个结构中的 name_index、descriptor_index ,带着 index,应该都是指向常量池中某个成员的索引吧。

 

老 I:对,name_index 是一个有效索引,常量池中该索引处成员必须为 CONSTANT_Utf8_info 结构, 根据图中索引为 0x0005,找到常量池如下位置。

 

 

(3)descriptor_index

老 I:descriptor_index 也是一个有效索引,常量池中该索引处成员必须是 CONSTANT_Utf8_info 结构,为字段的描述符,根据图中索引 0x0006,找到常量池如下位置。

 

 

(4)attributes_count

小 O:那接下来的这个 attributes 是做什么的呢? 为什么这里是 0x0000?

 

老 I:这个表示当前字段的附加属性表中成员的个数。

 

(5)attributes[attributes_count]

老 I:属性表的成员,每一个成员为 attribute_info 结构,举个例子,可以在字段上增加 @Deprecated,如下图所示,具体的可以在之后看 attribute_info 时分析。

 

 

14.methods_count

 

小 O:这个应该是表示当前 class 文件 methods 表成员个数,最初那个例子中,0x0002 表示有两个函数,但是我们不是只定义了 main 函数吗?

 

老 I:对的,在最开始使用的例子中,0x0002 表示有两个函数。

 

15.methods[methods_count]

 

老 I:紧跟着 methods_count 的是方法表的成员,每一个成员为 method_info 结构,用于表示当前类或接口中某个方法的完整描述,结构如下。

​​​​​​​

method_info {    u2             access_flags;    u2             name_index;    u2             descriptor_index;    u2             attributes_count;    attribute_info attributes[attributes_count];}

 

老 I:我们使用如下代码来看这个结构,也顺道解释为什么之前的代码虽然只定义了一个 main 函数,count 却是 0x0002。

​​​​​​​

public class Main {}

 

老 I:我们可以通过 jclasslib 来看,比较清晰。实际上会有一个编译器提供的默认构造函数。

 

 

(1)access_flags

小 O:嗯,这个 method_info 跟 field_info 很接近,让我来试着解释一下。

 

老 I:好的,请开始你的表演,这个 flag 的定义我先列出来。

 

              标志名                 值                含义
ACC_PUBLIC0x0001public
ACC_PRIVATE0x0002private
ACC_PROTECTED0x0004protected
ACC_STATIC0x0008static
ACC_FINAL0x0010final
ACC_SYNCHRONIZED0x0020synchronized
ACC_BRIDGE0x0040bridge 方法,由编译器产生
ACC_VARARGS0x0080表示方法带有变长参数
ACC_NATIVE0x0100native
ACC_ABSTRACT0x0400abstract
ACC_STRICT0x0800strictfp,使用 FP-strict 浮点模式
ACC_SYNTHETIC0x1000字段由编译器生成

 

小 O:因为默认生成的构造函数是 public,所以对应 010Editor 中显示为 0x0001,即 ACC_PUBLIC。

 

(2)name_index

小O:name_index 是一个有效索引,常量池中该索引处成员必须为 CONSTANT_Utf8_info 结构,表示一个特殊方法名或有效非限定名,根据图中索引为 0x0004, 就可以找到常量池在如下位置。

 

 

(3)descriptor_index

小O:descriptor_index 也是一个有效索引,常量池中该索引处成员必须为 CONSTANT_Utf8_info 结构,表示方法的描述符,根据图中索引为 0x0004,就可以找到常量池在如下位置。

 

 

(4)attributes_count

小 O:这个 attributes_count 表示当前方法的附加属性表中成员的个数。

 

(5)attributes[attributes_count]

小 O:属性表的成员,每一个成员应该也为 attribute_info 结构。

 

老 I:嗯,对的,厉害了。这部分我补充个例子,比如 Code_attribute,可以看到如下图所示,具体在之后看 attribute_info 时分析。

 

 

16.attributes_count

 

小 O:这个 attributes_count 应该表示的是当前 class 文件属性表的成员个数。

 

老 I:嗯,没错。

 

17.attributes[attributes_count]

 

老I:这个文件属性表成员,每项都必须是attribute_info 结构,以 SourceFile_attribute 为例,我们通过如下代码来看。

​​​​​​​

public class Main {}

 

老 I:如下图所示。

 

 

老 I:其结构如下:​​​​​​​

 

SourceFile_attribute {    u2 attribute_name_index;    u4 attribute_length;    u2 sourcefile_index;}

 

(1)attribute_name_index

小 O:这个 index 肯定是一个有效索引。

 

老 I:对的,常量池中该索引处成员必须为 CONSTANT_Utf8_info 结构,表示字符串 "SourceFile"。

 

(2)attribute_length

老 I:SourceFile_attribute 的 length 为固定值 2,即图中 0x00000002。

 

(3)sourcefile_index

老 I:最后的 index 也是一个有效索引,常量池中该索引处成员必须为 CONSTANT_Utf8_info 结构,表示被编译的 class 文件的源文件名。

 

等你先熟练掌握今天介绍的内容,我再给你继续讲解其他的结构。常量池、属性(filed, method 中的 attribute_info 也将放在一起)涉及较多内容,掌握字节码对后续了解及使用 ASM(一个通用的 Java 字节码操控和分析框架)有很大帮助,也可以让你更快熟悉代码。

 

小 O:好的,让我再分析几个 class 文件熟悉一下。

 

小结

 

理解 Java 字节码并不单单对了解无埋点插桩( ASM 等框架)有帮助,在一些常见的情境下它也能发挥自己的作用。所以对 Java 字节码的掌握有利于我们更加深入地了解 Java 的各种机制,比如说很常见的面试题(可以看看自己是否能够回答上来)

  1. String 在编译期与运行期最大长度

  2. synchronized 语义

  3. new 语句中 dup 指令作用

 

参考文档:

  • https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

  • 《Java虚拟机规范 Java SE 8版》

 

Android 基于 DroidAssist 插件实现无埋点 DroidAssist DroidAssist (源码) 是一个轻量级的 Android 字节码编辑插件,基于 Javassist 对字节码操作,根据 xml 配置处理 class 文件,以达到对 class 文件进行动态修改的效果。和其他 AOP 方案不同,DroidAssist 提供了一种更加轻量,简单易用,无侵入,可配置化的字节码操作方式,你不需要 Java 字节码的相关知识,只需要在 Xml 插件配置中添加简单的 Java 代码即可实现类似 AOP 的功能,同时不需要引入其他额外的依赖。 使用方式 阅读详情

相关推荐

Android无埋点的技术选型之路

数极客是国内新一代用户行为分析平台,支持无埋点采集,前端代码埋点采集,后端代码埋点采集等多种混合数据采集方式,支持30多种数据可视化效果,是增长黑客必的备大数据分析工具,支持APP分析数据网站分析及用户画像,独创了6大转化率分析模型,的英文用户行为分析领域首家应用定量分析与定性分析方法的数据分析产品,运用数极客用户行为录屏系统,可以分析并优化用户体验的细节,基于用户行为分析系统- ,了提供会员营销...

开启智慧人生的大门 2893

growingio基本使用(总结)

  growingio基本使用 背景:方便分析图片报告的哪些报告受到用户喜欢,来调整报告的侧重点  设计师引流网站:http://huaban.com/  (国内,花瓣)                                  http://www.pinterest.com/ (国外) 一,准备工作: 注册一个GrowingIO账号 拥有自己的网站或APP 1,选择...

gaokcl的博客 3万+

Android实现无痕埋点具体实现-采用代码插桩的方式

目录 1.View.AccessibilityDelegate 1.1先看下为什么采用View.AccessibilityDelegate方式,通过View源码如何执行点击事件: 1.2完成替换View中AccessibilityDelegate类,实现sendAccessibilityEvent(this, eventType)方法 2.gradle插件字节码插装 2.1Android下apk编译流程 2.2编写gradle插件模块(groovy文件实现) 2.2.1工程下新建buildSr

Tiger的专栏 3307

android+无埋点+开源,得到Android无埋点方案细节分析

1. View唯一标识id组成:ActivityName_LayoutFileName_idName对应源码:ResourceHelper#getGlobalIdNamepublic static String getGlobalIdName(@NonNull View view) {int id = view.getId();...try {Context context = view.getC...

weixin_35745915的博客 261

Android自动化埋点(一) - JVM字节码

JVM作为基础,是进行字节码插桩所必须要掌握的知识,但是本篇不会进行太深入的讲解,以免初学者陷入细节无法自拔或者不知所云。

qq_15328623的博客 772

ASM的基础使用 Android 自动化埋点方案原理剖析

Android 自动化埋点方案原理

菜鸟博客 2820

android 无埋点 简书,无埋点README

无埋点编码规范无埋点方案基于窗口回调(Window.Callback)机制。BaseActivity中集成了自动打点相关逻辑。但由于dialog和activity实现机制不一样。为了dialog同样能够集成自动打点功能,解决方案如下:任何Dialog,需要继承DDAlertDialog/DDDialog/DDV7AlertDialog。任何PopupWindow需要继承DDPopupWindow。...

weixin_36230923的博客 316

使用Metasploit生成木马控制Windows系统

使用Metasploit生成木马控制Windows系统

weixin_56956399的博客 2508

Android开发必会App启动优化(1),含泪狂刷Android基础面试118题

initARouter(); CacheManager.getInstance().initialize(getInstance()); ConnectionManager.getInstance().initialize(); initImageFactory(); initBJY(); initGrowingIO(); initUmeng(); initBugly(); initOkHttp(); initSobot(); setRxJavaErrorHandler(); } }).start(); 将

m0_66264134的博客 638

游程理论提取灾害事件特征V2---基于MATLAB语言的编程实现

游程理论,灾害事件,MATLAB

EWBA_GIS_RS_ER的博客 3793

从零上手HiAgent:构建能听懂指令的智能体框架实战指南

智能体(Agent)作为人工智能领域的重要范式,正从传统的预设流程自动化转向以目标驱动的自主规划与执行。其核心原理在于利用大语言模型(LLM)作为决策大脑,通过任务规划、工具调用与记忆机制,将模糊的自然语言指令转化为可执行的工作流。这一技术显著提升了人机协作的效率和自然度,其价值在自动化办公、数据分析与智能流程编排等场景中尤为突出。本文聚焦于HiAgent这一具体框架,深入解析其作为智能体开发平台的核心架构,涵盖规划器、执行器、工具集等关键组件,并提供从环境配置、自定义工具开发到复杂任务链构建的完整工程实践

weixin_29266007的博客 888

GrowingIO 如何做到不必埋点即可采集到齐全的用户行为点击流数据?

source: https://www.zhihu.com/question/38000812 孔淼 诸葛io(http://zhugeio.com) CEO 36 人赞同了该回答 首先直接回答题主的问题: 大多对于可交互式的应用程序,例如Android应用,iOS应用,网站,Window

BalterNotz的博客 6504

Android音频学习(八)——AudioFlinger线程

在 PlaybackThread 的实现中,Flag 用于标识线程的特殊行为或配置。

miemie2014的博客 1399

android studio右面不显示attribute_Android 无埋点从入门到放弃:了解 Java 字节码

Android 无埋点的本质是通过技术手段来改写 Java 字节码,达到“自动写代码”的目的,从而实现业务目标,简单来说就是一种 Hook 形式。但是在进行之前,我们需要了解下 Java 字节码,以免出现错误的修改,导致无埋点变成“crash 点”。这就好比我们写文档前,需要先识字一样。本文讲述的内容虽然比较难懂和枯燥,但是我们尽量用生动的对话形式和例子来描述。如果您一次阅读后无法消化,请收藏,...

weixin_33914982的博客 1377

人机协作新纪元:AI会抢走IT人的饭碗吗?

产品经理用自然语言描述需求,AI将其转化为技术规格书(准确率已达89%)

819

sift、surf、orb 特征提取——三维重建

参考文章:[sift、surf、orb 特征提取及最优特征点匹配] 最近刚刚入门三维重建,在SFM算法的代码中注意到了feature_type( feature extraction method)这个参数,想细致了解一下这几种特征提取算法,在这里做一下笔记。 SIFT 简介 SIFT(Scale-Invariant Feature Transform)——尺度不变特征变换,是一种计算机视觉的特征提取算法,用来侦测与描述图像中的局部特征。 实质上,它是在不同的尺度空间上查找关键点(特征点),并计算出关键点的

bb_sy_w的博客 4362

Android 无侵入式数据采集:从手动埋点到字节码插桩的演进之路

摘要 本文探讨了无侵入式数据采集在App开发中的必要性及实现方案。传统手动埋点存在代码侵入性强、维护成本高、沟通成本大、错误频发等问题。无侵入方案通过AOP和字节码插桩技术,在编译期自动植入埋点逻辑,实现业务与数据采集解耦。重点介绍了ASM实现页面浏览和点击事件自动采集的技术细节:对Activity/Fragment生命周期方法插桩采集PV/UV,通过代理模式拦截点击事件。对于复杂业务事件,建议采用注解驱动半自动化方案。编译期插桩相比运行时Hook具有更高稳定性和性能优势,是生产级应用的首选方案。

csdn_silent的博客 5095

在Simulink中搭建一个基于IoT设备间通信协议栈的仿真模型

物联网(IoT)设备间的通信协议栈仿真对于理解不同层级的协议如何协同工作,以及优化网络性能至关重要。通过Simulink结合MATLAB的强大功能,我们可以模拟和分析从物理层到应用层的完整通信过程。下面详细介绍如何使用Simulink进行IoT设备间通信协议栈的仿真。

amy_mhd的博客 156

安卓字节码插桩与埋点

本文介绍了安卓字节码插桩,并用埋点为例子,介绍了它的使用

Meteors.的博客 404

OpenCV实例(八)车牌字符识别技术(三)汉字识别

相较于数字和英文字符的识别,汽车牌照中的汉字字符识别的难度更大,主要原因有以下4个方面:(1)字符笔画因切分误差导致非笔画或笔画流失。(2)汽车牌照被污染导致字符上出现污垢。(3)采集所得车辆图像分辨率低导致多笔画的汉字较难分辨。(4)车辆图像采集时所受光照影响的差异导致笔画较淡。综合汉字识别时的这些难点来看,很难被直接提取的是字符的局部特征。笔画作为最重要的特征而仅存在于汉字中,这由先验知识可知。一旦捺、横、竖、撇这些笔画特征被提取到,对于汉字字符识别的工作就完成了许多。

小幽余生不加糖 1650

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Android 全埋点方案盘点

全埋点是什么 全埋点,也叫无埋点、无码埋点、无痕+埋点、自动埋点。 全埋点是指无需Android应用开发工程师写代码或只写少量的代码,就能预先自动收集用户的所有行为数据,然后就可以根据实际的业务分析需求从中筛选出所需行为数据并进行分析。 全埋点采集的事件目前主要包括以下四种 $AppStart事件 指应用程序启动(冷启动和热启动)场景。热启动也就是指应用程序从后台恢复的情况。 $AppEnd事件 ...

朱豪凯的博客 2765

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

android无埋点统计

https://www.jianshu.com/p/9039a3e46dbc   Android ASM自动埋点方案实践  C6C 关注 2018.01.11 21:28* 字数 2352 阅读 6241评论 13喜欢 44 这段时间想到一个有趣的功能,就是在Android的代码编译期间进行一些骚操作,来达到一些日常情境下难以实现的功能,比如监听应用中的所有onClick点击时间,或者...

u010029439的博客 850

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

自定义Gradle插件 字节码插桩 附带Demo

参考: Android字节码插桩采坑笔记 通过自定义 Gradle 插件修改编译后的 class 文件 ASM官方文档

薛瑄的博客 7562

公众号赠书+干货 | Android 全埋点解决方案之 Javassist

全埋点,也叫无埋点、无码埋点、无痕埋点、自动埋点。 全埋点是指无需 Android 应用程序开发工程师写代码或者只写少量的代码,就能预先自动收集用户的所有行为数据,然后就可以根据实际的业务分析需求从中筛选出所需行为数据并进行分析。 本文来主要介绍 $AppClick 全埋点方案:Javassist,更多全埋点方案请关注《Android 全埋点解决方案》一书。 关键技术 Javassist Jav...

SDResearch的博客 611

最通俗易懂的字节码插桩实战(Gradle + ASM)—— 自动埋点

### 前言 字节码插桩,看起来挺牛皮,实际上是真的很牛皮。 但是牛皮不代表难学,只需要一点前置知识就能轻松掌握。 ### Gradle Transform Google在Android Gradle的1.5.0 版本以后提供了 Transfrom API,允许开发者在项目的编译过程中操作 .class 文件。Transfrom需要介绍的地方不多,唯一的难点就是要熟悉API,我会在文尾推荐相关文章,这里就不过多介绍,影响大家的阅读体验。 ### ASM ASM是一种通用Java字节码操作和分析框架。它..

m0_61170579的博客 1310

Android自动化埋点无痕埋点代码插桩Demo:为移动应用注入智能数据收集能力

Android自动化埋点无痕埋点代码插桩Demo:为移动应用注入智能数据收集能力 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 Android自动化埋点(无痕埋点)代码插桩Demo,是一个展示如何通过字节码插桩技术实现自动化埋点的Android项目示例。该技术能够在不修改源代码的情况下,自动收集用户的行为数据,对于提高应用的用户体验和数据分析效率具有显著优势。 项目技...

gitblog_06717的博客 1606
上一篇: GrowingIO 大数据多维分析自动化测试实践
下一篇: 企业级 SaaS 增长的 18 大关键指标
GrowingIO_
博客等级 码龄8年 56粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值