新技术又又又又叒叒叒来了

294 篇文章 4 订阅
268 篇文章 8 订阅

此“新技术”主要指大厂近期对外的分享,「大厂的对外分享系列」更新一篇, 目前第 23 期,如果你对新技术都比较感兴趣,欢迎持续关注。

标题中的“又”的个数+10就是当前期数了。

上一期链接:

新技术又又又叒叒叒来了?

距离上一期(2022-01-10)两个多月,看看这一期间大厂都更新了什么吧。

1. Google官方一些新技术更新

发布了Android 13 开发者预览版 2

这发布速度太惊人了,上一次还在聊 Android 12,我估计大家慢慢就要接收到各个厂商的通知了,要求“适配Android13”,一般遇到厂商要求的适配,一定要尝试确认下,大多数情况下只需要 App 在相关系统能稳定运行即可,并不要求提升 target版本。

当然目前依然觉得 Android 12适配才是主流,所以继续收集12 适配的文章给大家:

Android 12 已来,你的 App 崩溃了吗?

Android 12 适配你准备好了吗?

适配到Android 12,全版本支持保存图片到相册方案

Android 12 适配工作来了,实践Jetpack SplashScreen API

Android 12 快速适配要点

Android 12 自动适配 exported 深入解析避坑

Android 12 功能和变更列表

https://developer.android.google.cn/about/versions/12/summary

Flutter 2.10 发布

距离上次更新,Flutter 从 2.8->2.10,难以置信,Flutter 又发布正式版了...

主要的更新就是,Flutter 2.10 版本提供了 Windows 支持的稳定版本。

详细的可以点击阅读:

Flutter 2.10 | 一文解读重点更新

Jetpack 也迎来了一波更新

应用架构指南修订啦

官网:

https://developer.android.google.cn/jetpack/guide

没错,Google 确实更新了应用架构指南,之前推送了一篇:

Google 推荐使用 MVI 架构?卷起来了~

之前的很经典的架构图被下面的取而代之了:

官方也对新的架构给出了非常详细的教程:

地址:

https://developer.android.google.cn/courses/pathways/android-architecture

compose 发布了1.1.1 稳定版本

 

地址:

https://developer.android.google.cn/jetpack/androidx/releases/compose

之前对 compose 保持观望态度的,可以尝试体验了。

使用baseline profiles 提升应用性能

大家乍一听「baseline profiles 」可能不知道说的是什么,我简单解释下,在 Android N之后为了平衡安装速度和运行速度,应用在安装后运行,会收集热代码,并在「空闲时刻」翻译为类似于机器码,从而提升下一次运行相关代码的效率。

当然上述这一切对于用户以及开发者都是黑盒的,假设系统允许开发者给提供热代码的规则,那么就相当于开发者可以控制重要代码让其可以翻译为“机器码”,例如启动等相关核心场景,从而提升用户体验。

没错 google提供了一个库来做这个事情:androidx.profileinstaller:profileinstaller:1.2.0-alpha01

详细可以参考:

https://developer.android.google.cn/studio/profile/baselineprofiles

之前抖音也分享了一篇dex2oat 的文章,可以一起阅读:

Android性能优化之Android 10+ dex2oat实践

意外发现

另外我意外发现 Jetpack 的索引做的挺好的,如果只是查询最新的 androidx相关库,可以在官网查询,有最新版本信息:

https://developer.android.com/jetpack/androidx/releases/core


可以替换掉我之前在 wanandroid 上做的androidx 快速查询页面了,一句拿来吧你,将官网链接放到右侧:

 

2. 大厂对外文章分享

vivo 互联网技术

跑马灯带你深入浅出TextView的源码世界

这篇文章还是比较值得看一下的,文章主要讲了对于 TextView 跑马灯效果原理的分析,但是更为重要的是:

对于繁琐的源码世界,提出了一种通过源码解决问题的思路,也给出了一些看源码的建议:猜想论证、debug、画流程图辅助分析等。

字节跳动技术团队

这段时间是真高产...

抖音Android包体积优化探索:从Class字节码入手精简DEX体积

看着名字就知道有点硬核,主要就是在编译期间,对于Class 字节码进行操作,例如:

  1. 删除冗余指令,例如一些static变量冗余的赋值指令;

  2. 删除无用指令,例如我们打印的 log,以及 e.printStackTrace()之类的,在线上无用的代码;

  3. 短方法内联,例如 getter-setter,编译器生成的 access 方法等;

  4. R 文件内联,默认在低版本的 AGP 上,每个 module 都有个 R.class 文件,这些文件可以移除,另外 app 目录下的 R文件都是常量,可以通过内联的方式去除原本的 R.class 文件;

  5. ...

大家可能看得头大,不需要担心,上述方案都开源了,开箱即可用:

https://github.com/bytedance/ByteX

一文读懂直播卡顿优化那些事儿

虽然标题说的是直播卡顿,实际文章介绍了非常多系统卡顿的相关原理,这块值得好好阅读一下。

然后也提出了一个优化手段,当然都是理论性的,并为提供源码,需要大家自己根据描述实践。

