抖音 Android 包体积优化探索:资源二进制格式的极致精简

发表于 1年以前  | 总阅读数:1740 次

前言

目前,安卓端对于包体积的优化方案已经多如过江之鲫,我们系列的[上一篇文章] 介绍了 Class 字节码的优化,本期我们将关注点聚焦到资源文件上,从资源二进制文件的全新角度,拓展出包体积优化的新思路。

在资源文件优化方面,通常的优化手段多集中在图片/文件压缩、资源文件名称混淆、离线下载资源文件等方面,而我们的新思路基于对于常规思路的深度分析及思考。

一开始,我们是从资源文件名称混淆入手优化,业界对于资源文件名称混淆方案,最为熟知的开源项目当属 AndResGuard,该项目优化目标为资源文件目录 res 内的文件,其优化点如下:

  1. 对重复的资源文件,以计算 md5 值的方式来判断是否重复并只保留一份;
  2. 对资源文件名称进行缩短,即名称混淆;
  3. 对 APK 中的内容采取 7zip 压缩优化;

按照此项目进行优化,总体收益可以达到非常可观的 MB 级别。但完成此项目的优化后,资源文件的进一步优化便达到瓶颈。

为了在此基础上更好的实现优化资源大小,我们需要了解资源文件目录 res 所包含的文件类型及其大小的分布情况。以抖音为例,下表是对其包含的子文件夹名称、文件数量、将文件夹 zip 压缩后大小的梳理,以文件数量降序排序:

子文件夹名称 文件数量 文件夹zip压缩后大小
drawable-xxhdpi-v4 6054 19.5MB
layout 5970 12.2MB
drawable 4388 4.6MB
layout-v17 2985 8.5MB
drawable-night-xxhdpi-v8 994 ...
drawable-xhdpi-v4 431 ...
anim 382 ...
color 152 ...

从上表,可以看到:

  • drawable-xxhdpi-v4 目录下文件数量最多有 6000+,压缩后文件大小约为 19.5MB。
  • drawable 目录下文件数量排第三,有 4388 个,压缩后 4.6MB,同时包含图片和.xml 文件。
  • 文件数量排第二和第四的都是 layout 目录下的布局文件,分别有 5970,2985 个,其文件夹压缩后大小分别为 12.2MB,8.5MB。布局文件总数近 9K,文件大小约 20.7MB

可见,layout 目录下的布局文件大小已经和图片文件不相上下。而这部分如此大的文件,除了有文件名称的混淆优化之外,是否还有其他优化方式?或者其文件名称混淆是否彻底?

此外,APK 解压后的 resources.arsc 文件有 7.3MB 之大。其中包含了 app 所有资源文件名称和资源字符串值,其中是否也存在冗余字符串?

对于 layout 布局文件,从近万份之多的文件数量及 20+MB 的文件体积来看,即存在值得探究的必要。我们通过对资源文件的二进制文件格式的解析,并从文件内容被使用的角度分析,发现存在可以删除的冗余内容。在反复尝试并解决了各种稳定性和打包兼容问题后,最终研发出了一套针对 Android ARSC/XML 文件格式的包体积优化方案,目前已经落地抖音,实现 2MB 以上的收益。

接下来,本文将深入讲解该方案的实现细节。

APK 资源格式优化

我们的核心思路是,以资源路径缩短为优化出发点,在最终的 APK 文件里,从resources.arsc与 layout 布局文件的二进制文件格式着手,查看其内容结构,寻找可以删除的未使用字符串,优化文件名称或者文件里的字符串池。主要分为下面两个优化点。

资源路径缩短

资源格式修改

接入 AndResGuard 后,资源文件 res 目录 -> r,其中的子文件夹和文件名也都被混淆,即:

  • res/anim/abc_fade_in.xml -> r/a/a.xml

这是为了减少资源文件路径,从而减少包体积,自然联想到,是否还能进一步减少资源文件路径呢?显然,如果能将所有文件都放在 r 目录下,将中间的子文件夹去掉,则可以进一步减少资源文件路径和 zip 节点数量,一定还有包体收益;顺便可以将文件名的后缀去掉,也可以减少文件路径,即:

  • r/a/a.xml -> r/a
  • r/a/b.png -> r/b

