
android
文章平均质量分 83
我是黄大仙
黄大仙
展开
-
sdk 动态加载实践
这样我们就实现了 sdk 远程加载的方式进行初始化。每个业务只需要引用一个壳工程,每次只需要服务进程更新即可,避免业务需要频繁更新 sdk 版本的问题和版本不一致的问题。原创 2024-08-29 17:22:21 · 1053 阅读 · 0 评论 -
使用docker创建自己的Android编译容器
每次拿到新机器或者系统重装,最麻烦的就是各种环境配置,最近学习了一下docker的知识,用dockerfile创建一个Android编译容器,这样就不用每次都吭哧吭哧的配置各种环境,至少编译可以方便点,开发环境还是得手动配的。需要注意的是,RUN和COPY指令都会增加容器的层级,所以我们尽可能的将可以合并的指令通过 && 连接起来,以此来减少容器的层级,减少容器的大小。再clone一个工程,尝试编译,发现能够编译成功。我们用这个镜像创建一个容器,并进入到这个容器中。发现已经有java的环境变量了。原创 2023-12-22 10:29:01 · 2153 阅读 · 1 评论 -
第三方登录踩坑记录
最近做了注册登录的功能,其中涉及到第三方登录,就是通过 QQ 或微信或 FaceBook 等的账号进行登录。这种通过第三方的账号进行登录的逻辑都差不多,就是通过第三方的 sdk 拿到对应的 token,然后再用 token 向自己的业务后台进行注册,后台可以通过 token 获取到第三方平台的用户信息。原创 2023-03-26 15:47:34 · 308 阅读 · 0 评论 -
多语言解决方案
多语言是一个比较麻烦的事情,特别是当 App 比较大的时候,还会涉及到多个部门的开发以及翻译人员,这中间可能会存在比较大的沟通成本,而且还可能会阻塞开发的进度。以下是我们在具体开发过程当中使用的一个方案,通过管理端+流水线自动同步的方式来解决。原创 2023-02-23 11:30:31 · 1700 阅读 · 0 评论 -
基于配置系统和流水线的热更新方案
最近我们要在一个新的 App 上增加热更新的能力,按照以往的设计思路,需要后台一起参与,并提供对应的接口原创 2023-01-10 11:26:50 · 451 阅读 · 0 评论 -
PAD 踩坑记录
PAD 踩坑记录原创 2022-11-07 10:19:11 · 2279 阅读 · 0 评论 -
Unity-huatuo热更新调研
Unity-huatuo热更新调研原创 2022-11-04 18:00:38 · 2008 阅读 · 0 评论 -
愉快无负担的跨进程通信方式2
跨进程版的EventBus 2.0原创 2022-07-10 17:05:37 · 691 阅读 · 1 评论 -
冷启动的最优解决方案
冷启动任务的最优解决方案原创 2022-06-18 22:00:05 · 1216 阅读 · 0 评论 -
愉快无负担的跨进程通信方式
跨进程版本的EventBus原创 2022-06-10 21:01:24 · 905 阅读 · 0 评论 -
sdk开发经验总结
文章目录1. 降低接入成本1.1 接入简单1.2 文档和 demo1.3 api接口设计1. 接口保持精简,不要提供过多的接口2. 每个接口均应当提供详细的接口说明3. 接口参数不应过多4. 接口方法过多,应当提供默认实现5. 接口尽可能和系统或者业内标准保持一致1.4 向后兼容2.稳定性2.1 plan B2.2 监控2.3 错误指引3.其他3.1 易扩展3.2 关注性能3.3 鉴权3.4 合规3.5 sdk接入标准化4. 总结博主之前做过一些 sdk 的开发,也对接过一些 sdk ,有一些 sdk 设原创 2022-04-26 23:32:43 · 9864 阅读 · 1 评论 -
使用DSL增加代码的可读性
1.背景2.具体实现2.1 lambda表达式2.2 invoke约定+中缀表达式+扩展函数原创 2022-04-21 21:36:07 · 2180 阅读 · 0 评论 -
使用协成将异步转同步
最近学习了一下kotlin的协成,发现使用协成能够帮助我们将异步代码转换成同步代码,能够极大的提高代码的可读性。1.普通的异步写法如下所示,为我们常见的一些异步代码,通常情况下,我们会传递一个callback到方法里面,等到异步代码执行完毕之后回调回来。public fun realRequest(response: Callback) { Thread(Runnable { println("start request:" + address) Thread.原创 2022-03-31 19:16:23 · 7480 阅读 · 0 评论 -
kotlin的属性代理
今天学习了一下kotlin的属性代理,觉的挺有趣的,借助属性代理我们可以实现一些有意思的功能。基本语法class Student{ var name: String by Delegate()}class Delegate{ operator fun <T> getValue(thisRef: Any?, property: KProperty<*>): T{ ... } operator fun <T> setV原创 2022-03-01 23:24:37 · 2850 阅读 · 0 评论 -
应对隐私检测的各种姿势
文章目录背景隐私检测的流程流程 1.0流程 2.0流程 3.0应对隐私检测的各种姿势1. 提前获取数据和获取频率2. 权限问题3. sdk问题反编译终极大招总结背景去年11月,我们团队就已经宣布解散,但是由于隐私监管的问题,我们还得维护最后一个版本,满足隐私监管的要求。我们团队的隐私问题主要是由我来负责,回想起这一年,真是被各种隐私问题折腾得死去活来,所幸最后一个版本终于上线了,现针对隐私问题总结一下各种应对的方法。隐私检测的流程流程 1.0在刚开始被要求隐私检测的时候,我们的流程是这样原创 2022-01-28 11:51:34 · 4608 阅读 · 0 评论 -
徒手撸一个gradle插件
1.准备工作1.1创建一个Android module1.2准备maven环境2.实现插件2.1实现插件类2.2编辑properties文件2.3发布插件3.应用插件3.1引入插件3.2应用插件1.准备工作使用java开发gradle插件,基于gradle7.0版本开发,所以一些gradle的API针对低版本已经发生了变化。1.1创建一个Android module创建Android模块GradlePlugin,删除掉res和androidTest这两个目录,在main目录下创建resource.原创 2022-01-08 13:08:52 · 1500 阅读 · 0 评论 -
反编译更改jar包代码
背景实现步骤1.新建工程,将jar包引入,打包成apk2.使用apktool,将apk转换成smali文件3.找到对应的位置,修改smali代码4.将修改完成的工程,使用apktool将smali打包成dex5.将dex转换成为jar包6.从jar包当中找到对应的class文件,解压,并存放在对应的目录当中7.使用zip -u命令更新原来的jar包背景在某些特殊的场景,我们需要将jar包反编译然后修改里面的源码来实现我们自己的功能。博主前段时间就遇到了这样的问题。由于隐私监控越来越严格,博主所在的部.原创 2022-01-08 12:34:49 · 2847 阅读 · 0 评论 -
JNI绑定实践
目录背景静态注册1.引入so文件和native方法2.编译生成jni头文件3.实现jni方法4.实现CMakeLists.txt动态注册1.定义对应交互的java方法2.引入c++代码和CMakeLists.txt文件3.编辑c++文件4.实现CMakeLists.txt背景博主之前做的日志组件的结构是java和c++相结合实现。将日志的加密,压缩,文件写入等对性能比较敏感的模块放在c++层实现,而将日志的格式化,日志脱敏等功能放在java层实现。这就会涉及到java和c++的交互,即jni。jni注原创 2022-01-08 11:35:11 · 702 阅读 · 0 评论 -
安全高效可视化的日志解决方案
背景一条工单引发的日志需求我们的业务收到了一个信息泄漏的工单,漏洞是明文打印日志。我们当时使用的是某网络库自带的日志系统(以下简称 A 系统),会直接将明文写入到了日志文件当中,这样就有信息泄漏的风险。我们搜集了当前使用 A 系统的痛点:明文打印,造成隐私泄漏;关键日志丢失;无法方便的打印当前的堆栈,线程等信息;不支持各种格式化输出。为了解决这个问题,我们设计并实现了 TinyLog。TinyLog 能支持日志的加密和压缩,减少日志文件大小并确保隐私不会泄漏;能够支持各种格式化输出,原创 2021-11-15 10:44:08 · 787 阅读 · 0 评论 -
一个轻量级的任务执行组件
之前做启动优化的时候,把各种任务单独拎出来,做成一个组建,然后根据任务的优先级以及依赖顺序去执行.源码见:https://github.com/huangbei1990/HDemo整个模块主要分成以下四个部分.1.tasktask设置了四个优先级,具体如下所示,不同优先级的task会有不同的执行逻辑.public enum Priority { Immediately,//放入缓存线程池执行 Normal,//放入线程池执行 Idle,//cpu空闲时执行 Main原创 2020-12-09 17:26:11 · 245 阅读 · 0 评论 -
mock简单使用
最近楼主在做一个sdk,和后台进行协同开发,依赖于后台实现的接口,在开发之前先和后台约定好了接口,然后在开发的过程中可以先mock这个接口,这样就不会阻塞开发的流程.等后台开发好了之后,再一起联调就可以了.1.引入implementation 'org.mockito:mockito-core:1.10.19'implementation 'com.crittercism.dexmaker:dexmaker:1.4'implementation "com.crittercism.dexmaker:d原创 2020-12-04 10:47:18 · 752 阅读 · 0 评论 -
Android项目模块化最优配置
随着Android项目越来越大,每个项目都会分成各个小模块方便管理,而每个模块都有各自的编译配置,因此统一配置是需要考虑的一个问题.以下是我比较喜欢的一种配置方式.随着Android项目越来越大,每个项目都会分成各个小模块方便管理,而每个模块都有各自的编译配置,因此统一配置是需要考虑的一个问题.以下是我比较喜欢的一种配置方式.1.在根目录新建config.gradle文件.内容如下,其中ext是gradle提供的一个ExtensionAware类型的属性,本质是一个map.ext.config =原创 2020-11-08 21:15:26 · 309 阅读 · 0 评论 -
Activity的显示
1.Activity的显示Activity的显示原理如下图所示在Activity启动的时候会创建一个PhoneWindow,而这个PhoneWindow会包含一个DecorView,DecorView就是Activity的rootview,其中包含一个bar和contentView,我们自己写的布局会放到contentView当中。对于每个DecorView都有一个对应的ViewRootIm...原创 2020-03-16 11:44:22 · 454 阅读 · 0 评论 -
Activity的启动流程
1.Activity的启动流程当我们点击桌面的图标时,其实就是启动对应应用的入口Activity。启动Activity主要有两个流程,一个是对应的应用进程存在,一个是对应的进程不存在,以下的流程是对应的进程不存在的流程。如上图所示,当启动一个activity时,会将请求发送至AMS,AMS会判断目标进程是否存在,若不存在,则先发消息给zygote进程,然后从zygote进程当中fork出目标...原创 2020-03-14 20:11:53 · 2419 阅读 · 0 评论 -
binder调用流程分析
binder是一个非常好的跨进程通信工具,Android对其进行了各种封装,虽然我们用起来简单,但是理解起来却比较困难。1.自己设计一个跨进程通信机制在理解binder之前呢,首先我们想一下,如果我们自己设计一个跨进程通信的机制,那我们会怎么设计呢?如果是我的话,我可能会按照下图设计。图中左边是客户端,右边是服务端,客户端想要调用服务端的call函数,首先我们需要先将函数名称以及参数值进...原创 2020-03-12 12:19:49 · 906 阅读 · 0 评论 -
只有主线程才能更新view吗?
1.子线程更新产生异常做过Android开发的同学都知道只有在主线程才能够更新view,如果在子线程更新view,则会抛出异常。我们来看下这个异常到底是哪里抛出来的。如下代码所示,新建了一个线程去更新viewnew Thread(() -> { jumpBtn.setText("测试");}).start();这时抛出的异常如下 android.view.View...原创 2020-02-26 16:09:54 · 489 阅读 · 0 评论 -
跨进程传输大文件
1.出现异常2.异常分析3.解决方法原创 2020-02-23 16:00:21 · 1695 阅读 · 1 评论 -
service的绑定原理
看完service的启动流程,继续撸一下service的绑定流程1.service的绑定流程首先我们看下如下图所示的service的绑定原理,应用向AMS发起bindService,然后AMS检查自己是否有对应service的binder句柄,如果有,则直接返回,如果没有则会向service请求对应的binder句柄。然后若service所在的进程没有启动,则先启动进程,进程启动完了之后,s...原创 2020-02-11 11:00:43 · 434 阅读 · 0 评论 -
service的启动过程
疫情似乎仍然没有好转的迹象,邻居被查出来感染上了病毒,搞得人心惶惶的。待在家里啥也做不了,就好好学习吧。今天看了下service的启动过程,然后将其捋一捋加深印象。1.service的启动流程如下图所示为service的启动流程我们可以看到,我们调用的startService是ContextImpl的startService方法,然后会远程调用AMS,AMS再调用ActiveServic...原创 2020-02-06 22:32:25 · 686 阅读 · 0 评论 -
framework当中的单例模式
最近看了一些framework的代码,发现里面用到了一些单例模式,挺有意思的,我们在自己的项目当中也可以借鉴。1.进程内的单例首先是我们最熟悉也最常用的,就是进程内的单例Singleton是一个抽象类,里面有一个抽象函数create,我们只需要继承Singleton,然后实现其抽象函数就可以实现单例模式了。这样可以帮我们节省很多的代码。public abstract class Singl...原创 2020-02-03 22:11:07 · 341 阅读 · 0 评论 -
IdleHandler原理分析
1.使用方法及场景之前做过冷启动优化,在冷启动的场景有很多的任务其实并不需要马上启动,通常的做法就是做一个延迟启动,如下所示Handler mHandler = new Handler();mHandler.postDelayed(() -> { //do something}, 1000);将任务延迟启动1000ms,但是这个延迟启动的时间不好确定,只能是自己预估的,对...原创 2020-02-02 21:13:54 · 1907 阅读 · 0 评论 -
Android屏幕的刷新机制
最近的冠状病毒搞得人心惶惶,待在家里面也没啥事,正好趁这段时间学习一下。了解一下Android屏幕的刷新机制对于我们解决应用卡顿也有帮助。1.屏幕刷新机制1)屏幕显示首先我们看下Android屏幕的显示原理,如下图所示应用需要界面重绘时,会向系统申请buffer,拿到buffer之后会将图像信息写入buffer当中提交给系统,然后屏幕从缓冲区拿到图像数据进行显示。Android手机一般...原创 2020-02-01 21:45:27 · 2317 阅读 · 0 评论 -
一文搞懂ANR
1.ANR的定义ANR(Application Not Responding):应用无响应即主线程在特定的时间内没有完成特定的事情,就会产生ANR。在Android当中有以下几种ANR的类型:KeyDispatchTimeout,input事件在5秒内没有处理完;ServiceTimeout,前台service在20秒内,后台service在200秒内没有处理完;BroadcastT...原创 2020-01-18 15:17:36 · 1432 阅读 · 0 评论 -
徒手撸一个注解框架
运行时注解主要是通过反射来实现的,而编译时注解则是在编译期间帮助我们生成代码,所以编译时注解效率高,但是实现起来复杂一点,运行时注解效率较低,但是实现起来简单。首先来看下运行时注解怎么实现的吧。1.运行时注解1.1定义注解首先定义两个运行时注解,其中Retention标明此注解在运行时生效,Target标明此注解的程序元范围,下面两个示例RuntimeBindView用于描述成员变量和类,...原创 2020-01-18 12:44:17 · 489 阅读 · 0 评论 -
App里面有几个context?
1.Context的继承关系想要弄清楚这个问题,我们得先搞清楚Context的继承关系,如下图所示Context是一个抽象类,应用里面的Application、service和Activity均是其子类。而对于ContextWrapper来说,所有Context的具体实现均交由ContextImpl,这里用到了桥接模式。public class ContextWrapper extends...原创 2020-01-08 18:32:31 · 1176 阅读 · 0 评论 -
回调的方式使用startActivityForResult
问题最近遇到了一个很有趣的问题,为什么不能够用回调的方式使用startActivityForResult呢?如果我们想要用回调的方式使用,有什么问题?首先我们看一下目前官方的使用方式,如下图所示其实这个流程很复杂,很不符合高内聚的原则,特别是如果页面的请求很多就会变成如下的情况 protected void onActivityResult(int requestCode, int...原创 2019-12-18 19:36:17 · 771 阅读 · 0 评论 -
常见的内存泄漏场景分析
博主最近遇到了很多内存泄漏的问题,其实说白了,在Android里面的内存泄漏最多的就是activity或者fragment对象,当他们执行了ondestory周期函数之后,内存当中的对象却得不到释放,因而造成了内存泄漏。1.内存泄漏的原因2.常见的内存泄漏场景分析2.1 匿名内部类或者内部类持有持有2.2 回调函数持有2.3 AsyncTask2.4 Handler2.5 单例或者...原创 2019-12-15 12:11:49 · 1160 阅读 · 2 评论 -
Android当中的序列化
序列化序列化:把对象转换成为字节序列的过程; 反序列化:把字节序列转换成为对象的过程; 当使用Intent或者Binder传递对象的时候,需要将对象序列化。在Android中有两种方式可以将对象进行序列化,第一种是Serializable,另一种是Parcelable。Serializable使用Serializable可以很简单的将对象进行序列化,只需要继承这个接口,并加上s...原创 2018-04-16 17:27:11 · 387 阅读 · 0 评论 -
自定义控件一
自定义控件主要分成三种,1.完全自定义的控件;2.对当前的控件进行扩展;3.对当前的控件组合。 首先看第一种,完全自定义控件。以MyCircleImageView为例来说明自定义控件的创建方法。 先来看看MyCircleImageView 的效果,如下图所示,将一幅图片显示为圆形,并可以在边缘加上自己设定的颜色。 创建的过程大致分为以下几步:原创 2017-01-08 13:31:31 · 242 阅读 · 0 评论 -
adapter优雅的实现方式
最近博主在前人留下的代码当中发现到了adapter和viewhodler的实现方式,觉得很优秀,比自己实现的优雅很多,觉得自己以前的实现真的非常的丑陋。1.去掉ViewHolderlistview是个很常用的控件,为了复用view,我们经常会定义一个ViewHolder,例如下面的代码 public class ViewHolder { public TextView...原创 2019-08-17 13:06:15 · 259 阅读 · 0 评论