Android 系统 Bar 沉浸式完美兼容方案

这个标题说明了一切,主要针对各个版本去做 Bar 沉浸式适配。

一次关于架构的“嘴炮”

这篇文章我是比较有感受的,我最近也在推动做架构的事情,很多时候大家以为搞架构的同学:

每天都在研究各种新技术、架构方案,然后去其糟泊取的精华,最后搞出来一套符合当前项目的牛批架构,整个人金光闪闪。

实际上每天:

“哥,这个代码你改下呗,没按照这个架构规则来写”

“哥,你这个组件收敛下呗,方便多个 app 复用”

“哥,你这个组件 readme 咋没写?”

...

做架构的同学苦呀,而且还要面临上级灵魂发问:

“你这个架构说能够提升研发效率?怎么评估提升了多少,咋没有看到iOS那边被你干崩盘呢?”

文章中有两张大图关于工程架构、业务架构的关联的事情,差不多就是我们当下不断在完善和提升大家意识的事情。

一文读懂现代 Android 开发最佳实践

和上文形成一点对比,这个从技术角度去论述了,大家自行阅读吧,我也总结不出来东西。

抖音 Android 性能优化系列:启动优化实践

这篇文章应该包含了抖音绝大多数的优化方案,大家在聊启动优化的时候,除了task 拆分任务、延迟加载、异步加载等,还可以看看还有哪些方案可以借鉴。

文中我有个印象比较深刻的 FileProvider 优化,真的是...太细了,你去仔细看下就知道了,当然里面大多数方案我们都实践过。

百度 App 技术

百度APP Android包体积优化实践(一)总览

文章还是比较实在的,提到了不少方案,并且在文末给了参考链接。

其实我个人对于包体积优化也有一点感触,大家其实看得时候可能比较关注各种各样的黑科技,但是真想做好包体积这个事情,还是流程最重要。

必须有一套完善的流程,能够发现包体积增大的原因,然后针对这些原因去引导全组所有同学的包体积优化的意识,只有全面的意识的形成,才能从根本上压制住包体积的快速增长。

否则就是技术同学天天苦哈哈的上方案,运气好优化几 M,过几个版本又劣化回去了,反反复复,但是可用的技术方案越来越少,最后...又是苦的负责的技术同学。

淘系技术

什么是好的技术氛围?

大家简单学习一下,取长补短~

淘宝 Android 帧率采集与监控详解

对于帧率采集,大家肯定能够提出来Choreographer#postFrameCallback,核心原理肯定离不开它,但是大家都在往“更精准的评定上去做努力”,可以看看淘宝它们做了哪些改善。

另外文中提到一个 API: 

FrameMetrics,开发文档见 https://developer.android.com/reference/android/view/FrameMetrics

有必要了解一下。

APM 页面加载耗时校准

关于页面加载耗时的结束点,有很多不同的口径:

  1. Activity onResume

  2. Activity onResume 后 post 一个 Runnable

  3. 页面 View.addPredrawListener

  4. 网络数据请求完成

  5. ...

其实这些都不能够精准的和用户觉得页面加载完成相匹配,而且不同的场景差距巨大。

淘宝这边给出的可见 View 的页面投影、面积计算感觉很有新意,也确实更符合用户的实际体验,当然这也没有办法抽象成一个简单通用的方案,还是有很多细节需要针对具体业务场景处理。

阿里巴巴移动技术

“向工程腐化开炮”系列

向工程腐化开炮 | proguard治理

向工程腐化开炮 | manifest治理

向工程腐化开炮:Java代码治理

向工程腐化开炮|资源治理

向工程腐化开炮|动态链接库so治理

看这标题就很刺激,每篇文章都值得精读和吸收,我觉得上述的问题在各个团队存在的概率很大,不知道后面还有没有「向工程腐化开炮|gradle脚本治理」,我们项目目前就有一堆脚本急需治理。

字节跳动终端技术

APK修改神器:插桩工具 DexInjector

一般聊到插桩都是Java 字节码插桩,很少见到针对 dex 去做插桩的,以前接触过最复杂的无非就是 apk->dex->smali 做一些简单的修改。

我觉得这个技术还是比较有意思的,如果有一套比较稳定的方案,在一些自动化平台上需要注入一些代码上会简化比较多的流程,不再需要接入方去引入各种 gradle plugin 了。

历史分享(点击可直接访问):

3. [更新]综合来谈隐私合规治理

主要还是上期的内容,看到还有大厂相关更新,还留着吧,应该有用,如果上期已经仔细阅读过可以跳过了。

先看看大厂相关分享:

[新增]有赞 coder

有赞移动隐私制约探索与实践

主要还是针对敏感方法,做字节码 hook 去做发现、监控、治理。

网易云音乐大前端团队

Android 隐私合规静态检查

Android 隐私合规静态检查(二)

这两篇文章说的还是比较清楚的,主要突出如何发现隐私合规问题,关注的是运行时、对产物进行扫描来发现调用隐私 API 的堆栈。

