自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

天花板的随笔

人与人之间最小的差距是智商,最大的差距是坚持!记录点滴,稳步成长!

  • 博客(151)
  • 资源 (3)
  • 问答 (5)
  • 收藏
  • 关注

原创 卡顿优化总结

首先在performLaunchActivity的时候会创建PhoneWindow,然后在setContentView的时候创建DecorView,并加载XML布局文件到DecorView的contentParent这个父布局上,在onResume的时候WindowManagerGlobal在addView方法中创建ViewRootImpl,然后执行ViewRootImpl的setView方法,然后ViewRootImpl会执行requestLayout方法。复制算法:把内存分成两块,只使用其中一块内存。

2024-04-09 10:53:07 990

原创 启动性能优化

由于冷启动一个新的应用,会存在一定的耗时,Google为了避免让程序看起来有延迟的情况出现,即用户点击图标后就会有即时的响应,会在App创建的过程中先显示一个空白页作为过渡。使用Android Studio自带的Profile,选择Trace Java Methods,然后开启Record,或者在Run 的时候选择Profile,就可以生成一段时间内的方法调用栈记录文件。X轴:方法调用的时间占比,或者更精确地叫抽样数,即X轴越宽,则被抽中采样的次数越多,方法所消耗的时间就越长。

2024-03-25 21:04:25 998

原创 Handler屏障消息和IdleHandler

首先我们需要知道的是,我们正常往handler发送的消息都是同步消息,即Message中的变量isAsynchronous是false的,只有当isAsynchronous的值是 true,才表示是一个异步消息。在获取下一条执行消息的时候,如果存在target为null的消息,那么就是屏障消息,这个时候会忽略掉队列里面的排在前面的同步消息,优先去任务队列里面找寻isAsynchronous为true的移步消息,并返回。屏障消息也叫同步屏障消息,作用是提升异步消息的执行优先级的。

2024-03-25 19:27:05 407

原创 算法题汇总

2.链表反转中间段的节点。6.锯齿分层遍历二叉树。

2024-03-18 16:35:41 197

原创 Java多线程算法总结

wait()会释放对象锁;notify()是起到唤醒等待对象锁的线程的作用,并不会马上释放锁,但是一旦同步代码块执行完毕后,就会释放对象锁。1.三个线程同时运行,依次打印ABC,一共打印10次。

2024-02-28 16:32:46 222

原创 Kotlin函数和对象

扩展函数在语法上看起来就像是类的原生方法一样,但实际上是在类的外部定义,因此,它不能访问类的私有或受保护的成员,同时也不能在类的内部调用。拓展函数可以搭配高阶函数一起使用,组成拓展高阶函数。当函数被标记为inline时,表示这是一个内联函数,编译器会尝试在调用该函数的地方直接插入函数的实现代码,而不是生成调用函数的代码,从而消除函数调用的开销。在kotlin中函数也是有类型的,跟整型、字符串类型是同样的性质,函数类型就是将函数的“输入参数类型”和“返回值类型”的抽象表达,如(Int,Int)-> Int。

2024-02-19 20:30:00 688

原创 Android内存分析

这里就是对包名为com.example.demo这个进程在/data/local/tmp/目录下生成了一个demo.hprof的文件。可以在运行的设备上,使用adb命令生成 .hprof文件,表示在执行命令的那一刻,该进程的内存情况。建议在最开始泄漏前和泄漏之后各采取一次,做对比。

2024-02-19 19:51:20 262

原创 kotlin协程学习总结