由于修改资源文件名称需要修改resources.arsc文件,这里对resources.arsc 的文件格式分析下:

可以看到,其中包含有 3 个字符串池。

假如我们有一个资源文件abc_fade_in.xmlres/anim 目录下,其在resources.arsc文件中 3 个字符串池里的信息如下:

  • 全局字符串池(字符串池 1):主要包含完整文件路径名,即res/anim/abc_fade_in.xml
  • 类型字符串池(字符串池 2):资源种类名(包括存储 res 目录下子文件目录名),即anim
  • 键字符串池(字符串池 3):文件名,即: abc_fade_in

可以看到,与资源文件名相关的地方有两处,分别在全局字符串池保存着完整文件路径名,键字符串池保存着文件名,为了将资源路径缩短,需要同时修改这两处,即在全局字符串池中修改res/anim/abc_fade_in.xml -> r/f ,在键字符串池修改 abc_fade_in -> f。在resources.arsc文件中需要修改的两处字符串池,如下图箭头所示:

然而,在完成资源路径缩短后,却发现包体积反而变大了 160K+

键常量池裁剪

我们知道,文件名称混淆,其混淆名称来源于符合文件名称规范的混淆字符串集合,其中的字符串都是唯一不重合的,所以,字符串集合数量越大,其最长字符串的长度也会越大。

在资源路径未缩短情况,不同子目录文件夹下,其使用的文件名称每次都可以从混淆字符串集合中重新选取,使得其名称在键字符串池中始终保持最短;

其对应的文件名字符串集合为:[a,b,c,d,e]

而在缩短的情况下,由于所有文件都包含在一个文件夹r下,其使用的文件名称只能来自同一个混淆字符串集合,使其名称在键字符串池中会逐渐变长,同时也会使得路径字符串跟着变长,导致其整体结果反而变大!如下图所示:

其对应的文件名字符串集合为:[a,b,c,d,e,f,g,h,i,j]

因此,当所有文件都包含在一个文件夹r下时,无法使得不同子目录下的文件名得以复用,所以虽然路径缩短,会使得全局字符串池变小,但键字符串池反而会变大。这是因为键名默认需要和文件名保持一致。

猜想resources.arsc文件中,键名是否需要和文件名保持一致,更或者,键名本身是否有存在的必要?

其实,在经过编译后,资源文件被使用的地方会被替换成特定的 id 值,比如:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // => setContentView(0x7f0b001c); // 替换为id值
    }
}

由此可知,资源文件名称必然与整型 id 值有着一一对应的关系,这种一一映射的关系可以联想到:是否只需要根据整型 id 值,就可以找到相应的文件路径名称?因为这个过程里完全不涉及键字符串的引用。

基于这个想法,我们将键字符串池全部替换为单一值"_", 发现 APK 运行正常。显然,去掉键字符串池,似乎并不会影响 APK 运行期间根据整型 id 值去查找文件路径

那么,键字符串池中的字符串的作用是什么呢?翻看源码发现,只有使用类似“资源文件反射”的方式调用,才会获取键字符串池中的字符串值,比如:

// MainActivity.java
// 此处返回值为"_", 因为键字符串池已经全部替换为 "_"
String entryName = getResources().getResourceEntryName(R.layout.activity_main);
// 此处返回的id值为0, 因为找不到名为 "abc_fade_in",类型为"anim"的资源
int id = getResources().getIdentifier("abc_fade_in", "anim", "cn.pkg");

当前项目中,一般没有使用上述“资源文件反射”获取资源名称的使用方式,所以键字符串池可以全部替换为单一值"_";目前已知的必须要以这种方式使用资源文件的方式,大多是插件等不在一个宿主项目下的情况,如果需要,可以对这部分字符串名称进行保留,配置白名单即可。