运行时:主要在编译期间提前对相关隐私 API 代码进行插桩,当然很多隐私 API 都是系统类相关 API,注入代码不太可能,就考虑中转代理的方式(中转到我们定义的一个方法,执行完成自定义方法,再执行原来的调用),有点类似之前说的 lancet 的 Insert 和 Proxy 模式,可以参考:

Android 无所不能的 hook,让应用不再崩溃

产物扫描:说了一个演进流程比较有意思,最开始是 apk->dex->class->java 然后进行扫描,后续改为 apk->dex->smali进行扫描,确实 smali 因为是文本结构很适合做类似静态分析的工作。

文章提到的分析 smali 来还原调用栈,让我眼前一亮。

京东零售技术

ASM在隐私合规扫描中的应用实战

京东这个主要在讲如何在编译期间修改字节码了,有点偏 Transform 教程。

其实我个人也做了比较长时间的隐私合规治理,简单做一些分享,隐私合规主要就是两点:

  1. 隐私相关 API,在用户授权之前,不可以调用;

  2. 即使用户授权了,调用频率不能过高,一般现在厂商都有App 行为记录;

  3. Android 隐私相关权限相关不能随便使用,如果使用,需要明确给出解释;

大概说下我们做了哪些事:

产物扫描:一般打完包,都会做产物包的隐私合规扫描,可以基于 smali 去分析,不过说实话,扫描的结果意义不是太大,一般数量比较多,很多都是三方 SDK 内部调用,并不清楚调用时机以及频率,因为并不是完全不可以用,所以一般仅针对新增做下简单的 review。

运行时:和网易云分享的一样,字节码修改是必要的,因为没有办法保证所有相关 api 都能做运行时 hook,但是字节码 hook都是可以的,将相关 API 的调用,都中转到我们自定义的方法,在这个方法内部判断:

a. 当前用户是否已经用意?-> 未同意,直接崩溃

b. 调用频率分析 -> 用于分析后续合理性,频率不正常,告警

然后再调用原方法(对于字节码 hook 感觉比较困难,也可以尝试 epic去做运行时 hook,唯一注意就是做好代码隔离,别带上线了)。

合码:既然产物扫描增量的 review 意义最大,于是我们在合码阶段也简单做一下分析,发现有新增的隐私 API 调用会触发更严格的审核。

权限变更:打包期间我们还会做一次权限整体检测,防止同学不注意引入隐私相关 API,如果发现新增权限为危险权限,会立即告警:新增了哪个权限,哪个库引入等(合码阶段如果有构建流程,也可以放合码流程)。


另外对于一些厂商的用户行为记录,尝试不会告诉你明确的规则,只能去单点分析了,先确定哪些方法会触发行为记录,大多数都是基于 AppOps 或者是系统服务API调用,确认 API 后,可以通过字节码 hook 或者运行时 hook(大多数系统服务都可以被动态代理替换)。

治理

1. 未同意前不能调用,这个没的说;

2. 降低频率一般 3 个思路:减少调用;缓存结果;部分 API 可以修改为回调的方式;

当然上面的描述,都是思路,实践起来可能还有困难,这一篇也可以参考:

吹爆系列:彻底解决隐私方法调用,防止App被下架

转自:

新技术又又又又叒叒叒来了?
https://mp.weixin.qq.com/s/e-XwF30-CWgBwq7Nw_01UA

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,根据您提供的问题,我来回答。这是一个经典的背包问题,可以使用动态规划来解决。具体思路为:对于每个酒,我们可以选择放或者不放到背包中,如果放入,则需要考虑可用的酒量和当前酒的重量是否超过限制,以及当前价值是否更高,如果更高则更新当前最大价值和选择的酒的编号。最终输出最大价值和选择的酒的编号即可。以下是示例代码: ``` #include <iostream> #include <vector> #include <algorithm> using namespace std; struct Wine { int weight; int price; int id; }; bool cmp(Wine a, Wine b) { return a.price > b.price; } int main() { int n, m; while (cin >> n >> m) { vector<Wine> wines(n); for (int i = 0; i < n; i++) { cin >> wines[i].weight >> wines[i].price; wines[i].id = i + 1; } sort(wines.begin(), wines.end(), cmp); vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0)); vector<vector<int>> choice(n + 1, vector<int>(m + 1, 0)); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (wines[i - 1].weight > j) { dp[i][j] = dp[i - 1][j]; } else { int v1 = dp[i - 1][j]; int v2 = dp[i - 1][j - wines[i - 1].weight] + wines[i - 1].price; if (v2 > v1) { dp[i][j] = v2; choice[i][j] = 1; } else { dp[i][j] = v1; } } } } int max_price = dp[n][m]; if (max_price == 0) { cout << "There is no proper wine." << endl; } else { cout << "The max price is " << max_price << "." << endl; vector<int> chosen; int i = n, j = m; while (i > 0 && j > 0) { if (choice[i][j] == 1) { chosen.push_back(wines[i - 1].id); j -= wines[i - 1].weight; } i--; } sort(chosen.begin(), chosen.end()); cout << "Choose:"; for (int i = 0; i < chosen.size(); i++) { cout << " " << chosen[i]; } cout << endl; } } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值