diff --git a/blogs/SQLite.md b/blogs/SQLite.md index 2d592bb..c552132 100644 --- a/blogs/SQLite.md +++ b/blogs/SQLite.md @@ -11,7 +11,6 @@ Android 数据持久化之 SQLite - SQLiteDatabase - 常见问题 - 数据库升级之更改表名、增删改字段 - - - 优化建议 - 事务 - 建立索引 @@ -19,6 +18,8 @@ Android 数据持久化之 SQLite #### 思维导图 +![](https://i.loli.net/2018/12/13/5c11cb9de011f.png) + #### 基本使用 ##### SQLiteOpenHelper diff --git a/blogs/埋点.md b/blogs/埋点.md new file mode 100644 index 0000000..a8f266d --- /dev/null +++ b/blogs/埋点.md @@ -0,0 +1,150 @@ +--- +Android 全埋点 +--- + +#### 目录 + +1. 思维导图 + +2. 埋点概述 + + - 事件采集 + - $AppStart / End 事件 + - $AppViewScreen 事件 + - $AppClick 事件 + - 整体思路 + - 自动拦截参考 Android 对 View 事件的处理逻辑 + - 自动插入参考编译器对 Java 代码的处理逻辑 + - 实现方式分类 + - 静态代理 + - AspectJ + - ASM + - javassist + - AST + - 动态代理 + - 代理 View.OnClickListener + - 代理 Window.Callback + - 代理 View.AccessibilityDelegate + + - 手动埋点 + - 自动化埋点 + +3. $AppViewScreen 全埋点实现 + +4. $AppStart / End 全埋点实现 + +5. $AppClick 全埋点实现 + +6. 参考 + +#### 思维导图 + +#### 埋点概述 + +##### 事件采集 + +埋点就是预先手机用户的所有行为数据,采集的事件主要包括以下三种: + +1. $AppStart / End 事件 + + 指 App 启动以及 App 退出,启动包括冷启动和热启动,退出包括正常退出、退出后台以及 App 崩溃等。 + +2. $AppViewScreen 事件 + + 指 App 页面浏览,对于 Android 来说就是指 切换 Activity。 + +3. $AppClick 事件 + + 指 App 控件被电击。 + +采集的这三种事件中,最重要也最难采集的就是 $AppClick 点击事件,全埋点基本上也是围绕如何采集 $AppClick 事件。 + +##### 整体思路 + +全埋点的整体思路,就是找到那个被点击的 View 的原处理逻辑,然后利用一定的技术原理,在原处理逻辑进行拦截,或在其中插入相应的埋点代码,从而达到自动埋点的效果。 + +至于如何做到**自动拦截**原点击事件的处理逻辑,一般参考 Android 系统 View 事件处理逻辑来进行的。 + +至于如何做到**自动插入**埋点代码,基本上都是参考编译器对 Java 代码的处理流程来进行的。即: + +```java +javaCode --> .java --> .class --> .dex +``` + +##### 实现方式分类 + +按照在 “ 什么时候去代理或者插入代码 ” 这个条件来区分的话,Android 全埋点技术可以分为两种方式: + +1. 静态代理 + + 静态代理就是通过 Gradle Plugin 在编译期间 “ 插入 ” 或者修改代码( .class 文件 )。比如 AspectJ、ASM、javassist、AST 等方案均属于这种方式,这几种方式的处理时机可以参考下图: + + ![](https://i.loli.net/2018/12/11/5c0fd3b1b7a2f.jpg) + +2. 动态代理 + + 动态代理即指在代码运行的时候去进行代理,比如常见的代理 View.OnClickListener、Window.Callback、View.AccessibilityDelegate 等方案均属于动态代理。 + +显然,静态代理明显优于动态代理。 + +#### $AppViewScreen 全埋点实现 + +页面浏览事件的监听还是很简单的,即 Application#ActivityLifecycleCallbacks,从 API 14 开始提供,它是 Application 的一个内部接口,提供了一系列回调方法,用于让开发者可以对 Activity 的所有生命周期事件进行集中处理(或者叫监控)。 + +需要注意的是,Android 是先回调接口函数,再去执行 Activity 本身的生命周期函数。 + +```java +public class MyApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + + this.registerActivityLifecycleCallbacks(new MyActivityLifecycleCallback()); + } + + static class MyActivityLifecycleCallback implements ActivityLifecycleCallbacks{ + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + Log.i("2333","onActivityCreated"); + } + + @Override + public void onActivityStarted(Activity activity) { + Log.i("2333","onActivityStarted"); + } + + @Override + public void onActivityResumed(Activity activity) { + Log.i("2333","onActivityResumed"); + } + + @Override + public void onActivityPaused(Activity activity) { + Log.i("2333","onActivityPaused"); + } + + @Override + public void onActivityStopped(Activity activity) { + Log.i("2333","onActivityStopped"); + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + Log.i("2333","onActivitySaveInstanceState"); + } + + @Override + public void onActivityDestroyed(Activity activity) { + Log.i("2333","onActivityDestroyed"); + } + } +} +``` + +#### $AppStart / End 全埋点实现 + +对于 App 的启动和退出事件,其实就是判断当前 App 是出于前台还是处于后台。而 Android 系统本身没有给 App 提供相关的接口来判断这些状态,所以只能借助其他方式来间接判断。 + +#### 参考 + diff --git a/images/SQLite.png b/images/SQLite.png new file mode 100644 index 0000000..d469fb1 Binary files /dev/null and b/images/SQLite.png differ