下图是resources.arsc文件中键字符串池的格式和内容示意图:

  • 偏移数组(标记 1),数组的值为指向键字符串池(标记 2)中每个字符串的偏移值
  • 由于需要将键字符串池中所有字符串替换为单一值"_",那么,键字符串池中就只有一个"_"字符串,偏移数组也将只有一个元素,其指向键字符串池中"_"字符串的起始偏移值 0。

最后,还需将resources.arsc文件中,键字符串对应的偏移数组的索引值,所有被调用的地方,全部替换为字符串"_"对应的偏移数组的索引值 0,这样原有文件名字符串都会换为"_",键字符串池就只剩"_"字符串了。

崩溃和兼容性问题

在项目具体实施灰度中出现了崩溃,发现在 drawable 目录下的 xml 图片文件有对其后缀的检查,如下图:

frameworks/base/core/java/android/content/res/ResourcesImpl.java

//创建drawable
private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value, int id, int density) {
    ...
    if (file.endsWith(".xml")) { //对xml文件解析并创建drawable
        final String typeName = getResourceTypeName(id);
        if (typeName != null && typeName.equals("color")) {
            dr = loadColorOrXmlDrawable(wrapper, value, id, density, file);
        } else {
            dr = loadXmlDrawable(wrapper, value, id, density, file);
        }
    } else { //对.png等其他图片解析并创建drawable
        final InputStream is = mAssets.openNonAsset(value.assetCookie, file, AssetManager.ACCESS_STREAMING);
        final AssetInputStream ais = (AssetInputStream) is;
        dr = decodeImageDrawable(ais, wrapper, value);
    }
    ...
}

因此,我们对 drawable 目录下的 .xml 后缀不做去除。

上线后,有反馈 6.x 上部分手机启动慢的现象,经排查发现是其中图片文件名称后缀删除优化,导致的在部分 rom 上 app 启动慢。排除掉这些兼容性问题,最后,我们仅保留路径缩短和键常量池裁剪优化,而不做文件名后缀去除,即:r/a/a.xml -> r/a.xml,此部分资源路径压缩优化收益 300K+。

layout 优化

我们知道,layout 目录下的布局文件所占包体积很大,从之前的分析可知,resources.arsc文件中有好几个字符串池,有的字符串池并没使用可以删除,而 layout 布局文件与resources.arsc文件的二进制文件格式一致,其中也有字符串池,是否也存在类似的优化点呢?对此,有必要对布局文件的文件格式和内容探究一波,随意打开一个布局文件,其源代码和二进制文件格式内容如下:

//创建drawable
private Drawable loadDrawableForCookie(@NonNull Resources wrapper, @NonNull TypedValue value, int id, int density) {
    ...
    if (file.endsWith(".xml")) { //对xml文件解析并创建drawable
        final String typeName = getResourceTypeName(id);
        if (typeName != null && typeName.equals("color")) {
            dr = loadColorOrXmlDrawable(wrapper, value, id, density, file);
        } else {
            dr = loadXmlDrawable(wrapper, value, id, density, file);
        }
    } else { //对.png等其他图片解析并创建drawable
        final InputStream is = mAssets.openNonAsset(value.assetCookie, file, AssetManager.ACCESS_STREAMING);
        final AssetInputStream ais = (AssetInputStream) is;
        dr = decodeImageDrawable(ais, wrapper, value);
    }
    ...
}

从布局文件文件格式上,可以看到,布局文件有一个字符串池 strPool 和一个数组 resMap,为了阐述其作用,假如布局文件中有一个属性"layout_width",其在布局文件中包含的信息如下:

  • 字符串偏移数组(标记 1),指向字符串池(标记 2),用于从字符串池中获取标签(如:"LinearLayout")或属性字符串(如:"layout_width")
  • 字符串池(标记 2),布局文件中的唯一字符串池,保存布局文件中标签或属性字符串名,即:"layout_width"
  • 属性数组Resids(标记 3),包含当前文件所有属性的整型 id 值,属性"layout_width"的 id 值:10100F4h。从数组中整型 id 值提示的属性名(类似:attr_layout_width(10100F4h)),可以看到其属性名与字符串池中名称一一对应。

