Android(二)

So 库架构选择

unknown_filename.3
unknown_filename.4
 连微信也只有: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
2
3
compileSdkVersion: 31,  
minSdkVersion : 21,
targetSdkVersion : 31,

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

聊一聊Android存储行为的变化

  1. 在 res 目录下新建 xml 目录,在 xml 目录下新建 filepaths. xml 文件
  2. 在 AndroidManifest. xml 中申明:
1
2
3
4
5
6
7
<provider android:name="androidx.core.content.FileProvider" 
android:authorities="com.alexlu.androidstorage.fileProvider"
android:enabled="true" android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
  1. 使用的时候注意与配置文件中注册的包名一致:
1
2
3
File file = context.getExternalFilesDir(null);
// val file = File(xxpath)
val uri = FileProvider.getUriForFile(context, "com.alexlu.androidstorage.fileProvider", file);

文件不能随便访问了,新增了 READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO

动态申请权限

  1. 在 android 6.0 Marshmallow 版本之后,系统不会在软件安装的时候就赋予该 app 所有其申请的权限,对于一些危险级别的权限,app 需要在运行时一个一个询问用户授予权限。
  2. 只有那些 targetSdkVersion 设置为23和23以上的应用才会出现异常,在使用危险权限的时候系统必须要获得用户的同意才能使用,要不然应用就会崩溃。
  3. targetSdkVersion 如果没有设置为23版本或者以上,系统还是会使用旧规则:在安装的时候赋予该 app 所申请的所有权限。所以 app 当然可以和以前一样正常使用了,但是还有一点需要注意的是6.0的系统里面,用户可以手动将该 app 的权限关闭。
  4. 经试验:点拒绝没有奔溃,不过点不在提示后就一直不提示,也打不开那个页面,所以需要动态申请引导去设置页打开系统架

Android 13 32适配

Android 13 适配指南 - 掘金

相册权限

通过申请新的android.permission.READ_MEDIA_IMAGES 权限,就可以用以前的代码继续访问到以前的相册信息,因为对于目标版本为 Android 13 的情况,现在 READ_EXTERNAL_STORAGE权限被细化了,开发者需要使用READ_MEDIA_IMAGEREAD_MEDIA_VIDEOREAD_MEDIA_AUDIO 来替代适配;

在申请完权限之后,就可以正常读取相册等信息;

所以如果是 TargetSDK 在 Android 13 以下,不需要处理,如果在 Android 13 以及以上 ,需要增加申请权限

1
2
3
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

通知

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、支持更低的硬件。
缺点:

  1. 机器码占用的存储空间更大,字节码变为机器码之后,可能会增加10%-20%(不过在应用包中,可执行的代码常常只是一部分。比如最新的 Google+ APK 是 28.3 MB,但是代码只有 6.9 MB。)
  2. 应用的安装时间会变长。

保活

  1. Service 设置成 START_STICKY,kill 后会被重启(等待5秒左右),重传 Intent,保持与重启前一样
  2. 通过 startForeground 将进程设置为前台进程,做前台服务,优先级和前台应用一个级别,除非在系统内存非常缺,否则此进程不会被 kill
  3. 双进程 Service:让2个进程互相保护,其中一个 Service 被清理后,另外没被清理的进程可以立即重启进程
  4. QQ 黑科技: 在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死
  5. 利用系统广播拉活
  6. 多进程:用 C 编写守护进程 (即子进程)
  7. 引导用户调到自启动管理界面,参考请启动

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

  1. dex2jar:将 dex 文件转化成 jar,原理也是一样的,只要知道 Dex 文件的格式,能够解析出 dex 文件中的类信息就可以了
  2. jd-gui:可以查看 jar 中的类,其实他就是解析 class 文件,只要了解 class 文件的格式就可以,class 反编译成 Java

