Android(二)
So 库架构选择
连微信也只有:abiFilters “arm64-v8a”
arm64-v8a: 64位支持,目前主流的版本,虽然网上很多博客都说 v7是主流版本,但是我亲自试验了很多手机,都是 arm64-v8a 的架构,测试机型包括小米5-小米9,华为 P30,华为 mate10,魅蓝2等均是 v8架构查询手机 cpu 命令行
结论:用 arm64-v8a 处理速度快
250M 减到 88M
看源码
https://cs.android.com/
http://androidxref.com/
带 stub 就是 class 文件,反编译的,看不了
buildToolsVersion 和 TargetSdkVersion
compileSdkVersion:应用程序编译时使用的 Android SDK 版本
minSdkVersion :应用程序所支持的最低Android平台版本
targetSdkVersion 的作用:应用的兼容模式。它表明你的应用程序是针对该版本进行开发和测试的,并且遵循该版本的行为和特性。通过指定 targetSdkVersion
,你向系统表明你的应用程序是为目标平台版本进行优化的,系统会根据该版本来确定应用程序的运行环境和默认行为,以提供最佳的兼容性和体验。
TargetSdkVersion 设为23那么是按6.0设置的(运行时权限),小于23是按6.0以前的方式
目前项目:
1 |
|
31:android12
Android 6.0 23适配
使用FileProvider
存储的变化
Android 不再允许在 app 中把 file://Uri 暴露给其他 app,包括但不局限于通过 Intent 或 ClipData 等方法。
Uri photoOutputUri = Uri.fromFile (photoOutputFile);
原因在于使用 /file://Uri 会有一些风险,比如:文件是私有的,接收/file://Uri 的 app 无法访问该文件。
在 Android6.0之后引入运行时权限,如果接收file://Uri的app没有申请READ_EXTERNAL_STORAGE权限,在读取文件时会引发崩溃。
因此,google 提供了 FileProvider,使用它可以生成 content://Uri 来替代 file://Uri。
- 在 res 目录下新建 xml 目录,在 xml 目录下新建 filepaths. xml 文件
- 在 AndroidManifest. xml 中申明:
1 |
|
- 使用的时候注意与配置文件中注册的包名一致:
1 |
|
文件不能随便访问了,新增了 READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO
动态申请权限
- 在 android 6.0 Marshmallow 版本之后,系统不会在软件安装的时候就赋予该 app 所有其申请的权限,对于一些危险级别的权限,app 需要在运行时一个一个询问用户授予权限。
- 只有那些 targetSdkVersion 设置为23和23以上的应用才会出现异常,在使用危险权限的时候系统必须要获得用户的同意才能使用,要不然应用就会崩溃。
- targetSdkVersion 如果没有设置为23版本或者以上,系统还是会使用旧规则:在安装的时候赋予该 app 所申请的所有权限。所以 app 当然可以和以前一样正常使用了,但是还有一点需要注意的是6.0的系统里面,用户可以手动将该 app 的权限关闭。
- 经试验:点拒绝没有奔溃,不过点不在提示后就一直不提示,也打不开那个页面,所以需要动态申请引导去设置页打开系统架
Android 13 32适配
相册权限
通过申请新的android.permission.READ_MEDIA_IMAGES
权限,就可以用以前的代码继续访问到以前的相册信息,因为对于目标版本为 Android 13 的情况,现在 READ_EXTERNAL_STORAGE
权限被细化了,开发者需要使用READ_MEDIA_IMAGE
、READ_MEDIA_VIDEO
、READ_MEDIA_AUDIO
来替代适配;
在申请完权限之后,就可以正常读取相册等信息;
所以如果是 TargetSDK 在 Android 13 以下,不需要处理,如果在 Android 13 以及以上 ,需要增加申请权限。
1 |
|
通知
Android 13 里增加了通知的运行时权限,其中 Android 13 (33) 的通知会根据正在运行的应用程序的目标 API 级别进行不同的处理,不过不管应用程序的目标API级别如何,Android 13 都会提示用户授予应用程序发送通知的权限。
- 如果是 TargetSDK 在 Android 12L (32) 以下,只要用户同意才能发送通知,一般是在应用启动的时候,比如用户点击了不允许,就无法发出通知,需要等到下次 App 再启动,才会再次询问,或者去设置通知中心打开;
- 如果是 TargetSDK 在 Android 13 (33) 以上,就一定需要手动添加
android.permission.POST_NOTIFICATIONS
和代码调用申请,不然可能设置中心都无法打开;
Android 虚拟机
Dalvik 和 ART(5.0以后)
Dalvik 运行 dex 文件,而 JVM 运行 java 字节码
ART 的机制与 Dalvik 不同。在 Dalvik 下,应用每次运行的时候,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在 ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(AOT, Ahead-Of-Time)。这样的话,应用的启动 (首次) 和执行都会变得更加快速。
ART 有什么优缺点呢?
优点:
1、系统性能的显著提升。
2、应用启动更快、运行更快、体验更流畅、触感反馈更及时。
3、更长的电池续航能力。
4、支持更低的硬件。
缺点:
- 机器码占用的存储空间更大,字节码变为机器码之后,可能会增加10%-20%(不过在应用包中,可执行的代码常常只是一部分。比如最新的 Google+ APK 是 28.3 MB,但是代码只有 6.9 MB。)
- 应用的安装时间会变长。
保活
- Service 设置成 START_STICKY,kill 后会被重启(等待5秒左右),重传 Intent,保持与重启前一样
- 通过 startForeground 将进程设置为前台进程,做前台服务,优先级和前台应用一个级别,除非在系统内存非常缺,否则此进程不会被 kill
- 双进程 Service:让2个进程互相保护,其中一个 Service 被清理后,另外没被清理的进程可以立即重启进程
- QQ 黑科技: 在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死
- 利用系统广播拉活
- 多进程:用 C 编写守护进程 (即子进程)
- 引导用户调到自启动管理界面,参考请启动
Android 逆向反编译
Android 逆向工程主要是指反编译和二次打包,通过反编译可以破解一些有用信息,而通过二次打包则可以产生一些山寨应用。Android 逆向工程是一个很有意思的话题,如果开发者对其感兴趣的话,推荐大家阅读下逆向相关的书籍,比如《Android 软件安全与逆向分析》
Jar 和 Aar 的区别
Jar 包里面只有代码,aar 里面不光有代码还包括代码还包括资源文件,比如 drawable 文件,xml 资源文件。对于一些不常变动的 Android Library,我们可以直接引用 aar,加快编译速度
APK 反编译
拿到需要加密的 Apk 和自己的壳程序 Apk,然后用加密算法对源 Apk 进行加密;再与壳 Apk 的 Dex 进行合并得到新的 Dex 文件;然后替换原壳程序中的 dex 文件即可,得到新的 Apk。那么这个新的 Apk 我们也叫作脱壳程序 Apk,他已经不是一个完整意义上的 Apk 程序了,他的主要工作是:负责解密源 Apk,然后加载 Apk,让其正常运行起来。
通过反射和 classloader
- dex2jar:将 dex 文件转化成 jar,原理也是一样的,只要知道 Dex 文件的格式,能够解析出 dex 文件中的类信息就可以了
- jd-gui:可以查看 jar 中的类,其实他就是解析 class 文件,只要了解 class 文件的格式就可以,class 反编译成 Java
view
- LinerLayout 跟 RelativeLayout 的绘制原理
LinearLayout 需要测量一次,而 RelativeLayout 需要测量2次(对子 view 测量,横向纵向分别进行一次),然后如果只嵌套一层首选 LinearLayout,如果多层需要使用 RelativeLayout。
FrameLayout 和 LinearLayout 差不多
- RelativeLayout 会让子 View 调用2次 onMeasure,LinearLayout 在有 weight 时。也会调用子 View2次 onMeasure
- RelativeLayout 的子 View 假设高度和 RelativeLayout 不同,则会引发效率问题,当子 View 非常复杂时,这个问题会更加严重。
- 假设能够,尽量使用 padding 取代 margin。
- CoordinatorLayout
参考:fragment_task
CoordinatorLayout 是一个“加强版”的 FrameLayout,它主要有两个用途:
- 用作应用的顶层布局管理器
- 通过为子 View 指定 behavior 实现自定义的交互行为。
在我们做 Material Design 风格的 app 时通常都使用 CoordinatorLayout 作为布局的根节点,以便实现特定的 UI 交互行为。很常见的一种模式是 TabLayout 放在 ToolBar 布局中与其一起置顶在界面上方,在滑动的时候将 ToolBar 隐藏而 TabLayout 一直置顶在界面上方。
- CollapsingToolbarLayout
顾名思义就是可折叠的 toolbar 布局。CollapsingToolbarLayout 可以包裹 Toolbar , 当其显示完收缩动画时使 Toolbar 显示在顶端。可以再加入浸入式的效果让 CollapsingToolbarLayout 的背景图突破系统的状态栏使界面更加美观同时也不影响 Toolbar 的显示效果。
Padding 和 Margin 有什么区别?
Padding 是控件内容的距离,margin 是控件和控件间的距离
实现侧边栏、和指示器效果、页面滑动有几种方式
侧边栏:自定义、slidingmenu、DrawerLayout 、SlidingDrawer
指示器效果:自定义、viewpager 里面的 PagerTabStrip、ActionBar Tab 标签、viewpagerindicate、FragmentTabHost、TabActivity、radiobutton、tablayout
页面滑动:自定义、viewpager、手势识别器,其实就是 onTouchEvent 提供的简单工具类,onTouchEvent 将触摸事件委托给了手势识别器
layout_weight
屏幕适配经常用等分的长度“先各自分配各自控件的长度,然后将剩余的长度按照权重的比例 layout_weight 的大小进行设置。
抓包的原理
代理。客户端请求->经过代理->到达服务端服务端返回->经过代理->到达客户端
任何 Https 的 app 都能抓的到吗?
7.0以下是可以的,只要手机里安装对应 CA 证书,比如用 charles 抓包,手机要安装 charles 提供的证书就行。
Android 7.0 之后,Google 推出更加严格的安全机制,应用默认不信任用户证书(手机里自己安装证书),自己的 app 可以通过配置解决,但是抓其它 app 的 https 请求就行不通。
okhtttp 禁止代理,就可以了 builder.proxy (Proxy. NO_PROXY);
charles 抓包显示乱码解决方法:
- 工具栏–>Proxy–>SSL Proxying Settings
- 添加需求抓包的请求的域名和端口号0
HTTPS 能调试是因为你安装了调试工具给你的根证书,相当于你主动被中间人入侵
Intent 传输数据的大小有限制吗
Intent 中的 Bundle 是使用 Binder 机制进行数据传送的, 数据会写到内核空间,Binder 缓冲区域。
Binder 的缓冲区是有大小限制的, 有些 ROM 是 1M, 有些 ROM 是 2M;
这个限制定义在 frameworks/native/libs/binder/processState. cpp 类中, 如果超过这个限制, 系统就会报错
因为 Binder 本身就是为了进程间频繁-灵活的通信所设计的, 并不是为了拷贝大量数据;
如果非 ipc 就很简单了, static 变量, eventBus 之类的都可以;
如果是 ipc, 一定要一次性传大文件, 可以用 file 或者 socket;
没有给权限如何定位,特定机型定位失败,如何解决
GPS 就是精准定位!
蓝牙、移动信号、wifi 都是能定位的。就是基于网络定位,但是不太准,没有 GPS 定位那么准。
android 的定位权限就是 GPS 定位,但是只要你有网络请求,就能得到你的大概范围。
Android 各个版本
Android 3.0系统这个系统是为了平板电脑设计的,加入了 fragment
- 4.0版本,这个版本对于不在对手机和平板进行区别对待, actionbar 在这个版本加的
- 5.0系统,使用了 ART 运行环境代替了 Dalvik 虚拟机大大提升了运行速度之外,还提出了 Material Design 的设计语言来优化应用的界面,新增了很多控件。Material Design 主题,设置阴影、ToolBar (就相当于一个控件,更加灵活)、DrawerLayout、CardView,google 发布的新的 Android Support Design 库,里面也包含了几个新的控件,那么 TabLayout 就是其中一个。RecyclerView
- 6.0系统加入了运行时权限,加入指纹识别,能提供原生指纹识别 API,这不但降低了厂商开发指纹识别模块的成本。大量漂亮流畅的动画
- 7.0系统加入了多窗口模式功能,引入了 JIT 编译器,APP 的安装速度将比目前的安卓6.0提升最多75%,支持了 Java8语言模式,夜间模式
获取文件需要使用 fileprovider - 8.0对隐式广播、后台服务和位置更新等进行了后台自动限制,以此来增加手机电池寿命。
后台启动服务 startService 会报错,需要使用 startForgand ()
通知栏需要使用新的 API,旧的不生效了,需要指定个 channelID - 9.0:全面屏的全面支持
- AndroidQ:5G 网络、通知中的智能回复、黑暗主题、设置面板、分享快捷方式、用户隐私
缓存数据,如何保证和服务器的数据统一?
- 比如有个网络更新的功能, activity 可以每隔半小时开启 service 去访问服务器,获取最新的数据。
- 在缓存文件里面加入时间戳,根据实际情况在一定的时间差内再次访问网络数据、判断 URL 在缓存的第一行写一个上当前时间,读的时候判断是不是过期,根据需求看需要多久跟新
系统分层
(由下向上) 【如图】
- 安卓系统分为四层,分别是 Linux 内核层、Libraries 层、FrameWork 层,以及 Applications 层
- Linux 内核层:包含 Linux 内核和驱动模块(比如 USB、Camera、蓝牙等)
- Libraries 层:这一层提供动态库(也叫共享库) 、android 运行时库、Dalvik、apengl、虚拟机等,编程语言主要为 C 或 C++,所以可以简单的看成 Native 层。
- FrameWork 层:这一层大部分用 java 语言编写,有 activityManager、windowManager 等,它是 android 平台上 Java 世界的基石。
- Applications 层:应用层,桌面、联系人、拨号等软件
FrameWork 层 ——– Java 世界
Libraries 层 ——– Native 世界
Linux 内核层 ——– Linux OS
Java 世界和 Native 世界间的通信是通过 JNI 层, JNI 层和 Native 世界都可以直接调用系统底层 - Dalvik VM 和传统 JVM 的区别:
传统的 JVM:编写. java 文件→编译为. class 文件 → 打包成. jar 文件
Dalvik VM: 编写. java 文件 → 编译为. class 文件 → 打包成. dex 文件 → 打包成. apk 文件 (通过 dx 工具) 将所有的类整合到一个文件中,提高了效率。更适合在手机上运行
ABI
应用程序二进制接口 ABI(Application Binary Interface)定义了二进制文件(尤其是. so 文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。在 Android 系统上,每一个 CPU 架构对应一个 ABI:armeabi,armeabi-v7a,x86,mips,arm64- v8a,mips64,x86_64。
SO 文件
如果程序中使用到了 NDK,它将会生成. so 文件。c++的类库
CPU
中央处理单元(CPU)主要由运算器、控制器、寄存器三部分组成,从字面意思看运算器就是起着运算的作用,控制器就是负责发出 CPU 每条指令所需要的信息,寄存器就是保存运算或者指令的一些临时文件,这样可以保证更高的速度。
CPU 需要执行数以百万计的指示,才能使它向我们期待的方向运行
Intel 和 ARM 处理器的第一个区别是,前者使用复杂指令集(超高性能的台式机和服务器处理器),而后者使用精简指令集(低功耗处理器)。
ARGB
色彩模式,也就是 RGB 色彩模式附加上 Alpha(透明度)通道,常见于32位位图的存储结构。
透明度是个 0~255的值,为0的时候,完全不可见;为 255的时候完全可见,#(0-f) 00设置透明,f 全黑色 Color.FromArgb () 有一个构造函数有4个参数,
Color.FromArgb (int alpha, int red, int green, int blue). 这个用来控制颜色的透明度。