我们知道 layout_width 本身是一个attr属性,查看系统源码中的 public.xml,可以看到:

其整型 id 值与上面 layout 文件中的值,即 attr_layout_width 后面的整型 id 值完全一致,都是0x010100f4。系统属性的 id 值是固定的,而且,一个布局文件的属性由字符串名称或整型 id 值来唯一标识,那么,这里是否只需要 id 就可以标识属性,而属性的字符串名可以删除?

猜想:每个属性都有字符串名和整型 id 值,为了性能,在解析布局文件中每个节点的属性时,是根据整型 id 值而不是字符串名来唯一标识,并据此拿到该属性的值即可。

为了验证我们的猜想,简单修改字符串池中的一个属性字符串:layout_width -> llyout_width,验证可以运行成功。由前面的叙述可知 layout 目录下文件有近 9K 个,影响范围很广,如果可行其收益预计会很大,同时也更需要谨慎。

通过翻看源码发现,每个属性(attr)包含一个对应的整型 id 值,在parseXml()解析布局文件得到标签后,获取其属性值时果然会直接根据整型 id 值来获取。这里属于比较底层的代码,因为与性能相关,一般 rom 厂商似乎不会改到这里,其兼容性可能不会受影响。

源码中解析布局文件,标识属性并获取属性值的代码如下:

frameworks/base/core/jni/android_util_AssetManager.cpp

// 通过属性整型id值获取属性值
static jboolean android_content_AssetManager_applyStyle(...) {
    ...
    while (ix < NX && curIdent > curXmlAttr) {
        ix++;
        curXmlAttr = xmlParser->getAttributeNameResID(ix); //获取属性id值
    }
    if (ix < NX && curIdent == curXmlAttr) { //通过id值来标识属性
        block = kXmlBlock;
        xmlParser->getAttributeValue(ix, &value); //获取属性值
        ...
    }
    ...
}
uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const {
    int32_t id = getAttributeNameID(idx);
    // mTree.mResIds 就是 Resids数组;返回值即属性id值
    if (id >= 0 && (size_t)id < mTree.mNumResIds) {
        return dtohl(mTree.mResIds[id]);
    }
    return 0;
}

具体实现上,该思路一共有三个要点,总体收益 1.9MB+ ,详见如下分析。

属性字符串名称修改

首先,我们将所有能与 Resids 数组一一对应的字符串全部替换为""字符串,对所有 layout 目录下的文件进行处理,得到收益 1.1MB+

将此优化进行推广,对资源目录 res 下所有以 “.xml” 后缀的文件进行优化,得到附加收益 180K+。这部分收益不大的原因是其他目录下的“.xml” 后缀文件,多为 drawable 或者 anim 目录下的文件,这类文件中 Resids数组没有或者包含的属性不太多。

偏移数组修改

观察 layout 目录下布局文件中字符串池格式,发现包含偏移数组和字符串池,其中,每个节点从字符串池中读取字符串是根据偏移数组获取。所以,这里可以只修改偏移数组,将其指向同一个字符串值,从而将空字符串合并为一个,减少字符串池,节省空间,如下图:

上图中,左图,是将与 Resids 数组一一对应的字符串全部替换为""字符串了,其偏移数组会指向 5 个""字符串;右图,是修改偏移数组,将其值修改为指向第一个""字符串,同时删除冗余的 4 个""字符串,此方案得到收益 300K+。

命名空间去除

在解析布局文件获取属性值的时候,我们发现属性的命名空间字符串很长,例如:"http://schemas.android.com/apk/res/android"。而且每个布局文件都至少存在一个命名空间字符串,其出现相当频繁。我们猜想,在获取属性值时,是否也没解析属性的命名空间字符串呢?而在前面我们说过,属性值的获取只需要属性id值来标识,没用到命名空间字符串。将命名空间字符串替换为空串后,发现的确没有问题,此优化得到收益500K+。

最终优化形式如下:

标记 1--属性字符串名称裁剪,将字符串池中每一个字符串替换成""空字符串;

标记 2--偏移数组修改,将字符串池中所有""空字符串合并为一个;

标记 3--命名空间去除,将字符串池中命名空间字符串替换成""空串。

App Bundle 兼容

以上优化都属于通用方案,都能在国内 App 上接入使用。然而,目前在海外 Google Play 商店上,App 均采用的是 App Bundle 文件格式(即 AAB),其中resources.arsc文件和 layout 目录下布局文件的格式已和上述格式不同,谷歌在其之前二进制文件格式的基础上,使用了 protobuf 格式,以增强对该文件格式中内容的可扩展性和鲁棒性。

在 AAB 文件 split 成多个 APK 的时候,会有 protobuf 格式到二进制 xml 格式的转换,而这个转换过程在 Google Play 上,我们无法更改。所以只能针对 AAB 文件格式中的资源文件格式进行优化了,通过 App Bundle 解析布局文件中的属性并不复杂,这里不再详述,针对上述优化方案在 AAB 文件上的移植结果如下:

资源路径缩短:

  • 无法实现,因为resources.arsc文件中常量池裁剪无法实现, 即全部替换为同一个字符串"_"会转换失败,原因在于执行 protobuf 格式到二进制 xml 格式的转换中,会判断当前的键字符串是否重复,如果是,那么会直接返回,无法解析通过。

frameworks/base/tools/aapt2/format/proto/ProtoDeserialize.cpp

//读取protobuf格式的资源文件
static bool DeserializePackageFromPb(...) {
    ...
    for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) {
        ...
        //FindOrCreateValue搜寻已存在的或者创建新的ResourceConfigValue,搜寻时会判断键字符串是否已存在
        ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product());
        if (config_value->value != nullptr) {//发现已存在config_value,返回错误
          *out_error = "duplicate configuration in resource table";
          return false;
        }
        ...
    }
    ...
}

layout 优化:

  • 属性字符串名称裁剪:可以实现,取得收益 400K+;
  • 偏移数组修改:无法实现,因为最后转换 protobuf 格式到二进制 xml 格式,这一步是在 Google Play 本地的 aapt2 命令环境中实现,无法修改;
  • 命名空间去除:可以实现,取得收益 200K+

因此,我们的优化方案最终在某海外 App 上总体可以取得 600K+收益。在完成对 AAB 文件的优化后,通过 split 后获取其中的 base-master.apk,查看其中的 layout 布局文件,收益示意图如下:

标记 1--属性字符串名称裁剪命名空间去除已优化;

标记 2--偏移数组修改,无法优化,因此还是存在多个""字符串,而不像 APK 里面可以合并为一个。

总结

可见,在资源文件优化方面,还是可以另辟蹊径,有不少通用优化可以做,总结起来,主要工作还是在对无用字符串的搜寻和确认上。通常,编译后的二进制文件中,字符串的作用有:

  • 代码执行需要。这类字符串是必须的,但可以考虑是否可以精简,即混淆;
  • 调试辅助功能。这类字符串不一定必须,可以去除,如果需要保留,可以做相应的 keep 功能;
  • 文件格式设计者当初为了格式完备性引入,已拓展后续功能。这类字符串可能是与性能相违背的,如未使用可以直接去除;

后两个点便是搜寻冗余字符串和优化包大小的重点方向。

优化收益落地

App 收益
抖音 2.16MB+
飞书 1.6MB+

本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/rMRjof-oVJDtRWH0aEk7mw

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:7月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:7月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:7月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:7月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:7月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:7月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:7月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:7月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:7月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:7月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:7月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:7月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:7月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:7月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:7月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:7月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:7月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:7月以前  |  398次阅读  |  详细内容 »
 相关文章
简化Android的UI开发 4年以前  |  520698次阅读
Android 深色模式适配原理分析 3年以前  |  28623次阅读
Android阴影实现的几种方案 1年以前  |  10781次阅读
Android 样式系统 | 主题背景覆盖 3年以前  |  9583次阅读
 目录