view

  • LinerLayout 跟 RelativeLayout 的绘制原理
    LinearLayout 需要测量一次,而 RelativeLayout 需要测量2次(对子 view 测量,横向纵向分别进行一次),然后如果只嵌套一层首选 LinearLayout,如果多层需要使用 RelativeLayout。
    FrameLayout 和 LinearLayout 差不多
  1. RelativeLayout 会让子 View 调用2次 onMeasure,LinearLayout 在有 weight 时。也会调用子 View2次 onMeasure
  2. RelativeLayout 的子 View 假设高度和 RelativeLayout 不同,则会引发效率问题,当子 View 非常复杂时,这个问题会更加严重。
  3. 假设能够,尽量使用 padding 取代 margin。
  • CoordinatorLayout

自定义Behavior,好文章

参考:fragment_task

CoordinatorLayout 是一个“加强版”的 FrameLayout,它主要有两个用途:

  1. 用作应用的顶层布局管理器
  2. 通过为子 View 指定 behavior 实现自定义的交互行为。
    在我们做 Material Design 风格的 app 时通常都使用 CoordinatorLayout 作为布局的根节点,以便实现特定的 UI 交互行为。很常见的一种模式是 TabLayout 放在 ToolBar 布局中与其一起置顶在界面上方,在滑动的时候将 ToolBar 隐藏而 TabLayout 一直置顶在界面上方。
  • CollapsingToolbarLayout
    顾名思义就是可折叠的 toolbar 布局。CollapsingToolbarLayout 可以包裹 Toolbar , 当其显示完收缩动画时使 Toolbar 显示在顶端。可以再加入浸入式的效果让 CollapsingToolbarLayout 的背景图突破系统的状态栏使界面更加美观同时也不影响 Toolbar 的显示效果。

Padding 和 Margin 有什么区别?

Padding 是控件内容的距离,margin 是控件和控件间的距离
wpsF24B

实现侧边栏、和指示器效果、页面滑动有几种方式
侧边栏:自定义、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 抓包显示乱码解决方法:

  1. 工具栏–>Proxy–>SSL Proxying Settings
  2. 添加需求抓包的请求的域名和端口号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 网络、通知中的智能回复、黑暗主题、设置面板、分享快捷方式、用户隐私

缓存数据,如何保证和服务器的数据统一?

  1. 比如有个网络更新的功能, activity 可以每隔半小时开启 service 去访问服务器,获取最新的数据。
  2. 在缓存文件里面加入时间戳,根据实际情况在一定的时间差内再次访问网络数据、判断 URL 在缓存的第一行写一个上当前时间,读的时候判断是不是过期,根据需求看需要多久跟新

系统分层

(由下向上) 【如图】

  • 安卓系统分为四层,分别是 Linux 内核层、Libraries 层、FrameWork 层,以及 Applications 层
  1. Linux 内核层:包含 Linux 内核和驱动模块(比如 USB、Camera、蓝牙等)
  2. Libraries 层:这一层提供动态库(也叫共享库) 、android 运行时库、Dalvik、apengl、虚拟机等,编程语言主要为 C 或 C++,所以可以简单的看成 Native 层。
  3. FrameWork 层:这一层大部分用 java 语言编写,有 activityManager、windowManager 等,它是 android 平台上 Java 世界的基石。
  4. Applications 层:应用层,桌面、联系人、拨号等软件
    FrameWork 层 ——– Java 世界
    Libraries 层 ——– Native 世界
    Linux 内核层 ——– Linux OS
    Java 世界和 Native 世界间的通信是通过 JNI 层, JNI 层和 Native 世界都可以直接调用系统底层
  5. Dalvik VM 和传统 JVM 的区别:
    传统的 JVM:编写. java 文件→编译为. class 文件 → 打包成. jar 文件
    Dalvik VM: 编写. java 文件 → 编译为. class 文件 → 打包成. dex 文件 → 打包成. apk 文件 (通过 dx 工具) 将所有的类整合到一个文件中,提高了效率。更适合在手机上运行
    8f054a15-c276-48b1-948e-e69044b554d0

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). 这个用来控制颜色的透明度。


Android(二)
http://peiniwan.github.io/2024/04/7af0744060e5.html
作者
六月的雨
发布于
2024年4月6日
许可协议