【Android之路】安卓资源与编译初步

在制作安卓客户端的时候,,如果我们仔细观察,会看到这样的文件目录:

咱们今天着重于介绍assestres目录

二者的区别

assest目录中常用于存放软件是视频和音频等文件,这些文件通常是不需要做适配的,而res目录中则是存放需要进行设备适配的文件,就比如图片、文字等。在进行资源编译的时候,aeerst目录是不会被AAPT编译的,而res则是会被编译的。

什么是AAPT?

AAPT 全称是 Android Asset Packaging Tool ,是 Android SDK 自带的一个底层命令行工具,用来在构建 APK 时处理资源文件。

你在用 Android Studio 编译 APK / AAB 时,它会在后台自动调用 AAPT。


🌟 主要功能

  1. 打包资源(Packaging Resources)

    • res/ 目录中的图片、布局 XML、字符串、主题等资源编译成二进制格式,输出到 resources.arsc
    • 同时会把资源 ID 写入 R.javaR.class,让代码可以通过 R.string.xxxR.layout.xxx 等访问。
  2. 生成 R.java

    • 每次你添加/修改资源文件,AAPT 会自动扫描并分配唯一的整型 ID,生成 R.java,供应用代码引用。
  3. 压缩与合并资源

    • 会对 PNG、XML 等资源进行优化压缩,减少 APK 体积。
  4. 校验与构建 APK

    • 在打包过程中检查资源是否有效(如 XML 格式、图片路径),并最终打包成 .apk 文件。

🛠️ 常用命令(AAPT1)

如果你在命令行中运行:

bash 复制代码
aapt dump badging app-debug.apk

可以查看 APK 的应用包名、版本号、支持的屏幕分辨率、权限等信息。

例如输出:

复制代码
package: name='com.example.myapp' versionCode='1' versionName='1.0'
sdkVersion:'21'
targetSdkVersion:'33'
uses-permission: name='android.permission.INTERNET'
application-label:'MyApp'

其他常用命令:

  • aapt list app.apk 查看 APK 内部所有文件。
  • aapt dump permissions app.apk 查看声明的权限。

⚡ AAPT1 与 AAPT2 的区别

  • AAPT1:旧版打包工具,Android Gradle Plugin 3.0 以前默认使用。

  • AAPT2(现在默认):对资源编译做了增量优化,提高速度和错误提示质量。

    • 支持并行编译资源。
    • 错误提示更直观。

📌 总结

AAPT 是 Android 构建过程中专门处理资源的工具。

开发者一般不用手动调用,但在分析 APK、反编译、或 CI/CD 自动化中常用 aapt dump badging 来查看包信息。

如果你在分析开源 Android 项目时,看到日志里出现:

复制代码
AAPT: error: resource xxx not found

就是资源打包或引用出错时 AAPT 报告的错误。

res是怎么进行资源适配的?

在 Android 里,res/ 目录就是资源管理系统 的入口。

所谓"资源适配",就是让系统在不同设备特征 (屏幕密度、分辨率、语言、暗色模式、API 等)下自动选择最合适的资源文件。

这一切都是由 资源限定符(Resource Qualifiers)AAPT + 运行时资源选择机制共同完成的。


1️⃣ res/ 目录的基本结构

复制代码
res/
 ├─ drawable/            # 默认的图片、shape、selector
 ├─ drawable-hdpi/       # 针对 hdpi 屏幕的图片
 ├─ layout/              # 默认布局
 ├─ layout-land/         # 横屏布局
 ├─ mipmap-xxxhdpi/      # 启动图标
 ├─ values/              # 默认的 colors、strings、styles
 ├─ values-zh/           # 中文(简体)资源
 ├─ values-night/        # 夜间模式资源
 └─ raw/                 # 原始文件

每个子目录可以带限定符(Qualifier),用来声明这个目录的资源针对什么情况使用。


2️⃣ 常用资源限定符

类别 形式示例 含义
语言/地区 values-zh/values-zh-rCN/ 中文,或中文(中国)
屏幕方向 layout-land/layout-port/ 横屏 / 竖屏
屏幕尺寸 layout-sw600dp/ 最小宽度 600dp(平板常用)
屏幕密度 drawable-mdpi/drawable-hdpi/drawable-xhdpi/drawable-xxhdpi/ 对应 1x、1.5x、2x、3x 像素密度
UI 模式 values-night/ 夜间模式(暗色主题)
平台版本 values-v21/drawable-v24/ Android 5.0 (API 21) 及以上才用
触控方式 drawable-notouch/ 没有触摸屏的设备
布局方向 layout-ldrtl/ 支持从右到左布局(阿语等)

系统在运行时会根据设备实际配置(Configuration)自动选择最匹配的目录。


📌 示例:不同屏幕密度的图片适配

假设我们放置以下资源:

复制代码
res/
  drawable-mdpi/logo.png      (48x48)
  drawable-hdpi/logo.png      (72x72)
  drawable-xhdpi/logo.png     (96x96)
  drawable-xxhdpi/logo.png    (144x144)
  • mdpi 设备 (160dpi)→ 用 mdpi/logo.png
  • xhdpi 设备 (320dpi)→ 用 xhdpi/logo.png

如果缺少某一密度的资源,系统会自动缩放最接近的那个(有时会导致模糊)。


📌 示例:不同语言适配

复制代码
res/
  values/strings.xml
  values-zh/strings.xml
  values-en/strings.xml

如果设备系统语言是中文,加载 values-zh/strings.xml

是英文就加载 values-en/strings.xml

