继续总结本司机在工作过程中涉及到的一些小知识点或小的技巧,其中有代码片段,也有知识点,经验总结和分享。因为工作比较忙,真的没法保证每天都有一篇公号文章发出,所以标题再叫“每天一点小知识”就不太合适了,因此改名为“小知识集锦”。后续使用这个名称,继续为大家总结各种小知识或技巧。
1、Drawable和Bitmap区别
Bitmap - 称作位图文件(Bitmap),扩展名可以是.bmp或者.dib。位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2、4、8、16、24和32位色彩。例如,一幅1024×768分辨率的32位真彩图片,其所占存储字节数为:1024×768×32/(8*1024)=3072KB。
位图文件图像效果比较好,但是是非压缩格式的,需要占用较大存储空间,不利于在网络上传送。jpg格式则恰好弥补了位图文件这个缺点。
Drawable -是 Android平台通用的图形处理对象,它可以装载常用格式的图像,比如 GIF、PNG、JPG,以及 BMP,另外还提供一些高级的可视化对象,比如渐变、图形等。
2、Android编译器一点知识
最近在调试一些开源项目时遇到如下报错,
Error:Jack is required to support java 8 language features. Either enable Jack or remove sourceCompatibility JavaVersion.VERSION_1_8.错误解决
经过在网上查找资料,找到一个知识点需要跟大家普及一下。
2016 年 3 月,Google 向外界发布了 Android N 的预览版的同时,指出 Android N 增加了一项的新特性,这个特性是一项新的工具链,它与 Android 生态圈的所有开发者关系,即 Jack & Jill 编译器的引入。我们知道,Android一直依赖 Sun/Oracle 的 Java 编译器达十年之久,而Google和Sun/Oracle一直在为Java的版权问题打官司,所以,Google研发了自己的Java编译器--Jack。Jack 是 Java Android Compiler Kit 的缩写,它可以将 Java 代码直接编译为 Dalvik 字节码,可以进行 Minification, Obfuscation, Repackaging, Multidexing, Incremental compilation等工作。它可以取代 javac/dx/proguard/jarjar/multidex 库等目前已有的这些工具。
而Android N 7.0(API24)在对JAVA8的支持上,采用了新的编译器。所以这个变异错误的解决方法是在app的gradle文件defaultConfig 段中,增加如下声明语句,
jackOptions {
enabled true
}
即可解决问题。
参考官网定义如下,
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
注意: 需要使用Android N 也就是API24
3、Canvas 和和 Paint 的关系
Canvas - 画布。
我们可以看作处理工具,使用其提供的方法可以管理 Bitmap、或Path 所在的图形对象,同时它可以配合 Matrix 矩阵类给图像做旋转、缩放等操作,以及可以进行裁剪、选取等操作。
Paint - 画笔。
可以把它看做一个画图工具,比如画笔、画刷。用它可以设置画图时的字体、颜色、样式等。
4、插件化和热修复的区别
这两个概念对于新手来说,比较容易混淆,这里简单介绍一下二者的区别。
实际上,两者的表现并不相同,而且差别也较明显,虽然有些框架实现上可能有相同之处,比如利用ClassLoad进行hook等。
插件化或者叫组件化的目的是为了减小模块耦合,方便在项目体量变大之后实现更好地团队协作。说白一些就是让你把部分功能提取出来,放到插件里面,而不是一股脑都放到主APK里面,等你需要用到这个插件对应的功能的时候再把它下载下来,这样可以充分减少你主APK的大小。还有一个好处是可以灵活扩展功能,比如版本迭代,引入新的功能。
热更新或者热修复主要目的是不用重新下载和安装新的apk,使用户可以在无感知的情况下修复线上的问题,避免了应用在遇到问题后或者严重bug后频繁发布新版本。
5、比较新和有权威的插件化框架
插件化或组件化:
DroidPlugin -- 360团队出品
质量有保证,成功案例——360手机助手
Replugin -- 360出品
2017年06月30日开源,360 公司几乎所有的亿级用户量的 APP ,以及多款主流第三方 APP ,都采用了 RePlugin 方案
Small--wequick推出的框架
轻巧的插件化框架,酷狗音乐等著名开发团队在使用。
Atlas--阿里框架
淘宝开发和实用的组件化开发框架。
VirtualAPK--滴滴
2017年6月3号开源,良好的兼容性,且入侵性较低,可以作为加载耦合插件方案是较好选择。
除了以上,还有写比较老一些的或者个人开发者框架如,AndroidDymnamicLoader,dynamic-load-apk,CJFrameForAndroid,direct-load-api。
6、比较有名的热修复框架
Weex--阿里
不仅可以实现热修复,还支持跨平台。
andfix(或hotfix)--阿里
2015年下半年开源,提供了一种运行时在Native修改Filed指针的方式,实现方法的替换,达到即时生效无需重启。
dexposed--阿里
阿里大部分App客户端采用的热修复、线上调试能力的框架。
Sophix--阿里
2017年阿里新开源的框架,Sophix 可以说是博采众长,前面提到的Tinker及AndFix 都在某一方面存在缺陷。
Robust--美团
Robust 兼容性与成功率较高,但是它与 AndFix 一样,无法新增变量与类只能用做的 bugFix 方案。
QQ 空间超级补丁方案--腾讯
采用Dex分包机制实现,让修复后的类替换原有的类。
Tinker--腾讯
它是微信官网的Android热补丁解决方案
7、UID和PID区别
UID是用户ID。每个应用程序只有一个。
Android中的UID和计算机不一样,计算机指的是每个用户都具有一个Uid,而Android中每个程序都有一个Uid,默认情况下,Android会给每个程序分配一个普通级别互不相同的 Uid,Android规定只有Uid相同的组件才可以互相调用,因此同一个应用下的Activity是可以互相调用的。
可以通过读取文件data/system/packages.list来查看应用对应的UID。
也可以通过如下代码获取UID,
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ApplicationInfo appinfo = getApplicationInfo();
List run = am.getRunningAppProcesses();
for (RunningAppProcessInfo runningProcess : run) {
if ((runningProcess.processName != null) && runningProcess.processName.equals(appinfo.processName)) {
uid = String.valueOf(runningProcess.uid);
break;
}
}
PID是进程ID。每个进程对应一个ID,但一个应用可能会有多个进程,因此应用的PID并不是唯一的,它可能会有多个。
可以通过如下shell指令查看应用对应的PID。
ps|grep XXX
XXX表示程序的包名。
8、模拟产生点击事件
有些同学不知道,在Android原生系统中有一个input工具,位于/system/bin目录下,国内大部分国产手机是保留这个二进制可执行文件的,而有些手机却将其阉割掉了。它的使用方法如下:
input keyevent xxx<按键名或者按键值>
xxx指具体的事件,如KEYCODE_BACK,表示一个返回键,对应的值为3,再比如KEYCODE_HOME模拟一个home键。按键名或者值可以从官方文档查询,只要是以KEYCODE_开头的都可以。
但是这个指令的执行需要root权限才行。
9、如何判断activity是否已经被销毁
一般我们使用activity.isFinishing()方法来判断activity是否已经被销毁,若Activity被结束,这返回true,否则的话返回false。但是在实际的项目中还是有问题,需要增加activity.isDestoryed()方法来判断activity是否被销毁,但是isDestoryed()方法支持的最低版本为Level 17,因此这个方法也不是太靠谱?
官方给出一个方法,
FragmentManager的API doc 中有这样的定义:
/**
* Returns true if the final {@link Android.app.Activity#onDestroy() Activity.onDestroy()}
* call has been made on the FragmentManager's Activity, so this instance is now dead.
*/
public abstract boolean isDestroyed();
因此可以借助FragmentManager对象来判断,即
if(fragmentManager.isDestroyed) return;
10、Opus文件格式
前一段时间协助遥控器端调节智能语音遥控器,需要将遥控器端用户输入的语音数据由遥控器的智能芯片通过蓝牙BLE传输给盒子端,然后盒子端进行解码后用来识别,从而控制盒子的操作。我们使用的这个芯片支持三种语音格式,broadvoice,adpcm和opus这三种格式。于是对opus进行了一下了解,以下内容来自于网上。这里带大家了解一下这种音频压缩格式。
Opus编码器 是一个有损声音编码的格式,由互联网工程任务组近来开发的。Opus 格式是一种声音编码格式,并且是一个开放的格式,使用上没有任何专利或限制。它前身是celt编码器。在当今的有损音频格式争夺上,拥有众多不同编码器的AAC格式打败了颇有潜力的Musepack、Vorbis等格式,而在Opus格式诞生后,情况有所变化。通过诸多的对比测试,低码率下Opus完胜曾经优势明显的HE AAC,中码率就已经可以媲敌码率高出30%左右的AAC格式,而高码率下更接近原始音频。