既然协程挂起可以实现切线程,那肯定就不会阻塞当前的线程了。至于为什么叫非阻塞式挂起,是因为在实现协程代码的时候,是使用了看似阻塞式的书写方式,但是又实现了非阻塞式的效果。main {val user = suspendingRequestUser() // 耗时操作。

2024-02-19 17:52:28 460

原创 对于软件架构的思考

MVVM全称是Model View ViewModel,Model即数据模型,View指的是Activity或者Fragment,和MVP架构中的数据层、界面层意义是一样的。这里新增的ViewModel,是用来代替Presenter,和底层业务逻辑交互,并持有数据,内部通过LiveData去关联界面View和数据Model。

2024-01-15 13:11:11 387

原创 kotlin实现单例模式

类加载的时机,或者说类的初始化(两者是类加载到内存中达到可用状态的两个阶段),包括:创建类的实例对象,或者类的静态成员访问,类的反射,父类中的子类初始化的时候,虚拟机特定类。所以并不是程序初始化的时候就会加载所有的类,声明一个类型的变量时也不会加载该类,而是真的使用该类的时候才会去加载。通过伴生对象实现类似于static的静态变量,同时通过by lazy,实现了属性委托,延迟初始化,即在使用instance属性字段的时候,才会去初始化。同时,由于by lazy是线程安全的,也就实现了多线程的校验功能。

2023-10-31 13:27:06 868

原创 Android性能监测

1.使用adb top可以查看当前Android设备的CPU和内存(mem)使用情况。2.使用adb top还可以过滤查看单个进程的CPU和内存(mem)使用情况。%CPU 进程当前的CPU占用率,很可能超过100%,存在多核的情况。NI 进程的nice值,决定了CPU调度优先级,值越小,优先级越高。S 进程的状态,包括R(运行态)、S(睡眠态)、Z(僵尸态)等。PR 进程的优先级,值越小,优先级越高。ARGS 进程的包名,或者说叫进程名。VIRT 进程使用的虚拟内存大小。%MEM 进程当前的内存占用率。

2023-09-11 21:31:13 878

原创 keystore相关问题

1.SHA1和公钥的区别SHA1是一种哈希算法,用于将任意长度的数据映射为固定长度的数据,通常是160位。SHA1可以用于验证数据的完整性,例如在数字签名中。SHA1算法已经被认为不够安全,不再推荐使用,应该使用更安全的哈希算法,例如SHA-256或SHA-3。公钥是一个加密系统中的重要组件,用于实现公钥加密和数字签名。公钥由两部分组成:公钥和私钥。公钥可以公开发布,任何人都可以使用它来加密数据或验证数字签名,而私钥是保密的,只有拥有者可以使用它来解密数据或签署数字签名。在应用程序开发中,SHA1和公

2023-03-29 17:30:16 955

原创 MAC开发使用技巧

您可以通过以下步骤在 macOS 中查看所有已安装的程序:点击屏幕左上角的苹果图标,选择“关于本机”。在打开的窗口中,选择“系统报告”。在系统报告窗口中,选择“软件”选项卡,然后选择“安装的程序”子选项卡。

2023-03-01 20:18:31 641

原创 代码浅克隆

当代码仓库比较大的时候,我们直接克隆整个仓库,会失败。其实仓库大,不一定就是代码多造成的,而是由于导致的。这个时候需要使用浅克隆来分阶段、分需求来拉取代码。

2023-02-28 14:31:27 922

原创 adb命令相关

这可以找到对应包名安装文件的位置。列出所有已经安装的程序的信息。可以强制卸载对应包名的应用。kill特定包名的进程。

2022-12-08 15:32:01 893

原创 Android aar 打包事项

我们在开发中难免会遇到把现有的module变成库文件SDK的情况,aar包中不仅可以包含代码,也可以包含资源文件,是一种常用的库文件方式。引入这个库文件的作用,就是为了让我们打出的aar包中,自动包含module所依赖的其他三方库文件。'com.kezong.fat-aar’表示产物aar包会包含module依赖的库。'com.android.library’表示这个module的产物是一个库文件;当然,第三方库文件是需要放在lib文件夹下的。

2022-11-18 16:25:15 2483

原创 kotlin实践笔记

我们可以自定义访问器,如果定义了setter,那么每次给属性赋值时都会调用它。also和let的用法一致,只是返回的时候,also是返回最后一行表达式结果,而also是返回的it执行后的变量。Kotlin 提供by lazy的方式实现懒加载委托,也就是在data第一次使用的时候才开始加载。let是一个域作用函数,定义一个变量在一个特定的作用域范围内,避免写一些重复判空的操作。run是结合了let和with的用法,而apply则是结合了also和with的用法。by lazy的方式,只用于val定义的属性。

2022-09-19 15:46:32 593

原创 ubuntu命令相关

1.需要在很多日志文件中过滤打印的tag,我们有时候会使用工具软件类似nodepad++打开这些文件,然后再做搜索。但是这样子如果日志文件很多,那么导入文件就会很麻烦,不利于日志的查看。

2022-08-09 14:04:14 391

原创 Activity的创建过程源码分析

一、概述Activity的启动过程,涉及到多个进程以及跨进程通信IPC,总体的时序图如下所示,后面们会分步讲解。二、源码分析过程1.Activity A 发起startActivity,如下:会调用到Instrumentation的execStartActivity方法:这里我们看到,调用了ActivityTaskManager提供的远程接口,并且传入了一堆参数进去,主要的参数有intent、token、whoThread。intent我们都知道这是表示一个意图,也就是我们想要启动的Activi

2022-06-11 11:35:21 2881

原创 kotlin实现registerForActivityResult方式的界面跳转

在最新的Android SDK中,startActivityForResult已经被标记为过时的方法,转而使用registerForActivityResult的方式。1.为什么要使用registerForActivityResult的方式?以前使用startActivityForResult的方式,需要传递一个requestCode,在目的界面返回本界面的时候,再通过requestCode去识别是哪个请求的返回值,这样显得有些简陋和粗暴。而使用registerForActivityResult的方式

2022-02-18 09:42:08 3980

原创 Android单独打开和关闭BLE

1.常规操作经典蓝牙最近有一个功能需要使用蓝牙BLE,如果在使用之前蓝牙是关闭的状态,需要先打开蓝牙,并且在使用完之后,需要把蓝牙关闭。我们的功能是在后台服务执行,最开始使用常规的方式判断并打开蓝牙:boolean isEnableBefor = bluetoothAdapter.isEnabled(); //判断蓝牙是否打开if (!isEnableBefor) { bluetoothAdapter.enable(); //使用常规方式打开蓝牙 }这

2021-12-02 15:16:50 4021

原创 Java中:byte转换为int ,int转换为long

1.byte转换为int在Java语言中,byte 和 int都是有符号的,它们的数值都是用补码做计算的。byte的数值范围是:-128 ~ +127 。高位为1表示负数,0表示正数。如果在业务中遇到传输的数据是无符号的,就会存在问题。比如远程设备给我们传过来一个0xfe的数据:0xfe,无符号的时候表示的是254,二进制为 11111110 。但是在Java程序里面,0xfe在byte中的值却表示的是-2 ,这就会出现问题。如果用int数据类型来放0xfe,是没问题的。因为int虽然也是有符号的

2021-10-20 16:18:37 3083

原创 Android存储目录

Android存储的位置,主要是分内部存储和外部存储。1.内部存储:Android系统自带的一块存储区域,会给每个应用程序分配一个空间目录,它一般不会很大,可供应用存储少量的文件。内部存储空间始终是可用的,因此在存储应用所依赖的数据时更为可靠,而且应用程序本身也通常是存放在内部存储空间。应用使用此存储区域,不需要额外申请权限,并且该区域内的文件只有本应用可以访问。在应用中要获取内部存储空间,需要用到Context上下文对应的API:context.getFilesDir()文件的位置是在:/d

2021-10-13 10:18:01 1354

原创 Android HeadSetClient端通话的传递

Android源代码中,如果通话状态有改变,会沿着这样的顺序传递:蓝牙chip >> HCI接口 >> BlueDroid协议栈 >> Bluetooth >> 广播传递 >> Telecom ,下面重点介绍一下数据在Bluetooth内的传递过程:通话状态有改变,会通过NativeInterface这个类里面的onCallSetup方法回调通知:public class NativeInterface { ......... p

2021-09-24 14:59:22 1302

原创 Android HeadSet端的通话建立过程

蓝牙的HFP协议定义了两个角色,一个是HF端,如蓝牙耳机、车机端等免提设备;一个是AG端,通常指的就是手机端。在Android系统里面,也有对应的两个Profile,HF端对应HeadsetClient Profile,而AG端对应Headset Profile。下面我们就通过拨号指令,梳理Headset端的处理过程。首先来看一下整体的流程图:1.首先拨号的指令在HF端发出,经过两端蓝牙chip的信号传递,到达AG侧的协议栈中,在协议栈经过解析之后,已经明确了此为一个拨号的请求,于是就会通过JNI层

2021-09-22 14:50:23 1293

原创 Android BLE开发实战和总结

最近项目中需要使用到BLE通信,用来实现车机端和另外一个设备的信息交互(称为从设备)。在做了一番了解之后发现,Android对于BLE的封装已经很到位了,使得BLE的功能相对于整个Android蓝牙来说就是一个Profile,使用起来已经很方便。一、基本概念:1.概述BLE全称为Bluetooth Low Energy,低功耗蓝牙技术,用以解决传统蓝牙(BR)功耗过高的问题。其中定义了两个角色,一个是主设备(Master),如手机、车机等处理能力较强的设备;一个是从设备(Slave),通常是智能手环、

2021-09-09 17:54:28 1697

原创 BluetoothHeadSetClient的framework修改

1.概述:BluetoothHeadSetClient是Android系统中对于HFP协议HF端的定义,HFP协议AG端则是BluetoothHeadSet相关的定义。通常情况下,手机对应的是AG端;而类似于车机、蓝牙耳机等设备,对应的是HF端。Android原生的SDK是针对手机开发的,所以会发现在原生API中找不到BluetoothHeadSetClient相关的定义,这个时候我们就要去源码一探究竟了。2.修改源码可以看到源码中对BluetoothHeadSetClient是做了隐藏的:(an

2021-08-04 14:55:29 1070 2

原创 Settings的蓝牙搜索过程分析

1.界面触发扫描在Android原生的系统设置里面,点击添加新设备的“加号”按钮后,就会触发BluetoothScanningDevicesGroupPreferenceController的状态改变,然后去开启扫描:protected void updateState(PreferenceGroup preferenceGroup) { super.updateState(preferenceGroup); if (shouldEnableScanning()) {

2021-07-28 11:23:51 580

原创 Android系统开启蓝牙源码分析(下)

上篇博客我总结了Android打开蓝牙分为4个阶段,第一阶段就是打开蓝牙的方法从APP调到systemServer再到Bluetooth协议栈,最后走到了hardware蓝牙硬件设备。如下图绿色虚线的流程:经过了硬件的一些列操作,正真打开了蓝牙设备,下面继续分析。第二阶段:(对应图中蓝色虚线流程)在蓝牙打开成功之后,JNI层会通过JniCallbacks的stateChangeCallback方法把消息回调给AdapterService处理,AdapterService则继续把消息给到状态机处理:

2021-07-23 20:11:45 1795 3

原创 Android系统开启蓝牙源码分析(上)

Android系统的蓝牙打开过程,涉及到APP应用层、framework框架层和Bluetooth协议栈层,总体的流程图可以参考如下:可以看到,开启的流程大致分为4个阶段:第一阶段: (对应图中绿色虚线流程)应用软件调用BluetoothAdapter的enable()方法,通过Binder远程调用到BluetoothManagerService里面对应的enable方法:@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) pu

2021-07-23 15:23:09 2450 2

原创 一个很强大的Android源码在线查看网站

一个很强大的Android源码在线查看网站https://cs.android.com/

2021-07-02 16:35:19 539

原创 Android单元测试总结

一、概述:使用AndroidTest,我们可以获取到Android运行的环境,并且通过在测试文件中实例化我们需要测试的类,然后自己模拟一些参数去调用实例中的方法,来达到测试代码的目的。一个AndroidTest文件,就相当于一个运行进程一样,可以在真机上运行,并且可以把测试跑后的结果统计出来,作为研发自测重要的一个根据。二、创建测试单元我们可以针对我们代码中那些很关键的控制性类创建一个测试单元,这样创建的测试单元就可以包含很多内容。创建的方式也很简单,在需要创建的类边上进入提示,如下:点击Crea

2021-06-24 14:45:59 3833

原创 源码编译之Android.mk的那些事儿

Android.mk文件的基本属性解析1.include此命令是指引用相关的变量或者指令到本次的mk文件中。2.include $(CLEAR_VARS)因为Android编译环境规定,以LOCAL_开头的都是全局变量,因此,在定义mk里面的属性之前,需要把之前的变量值清楚掉。CLEAR_VARS实际上是引用的build/core/clear_vars.mk文件,用于清除部分以LOCAL_开始的变量(不会清除LOCAL_PATH)3.LOCAL_PACKAGE_NAME : APK名字如果是被

2021-06-22 14:48:21 631

原创 Linux磁盘挂载以及所属用户组修改

一、概述Ubuntu是Linux系统,它是天生支持多用户操作的,用户空间是在根目录下的home/username里面。可以从Other Locations 进入,可以看到自己的电脑的几个磁盘分区:这个Computer的磁盘,就是系统盘,进入之后:可以看到很多系统文件,其中的home目录里面,就是我们用户账号的空间,这个空间只有当前自己用户或者root用户可以读写。其实桌面左边的一些文件夹,就是home/user用户空间文件的快捷访问方式。现在问题来了,我的系统盘空间是有限的,如果我总是在系统盘里

2021-06-22 14:09:31 7726 2

原创 Bluetooth HFP连接过程分析

class BluetoothService extends SystemService {private BluetoothManagerService mBluetoothManagerService;public BluetoothService(Context context) { super(context); mBluetoothManagerService = new BluetoothManagerService(context);} public void on

2021-04-07 11:48:41 2439

原创 Dialog源码分析

我们先看一下Dialog的构造函数://构造函数Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) { if (createContextThemeWrapper) { if (themeResId == Resources.ID_NULL) { final TypedValue outValue

2020-11-09 10:54:18 172

原创 Activity、Window、View、ViewRootImpl的理解

概述:对于题目中的几个对象,我们可以简单地理解为Activity封装了Window,而Widnow又封装了View,而View又是通过ViewRootImpl把它添加WindowManagerService中去的。要较详细的分析,我们可以先从Activity的启动开始分析。源码分析:一个Activity开始启动的时候,会在ActivityThread中调用handleLaunchActivityhandleLaunchActivity(ActivityClientRecord r,

2020-11-09 10:04:29 552 2

原创 数字显示控件 -- 均匀长度显示

使用Android原生的TextView来显示号码存在一个问题,都是11位数的两个号码,他们的长度可能差别挺大的。这是由于TextView在显示字符串的时候,是根据文字需要的显示的宽度去测量并绘制的,数字“1”和数字“8”占用的像素宽度并不一样。如下:这个时候产品部的同事把这个问题揪出来提给了我,怎么办呢?那就自定义控件呗。效果对比如下:下面就是我自己定义的显示数字的控件,同时还可以实现选中的颜色匹配效果:下面贴出代码,由于只是在项目中用过一次,所以封装性不是很好,一些参数如文字大小、上下间隔距

2020-10-14 17:59:16 231

原创 利用贝塞尔曲线绘制水波纹动态图案

贝塞尔曲线可以通过设置很少的控制点,来绘制想要的平滑的曲线。下面是我使用贝塞尔曲线实现的水波纹效果,直接贴出关键代码public class BezierView extends View { private static final String TAG = "BezierView"; private Paint mPaint; private Path mBezierPath; private ValueAnimator valueAnimator;

2020-09-28 14:50:01 496

原创 蓝牙电话开发总结

一、 基本概念HFP协议 :蓝牙电话控制协议,如拨号,接听,拒接,挂断等操作。车机上判断是否连接上蓝牙,主要就是判断HFP协议的连接状态。PBAP协议:通讯录访问协议,主要指下载联系人,同步通话记录。A2DP协议:蓝牙音频传输协议,用来传输蓝牙音乐数据。(蓝牙电话不涉及)AVRCP协议:音视频远程控制协议,比如上下曲的控制。(蓝牙电话不涉及)二、 功能需求蓝牙设置:a.开关蓝牙 b.搜索可用设备 c.对搜索到的设备进行配对操作 d.对已配对的设备发起连接。蓝牙电话:a.同步通讯录 b.同步通话

2020-09-18 10:22:47 1676

framework.jar

开放单独打开关闭蓝牙BLE的API

2021-12-01

ksoap2-android

Android端webservice调用框架

2017-06-27

seekbar和竖向seekbar

seekbar和竖向seekbar

2017-06-16

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除