
Android
文章平均质量分 67
风语
这个作者很懒,什么都没留下…
展开
-
关于Android端相机应用涉及到的技术
目前AI视觉以及短视频相关的应用都和相机有关,涉及到相机的调用,Surface渲染,视频录制等功能,这里做了一个Demo项目,基本包含了Android相机应用涉及的所有技术。https://github.com/dingjikerbo/Android-CameraAndroid Camera Demos一、相机预览序号项目名称内容简介1GLSurfacePrevi...原创 2018-12-28 20:47:32 · 639 阅读 · 0 评论 -
Android蓝牙源码分析——BTA层消息分发
这里BTA是Bluetooth Application的缩写,从上层下来的请求都要经过这个BTA层,通过发送消息的方式将请求丢到BTA层中处理。这个发送消息的函数定义在bta_sys_main.c中,如下:void bta_sys_sendmsg(void *p_msg){ GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_ms原创 2016-09-03 18:15:46 · 6102 阅读 · 0 评论 -
Android蓝牙源码分析——Gatt连接(一)
本文将重点描述Android蓝牙GATT连接的大致流程,不会过多地纠缠代码细节,只为了从架构上梳理清楚,为接下来深入研究底层机制奠定一个宏观认识。 首先建立GATT连接前,我们通常要扫描蓝牙设备,获得设备的BluetoothDevice对象,然后调用connectGatt去建立GATT连接并等待连接状态回调,接下来我们就开始分析这一过程,首先看看connectGatt的实现:public Bl原创 2016-08-21 19:32:33 · 15198 阅读 · 5 评论 -
Android蓝牙源码分析——StateMachine状态机
StateMachine有自己单独的工作线程,protected StateMachine(String name) { mSmThread = new HandlerThread(name); mSmThread.start(); Looper looper = mSmThread.getLooper(); initStateMachine(name, looper)原创 2016-08-18 10:19:46 · 4102 阅读 · 0 评论 -
Android蓝牙源码分析——关于GKI
首先以gki模块的初始化为入口,在gki_ulinux.c中,如下: void GKI_init(void){ pthread_mutexattr_t attr; tGKI_OS *p_os; memset (&gki_cb, 0, sizeof (gki_cb)); gki_buffer_init(); gki_timers_init原创 2016-08-19 09:13:23 · 6084 阅读 · 0 评论 -
Android蓝牙源码分析——Gatt写设备
BluetoothGatt中的writeCharacteristic的实现在GattService中,如下:void writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value) { gattClientWriteCharacteristicNat原创 2016-09-03 18:36:43 · 5460 阅读 · 0 评论 -
Android蓝牙之Gatt Hook
许多人可能对Hook技术有些陌生,其实从字面意思上理解这就类似一个钩子,挂在了系统中的某些地方,然后当执行流程经过该处时会被勾住,可以选择放行或截获,或做点手脚偷偷改改参数,或记录日志,或检查权限,或post到别的上下文去执行,应用场景还挺多。本文会重点讨论蓝牙相关的Hook,要全局监测所有BLE蓝牙设备的操作,对于不那么活跃的设备我们会断开连接并释放资源,毕竟蓝牙通信信道是有限的。那么如何全局监测原创 2016-08-27 16:32:04 · 3600 阅读 · 1 评论 -
谈动态代理在解决内存泄露中的妙用
内存泄露在Android开发中很常见,每次产品上线之前都要集中解决内存泄露问题,有的问题很明显,有的藏的很深,解决起来要颇费一番功夫,不过总的思路都是一样,就是切断引用链,让资源在该释放的时候能被及时释放。我们先看一个内存泄露的案例:public class ServiceManager { public static void bindService(final BindResponse r原创 2016-08-26 21:21:44 · 3524 阅读 · 3 评论 -
将模块service化的好处
蓝牙的所有操作最好都封装成一个service,好处是相对独立,作为一个service组件,可以指定所运行的进程,所有实现彻底和外部解耦,不管是同进程还是跨进程调用对外接口是不变的。因为APP中可能拆分成多个进程,这些进程对service的访问是统一的,不管和service是不是在同一个进程。另外放在一个service里可以保持数据只有一个操作对象,调用方来自多个进程,但是最后操作数据的只有servi原创 2016-03-09 08:04:38 · 1865 阅读 · 0 评论 -
关于Android MultiDex的问题
这段时间研究了一下Android MultiDex,这个东西乍看起来很简单,其实涉及到很多东西,本文就来讲讲这个,想到哪就说到哪。分包主要是因为包太大了,低端手机安装可能会失败,或者Dex加载的时候会崩溃,所以分成多个包,跟启动相关的放在主Dex,其余的不那么紧急的放在副Dex,然后启动的时候去动态加载。首先来看看主Dex,所谓跟启动相关的主要就是四大组件,所以四大组件直接引用到的类都要放在主Dex原创 2016-03-06 19:09:05 · 4945 阅读 · 0 评论 -
一个关于Java的装箱与拆箱的bug
先看如下代码:public class TestBoxing { public static void main(String[] args) { int result = getProp("hello", new IPropGetter<Integer>() { @Override public Integer getProp(B原创 2016-05-11 10:48:12 · 1035 阅读 · 0 评论 -
一个让我很无语的bug
被一个诡异的bug折腾了半天,当找到原因时哭笑不得。先看如下代码,大家分析一下打出来的会是什么:public class TestDebug { private static HashMap<String, BleDeviceProp> mPropCache = new HashMap<String, BleDeviceProp>(); public static void main(S原创 2016-05-12 20:04:05 · 1236 阅读 · 1 评论 -
由两个bug引发的对Java类加载时机的思考
有一个单例类是这么写的:```Java public class BluetoothManager {private static BluetoothManager sInstance;public static BluetoothManager getInstance() { if (sInstance == null) { synchronized (Bluetooth原创 2016-05-07 19:00:36 · 1765 阅读 · 1 评论 -
谈动态代理在Android插件中的一些用法
我们为设备的插件提供了一系列接口,现在想记录下每个接口的调用情况,通常的做法是在每一个接口函数里都加上一堆上报的代码,这不是不可以,只是有些麻烦了,以后接口里每新增一个函数,就得记得加上上报,对于我这种记性不好的人来说,忘加的概率很大,所以如果有一劳永逸的办法那就好了,以后新增函数都会自动上报。先给出当前接口的形式,如下:public abstract class AbsBluetoothManag原创 2016-04-27 15:15:22 · 1803 阅读 · 0 评论 -
Android蓝牙源码分析——Gatt的Connection ID
我们注意到GattService中的所有GATT操作都会带两个参数,一个是clientIf,另一个是address,拿到这两个参数后,都会调用Integer connId = mClientMap.connIdByAddress(clientIf, address);获取对应的connId,然后之后的操作都是以这个connId为Key。我们来看看这个connId的生成过程,在ContextMap中,原创 2016-09-04 17:21:48 · 3143 阅读 · 0 评论 -
Android蓝牙源码分析——GKI定时器
GKI定时器初始化在gki_ulinux.c中的GKI_init中,如下:void GKI_init(void){ ...... struct sigevent sigevent; memset(&sigevent, 0, sizeof(sigevent)); sigevent.sigev_notify = SIGEV_THREAD; sigevent.sig原创 2016-09-08 13:02:33 · 2666 阅读 · 1 评论 -
从Camera源码看如何从Jni回调到Java层
通常设备层有数据或事件要通知到应用层是通过回调来完成的,可以采用的方式是直接调用java层类静态函数,或者调用java层某个对象的普通函数,涉及几个问题:1,内存泄露,引用问题2,多线程问题首先研究一下Camera的实现,首先打开Camera返回一个Camera对象,setPreviewCallback传入了一个callback,这个callback没有传入jni层,只是在Camera对象...原创 2018-11-23 20:45:15 · 1011 阅读 · 0 评论 -
Android BufferQueue原理分析
在Android中,BufferQueue是Surface实现本地窗口的关键,驻留在SurfaceFlinger进程中进行服务,下面从BufferQueue的结构开始分析,class BufferQueue : public BnGraphicBufferProducer, public BnGraphicBufferConsumer, ...原创 2018-11-23 20:48:25 · 4943 阅读 · 1 评论 -
Android视觉应用性能优化
计算机视觉在移动端的应用,典型的如手势识别,人脸识别,流程都差不多,都是利用移动端的相机采集数据,丢给算法层,根据识别的结果来做一些业务,中间可能还要做一些图形的渲染。本文主要讨论这中间涉及到的一些问题以及优化的思路,算是对过往工作的总结吧。大致问题有以下五点:一,相机采集数据的格式是NV21,而算法层所需的格式是RGB,这中间需要转换,对于每秒30帧,每帧1920*1080的图像转换的耗时还...原创 2018-11-23 20:50:05 · 400 阅读 · 0 评论 -
Android Camera源码分析
回顾这半年做的项目基本都跟Camera有关,从手势识别控制空调,到人脸识别的门禁,都是围绕相机的数据处理和渲染。这里相机不限于本地的相机,还包括远程的RTSP相机,要将数据流拉到本地进行渲染。这两天好好读了一下Camera的源码,大概理清了整体架构,总结了一下,其实没多少东西,Android的各个模块都差不多,都是有个系统服务,然后Java封一层,Native封一层,Java层和Native层的...原创 2018-11-23 20:55:40 · 3849 阅读 · 0 评论 -
NEON优化——OpenCV Resize双线性插值
算法要点一、基本原理具体原理可以自行搜索,这里只大致描述一下,目标图像上某一个点按比例映射到原始图像上某一点,不过通常计算得到的原始点坐标不是整数,最近邻的做法是向下取整,而双线性差值的做法是取与该坐标最接近的上下左右四个点来线性加权,在放大的时候不会像最近邻那样锯齿严重,但是计算量会大不少。这里要注意的是加权分为两个维度,横向和纵向。此外,边界的处理也要注意。二、优化思路这里核心的优化思...原创 2018-11-23 20:59:50 · 7644 阅读 · 5 评论 -
NEON优化——OpenCV WarpAffine双线性插值
算法要点warpAffine双线性插值和最近邻的区别根据目标图像的某点坐标算出原始图像对应的点坐标后,最近邻是向下取整,双线性插值需要获得相邻的四个点坐标以及纵横方向的权重最近邻直接拷贝原始图像点即可,双线性插值需要横竖加权很显然计算量要比最近邻大一些,但是效果会更好,对于放大的情况没有明显的锯齿。优化要点在计算偏移时基本和最近邻相同,同样要考虑异常情况和越界读的问题,另外要注意...原创 2018-11-23 21:04:34 · 3235 阅读 · 0 评论 -
NEON优化——OpenCV WarpAffine最近邻
warpAffine一种典型的应用场景是将camera拍到的图像中人脸抠出来,通过变换输出一张正脸,然后再做一些人脸识别,关键点检测之类的运算。所以通常是输入尺寸固定,输出尺寸也固定,变的是转换矩阵。最近邻的优势是计算量小,速度较快,问题是放大的情况下锯齿较明显,对于通常是缩小的应用场景最近邻是比较合适的,如果希望在所有的场景下有相对更好的效果,可以考虑双线性。算法要点warpAffine和...原创 2018-11-23 21:07:30 · 3034 阅读 · 1 评论 -
VLC卡死内存溢出解决
SurfaceTexture不直接显示图像流,而是转为GL外部纹理,因此可用于图像流数据的二次处理(如Camera滤镜,桌面特效等)。比如Camera的预览数据,变成纹理后可以交给GLSurfaceView直接显示,也可以通过SurfaceTexture交给TextureView作为View heirachy中的一个硬件加速层来显示。首先,SurfaceTexture从图像流(来自Camera预览...原创 2018-11-23 21:08:50 · 9178 阅读 · 0 评论 -
移动端算法加速总结
性能加速,即对于给定的输入,用更短的时间获得我们想要的输出。总的来说有两个思路:降低计算量提高计算速度。各种优化技术基本上都是围绕这两点展开的。降低计算量优化算法或模型,使得用更少的计算量就可以达到同样的效果简化算法或模型,使得在牺牲部分准确度或效果的情况下速度能有大幅提升,看应用场景算法本身不变,优化实现。或将算法中可能存在的重复计算抽离出来,结果进行复用,或其它...原创 2018-09-04 18:03:44 · 1786 阅读 · 1 评论 -
VLC RTSP视频播放终极解决方案
VLC播放RTSP视频流遇到的问题摄像头是RTSP协议的,需要在Android端实时显示摄像头视频流,这里采用了开源的VLC播放器,可能会有如下需求: 一、有截屏的需求 二、有屏幕录制的需求 三、视频本来是横的,但是现在要竖屏显示,如何旋转视频,另外旋转后视频会拉伸,因此需要截取一段显示 四、显示的视频可能需要做额外处理,比如识别出人脸后框出来先说说直接用VLC播原创 2017-10-12 20:23:27 · 17741 阅读 · 3 评论 -
智能家居Android技术系列之——蓝牙那些事
一、蓝牙能做些什么近距离通信:收发数据,指令控制蓝牙设备通常是穿戴式,便携式,室内或车内等,正是因为蓝牙适用于近距离通信的特点。如果要做远距离通信,则可借助于Wifi,用手机或网关做中转。广播消息、通知蓝牙可以以一定的周期发送广播,手机端接收到广播后,解析广播包,可做设备识别、配对,事件通知以及指令控制等。低精度定位根据设备的信号强度,可以估算出大概方位和距离。二、Android平台的蓝牙A原创 2015-10-19 20:26:14 · 9855 阅读 · 1 评论 -
Android内存优化另辟蹊径
研究preloadedDrawables是因为要在单独进程中启动一个service,而这个service的内存占用有严格限制,经过研究发现内存占用中很大一部分是preloadedResources,而service是后台运行无需界面的,所以这块内存可以清理掉。系统没有提供现成的接口,所以需要通过反射实现。首先,我们做一个实验来验证效果:public class MainActivity extend原创 2016-01-19 08:56:43 · 2100 阅读 · 0 评论 -
Retrofit源码解析
Retrofit代码不多,设计得很精巧,非常值得借鉴。首先看Retrofit是如何创建的:public <T> T create(final Class<T> service) { return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service}, new Invoc原创 2017-01-16 12:02:23 · 719 阅读 · 0 评论 -
Android BLE设备蓝牙通信框架BluetoothKit
这个框架源于目前一个智能家居APP项目,是蓝牙部分基础模块,用于蓝牙设备扫描、连接、通知等。由于目前接入的蓝牙设备大多为低功耗蓝牙设备,所以本框架暂不支持经典蓝牙的连接。项目地址: https://github.com/dingjikerbo/BluetoothKit先介绍本框架的特点: 一、支持经典蓝牙和BLE蓝牙混合扫描,支持自定义扫描策略 作为智能家居平台,接入的设备包括经典蓝牙和BLE,原创 2016-08-29 11:49:17 · 27145 阅读 · 64 评论 -
getSystemService的奇怪问题
先看如下代码,这两个PowerManager不是同一个对象,PowerManager manager = (PowerManager) getSystemService(POWER_SERVICE);PowerManager manager2 = (PowerManager)getApplicationContext().getSystemService(POWER_SERVICE);只能从内核源原创 2017-03-28 20:45:22 · 2373 阅读 · 0 评论 -
ProgressButton的实现
一向对UI不是太感兴趣,不过项目中遇到了还是得去做,做这个ProgressButton还是费了不少功夫,不过效果还可以,这里先记下,以后可能还会用到。只贴代码,原理就不多说了。public class ProgressButton extends Button { public static final int MODE_BUTTON = 0; public static final i原创 2017-03-30 10:21:10 · 1432 阅读 · 0 评论 -
谈Android PowerManager的Hook技术
在插件中,需要禁止插件调用系统原生接口持有WakeLock,Hook技术是不错的解决方案。通过阅读系统源码,可以了解到PowerManager持有WakeLock操作最后都通过Binder跨进程调到系统服务中,我们只要拦截这个Binder的所有调用即可。思路是先通过反射拿到这个IPowerManager的Binder,然后动态生成该Binder的代理对象,再覆盖原有的Binder即可。public原创 2017-03-29 11:20:15 · 1504 阅读 · 5 评论 -
采用Parcelable实现对象的深度拷贝
public class ParcelHelper { public static <T> T copy(Parcelable input) { Parcel parcel = null; try { parcel = Parcel.obtain(); parcel.writeParcelable(input, 0)原创 2017-08-03 11:52:58 · 3270 阅读 · 0 评论 -
如何拦截Activity的启动(二)
本文我们将以一个工程为例,验证Hook Activity的可行性。我们的目标如下: - 指定插件Apk路径,启动插件 - 插件内部可启动Activity - 插件可作为独立App启动首先新建插件工程,和正常APP一般无二,没有任何特别的地方。所有的Activity都是从android.app.Activity继承,可以安装并运行。接下来新建宿主工程,并将插件Apk用adb push到宿主原创 2016-02-16 18:21:11 · 2767 阅读 · 2 评论 -
如何拦截Activity的启动(一)
要把正常的apk当做一个插件启动起来,首先我们拿到这个插件的Launcher Activity,然后启动宿主APP中的Proxy Activity,在这里面调用插件的Activity的生命周期回调。结果会报Null Pointer Exception,原因在于调用插件Activity的onCreate时会调用到super.onCreate,里面需要用到的一些上下文没有初始化过,所以为null。这里原创 2016-02-15 13:57:09 · 3229 阅读 · 0 评论 -
关于Handler的拦截
为什么要Hook Handler?Android系统中存在大量Handler,我们要改变系统的某些行为就需要Hook掉一些关键节点的Handler,为此,我们要清楚Handler的工作原理。先做一个实验来看看Hook Handler的效果,如下:public class MainActivity extends Activity { private Button mBtnShow; p原创 2016-02-16 11:14:22 · 2825 阅读 · 0 评论 -
关于Android studio混淆遇到的问题
先给出官方文档链接: https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#manual/index.html混淆后,如果要查看混淆效果,有两种方式: 一、反编译dex或者jar文件,如果要查看so,可以objdump -tT libblecipher原创 2016-01-18 20:16:12 · 4827 阅读 · 0 评论 -
插件待研究的问题
如何满足以下条件: 一、运行对象可以单独运行,也可以作为插件运行,不需要做额外的修改 二、插件之间,插件和宿主可以互相通信,包括跨进程通信 三、插件完全透明,抽象成服务,用URI表示服务地址,宿主做DNS和权限控制原创 2015-11-15 21:17:51 · 634 阅读 · 0 评论 -
Android内核源码阅读环境配置
一般读源码都用source insight,只是这个软件貌似只有windows版的,而且界面我看得很不习惯。最近发现可以用sublime + ctags来看源码,其中ctag是作为sublime的插件来安装的,而sublime是支持各个平台的,包括windows,linux和mac。安装流程网上都能搜的到,我在这里大致说一下。首先安装sublime,然后在sublime里安装package cont原创 2015-12-20 21:40:55 · 905 阅读 · 0 评论