找不到就回退到默认 values/


📌 示例:夜间模式适配

复制代码
res/
  values/colors.xml        # 白天模式颜色
  values-night/colors.xml  # 夜间模式颜色

当用户切换到夜间模式 (UiModeManager 或主题切换),系统自动用 -night 资源。


3️⃣ 资源选择顺序(匹配规则)

Android 在运行时根据当前 Configuration 按以下优先级选择:

  1. 完全匹配所有限定符的资源
  2. 匹配度高的目录优先
  3. 如果没有找到完全匹配的,就回退到默认资源目录

例如当前设备:zh-CN、横屏、xhdpi

系统会按:layout-zh-rCN-land-xhdpilayout-zh-rCN-landlayout-zh-landlayout-landlayout/ 顺序去找。


4️⃣ 适配实践建议

  • 图片 :放在 mipmap-xxxhdpidrawable-xxxhdpi,至少提供 xxhdpi,系统可缩放。
  • 布局 :针对平板用 layout-sw600dp,横竖屏用 layout-land/port
  • 语言 :在 values-xx 下放多语言 strings.xml
  • 夜间模式 :用 -night
  • 版本差异 :在 values-v21/ 提供 Material 主题资源,旧版本用默认。

⚡ 总结

res 适配的核心是"限定符 + 系统自动匹配"。

你只要按规则命名不同目录,Android 在运行时会根据设备特性自动加载最合适的资源。

对于图片、布局、字符串、颜色、样式等都通用,几乎不需要手动写逻辑判断。

资源的访问

在 Android 里,"访问资源"有两种主要途径:

  1. 通过代码 (Java/Kotlin)
  2. 通过 XML(布局文件、样式文件等)

1️⃣ 资源在构建时的组织

  • AAPT/AAPT2 会扫描 res/ 下的所有资源文件,并为它们生成一个全局唯一的 ID,写进自动生成的 R 类(R.javaR.class)。
  • 你在代码中访问的 R.drawable.logoR.string.app_name 等,其实就是一个 int 常量,指向打包后的资源表中的索引。

例如:

java 复制代码
public final class R {
    public static final class drawable {
        public static final int logo = 0x7f080057;
    }
    public static final class string {
        public static final int app_name = 0x7f100004;
    }
}

2️⃣ 在 代码 中访问资源

几乎所有资源都通过 Context 或其子类的方法访问(ActivityApplicationView 都是 Context)。

资源类型 示例访问方式
字符串 getString(R.string.app_name)
带占位符的字符串 getString(R.string.welcome, userName)
颜色 ContextCompat.getColor(context, R.color.primary)
Drawable ContextCompat.getDrawable(context, R.drawable.ic_launcher)
尺寸 (dp/sp) getResources().getDimension(R.dimen.padding_large)
数组 getResources().getStringArray(R.array.planets)
原始文件 (raw) InputStream is = getResources().openRawResource(R.raw.music);
Assets (非res目录) AssetManager am = getAssets(); InputStream is = am.open("file.txt");

⚠️ 注意:assets/ 目录下的内容不会生成 R ID,需要用 AssetManager 访问。


示例:加载图片并显示

kotlin 复制代码
val imageView: ImageView = findViewById(R.id.myImage)
imageView.setImageResource(R.drawable.logo)

示例:加载颜色并设置背景

kotlin 复制代码
val color = ContextCompat.getColor(this, R.color.primary)
myLayout.setBackgroundColor(color)

示例:加载字符串并格式化

kotlin 复制代码
val welcome = getString(R.string.welcome_user, "张博")
textView.text = welcome

3️⃣ 在 XML 中访问资源

在布局或样式文件里,你通常通过 @ 前缀访问资源:

用法 示例
布局属性 android:src="@drawable/logo"
字符串 android:text="@string/app_name"
颜色 android:background="@color/primary"
尺寸 android:padding="@dimen/padding_large"
引用另一个资源 @style/AppTheme@array/planets
系统内置资源 @android:color/black@android:style/Theme.Material

@? 的区别

  • @:直接引用一个资源 ID
    例:android:text="@string/app_name"
  • ?:引用当前主题中定义的属性
    例:android:colorBackground="?attr/colorPrimary"

这使得主题可以动态换肤。


4️⃣ 特殊资源访问方式

  • TypedArray / obtainStyledAttributes

    用于读取自定义属性(自定义控件常用)。

  • Resources.Theme

    可以根据当前主题解析 ?attr/ 属性。

  • getIdentifier(name, defType, packageName)

    通过字符串动态获取资源 ID(不推荐频繁使用,因为性能较低):

    kotlin 复制代码
    val resId = resources.getIdentifier("logo", "drawable", packageName)
    imageView.setImageResource(resId)

5️⃣ 资源访问的运行时特性

  • 系统在访问资源时会根据当前设备配置(语言、夜间模式、屏幕密度等)选择最合适的版本。
  • 你在代码中只写 R.drawable.logo,运行时会自动加载合适的 drawable-hdpi/logo.pngdrawable-xxhdpi/logo.png
  • 当配置变化(如横竖屏切换、语言切换、夜间模式)时,Activity 会重新创建并加载对应资源。

🚀 总结

资源访问的核心:

  • 构建时: AAPT 为所有资源生成 ID 并写入 R 类。
  • 运行时: Context 根据设备配置选择最匹配的资源文件。
  • 代码访问:getResources()getString()ContextCompat 等。
  • XML 访问:@?attr/
相关推荐
阿巴斯甜20 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker20 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952721 小时前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android