初级与中级的Android面试题区别在哪里

本系列为小说《逆袭西二旗》的技术讲解,用于详细说明剧情里涉及的开发细节。

Android 文件系统

Android 文件系统是一套结构化环境,负责管理 Android 设备上的数据存储,让应用和用户能高效地存储、获取和管理文件。

它基于 Linux 文件系统架构实现,既为应用提供了私有和共享的存储空间,又遵循严格的安全与权限模型。

面试问题

Android 如何在文件系统中执行安全与权限控制?

有哪些机制能防止应用访问其他应用的私有数据?

核心组件

Android 文件系统包含多个目录和分区,每个都有明确的用途:

  • 系统分区(/system):存储核心系统文件,包括 Android 框架库、系统应用和配置文件。这个分区对普通用户和应用是只读的,防止意外或恶意修改。
  • 数据分区(/data) :存储应用专属数据,比如数据库、偏好设置、用户生成的文件。每个应用都有独立的 /data/data/[包名] 目录,确保数据安全。
  • 缓存分区(/cache):用于存储临时数据(如系统更新包、缓存文件),这些数据不需要在设备重启后保留。
  • 外部存储(/sdcard 或 /storage):提供多应用可访问的共享存储空间,常用于存放图片、视频、文档等媒体文件,可是内置存储或可卸载的 SD 卡。
  • 临时文件(/tmp):应用运行时存储临时文件的位置,通常在应用或系统重启后会被清空。

Android 中的文件访问方式

应用通过 Android 框架提供的 API 与文件系统交互。根据文件的可见性和生命周期需求,应用可以将文件存在不同位置:

  • 内部存储:应用沙盒内的私有存储,仅当前应用可访问,适合存放敏感或应用专属数据。
  • 外部存储:多应用可访问的共享存储,用于存放用户生成的内容或需要在应用外访问的媒体文件。

文件权限与安全

Android 文件系统强制使用严格的权限模型:

  • 应用私有数据:存在应用内部存储的数据是私有的,仅该应用可访问。
  • 共享文件 :应用间共享文件需通过外部存储,或结合适当权限的 Content Provider 实现。
  • 作用域存储 :Android 10 引入,限制了对共享存储的直接访问,要求应用通过 MediaStore 或 SAF(存储访问框架)API 操作文件。

总结

Android 文件系统是一套健壮且安全的环境,为应用和用户组织、管理数据存储。它为系统文件、应用专属数据和共享内容提供了专用空间,同时遵循严格的安全与权限控制。

开发者通过各类 API 与该系统交互,实现符合应用需求的高效、安全的文件管理。

ART、Dalvik 和 Dex 编译器

Android 应用依赖独特的运行时环境和编译流程在设备上执行,其中 Android Runtime(ART )、DalvikDex 编译器 是核心角色,它们确保应用在性能、内存效率和设备兼容性上达到优化。

面试问题

ART 中的提前编译(AOT )与 Dalvik 中的即时编译(JIT)有什么区别?

对应用启动速度和 CPU 占用有什么影响?

Android Runtime(ART)

ART 是 Android 4.4(KitKat)中引入的托管式运行时,从 Android 5.0(Lollipop)开始成为默认运行时,替代了 Dalvik 负责执行 Android 应用,并带来了多项增强。

ART 采用 提前编译(AOT) 方式处理应用:在应用安装时将字节码转换为机器码,省去了运行时的 即时编译(JIT) 步骤,从而加快应用启动速度、降低运行时的 CPU 占用。

ART 的核心特性包括:

  • 性能提升AOT 编译生成优化后的机器码,减少运行时开销。
  • 垃圾回收:引入了改进的垃圾回收机制,提升内存管理效率。
  • 调试与性能分析支持:提供更强大的开发者工具,比如详细的堆栈跟踪和内存使用分析功能。

Dalvik

DalvikART 之前 Android 的初代运行时,设计用于在内存和算力有限的虚拟环境中执行应用。

Dalvik 采用 即时编译(JIT) 方式:在运行时将字节码转换为机器码。这种方式减少了应用安装时间,但实时编译会增加运行时开销。

Dalvik 的核心特点包括:

  • 紧凑的字节码 :使用 .dexDalvik 可执行文件)格式,优化了内存占用和执行效率。
  • 基于寄存器的虚拟机 :不同于 Java 虚拟机的栈式结构,Dalvik 是基于寄存器的,提升了指令执行效率。

Dalvik 的局限性(如启动慢、CPU 占用高),使其在 Android 新版本中被 ART 取代。

Dex 编译器

Dex 编译器 负责将 Java/Kotlin 编译器生成的 Java 字节码,转换为 .dexDalvik 可执行文件)格式。这种 .dex 文件体积紧凑,专为 DalvikART 运行时环境优化。

Dex 编译器的核心作用

Dex 编译器 是 Android 应用高效运行的关键,核心功能包括:

  • 多 dex 支持 :当应用方法数超过 64K 限制时,编译器会将字节码拆分到多个 .dex 文件中。
  • 字节码优化:对字节码进行优化,提升 Android 设备上的内存占用和执行性能。

Dex 编译流程已集成到 Android 构建系统中,在应用开发的构建阶段自动执行。

从 Dalvik 到 ART 的过渡

DalvikART 的切换,是 Android 运行时环境的重大升级。ARTAOT 编译、增强型垃圾回收和性能分析能力,为开发者和用户带来了更好的体验。由于使用了 .dex 文件,为 Dalvik 设计的应用可以无缝兼容 ART,让开发者能平滑迁移。

总结

ARTDalvikDex 编译器 是 Android 应用执行的基础:ARTAOT 编译和性能提升取代了依赖 JITDalvikDex 编译器 则通过将 Java 字节码转换为适配两种运行时的 .dex 文件,衔接了整个流程。这些组件共同保障了 Android 应用的高效、快速和可靠运行。

APK 文件与 AAB 文件有什么区别

Android 应用的分发和安装主要使用两种格式:APK (Android 安装包)和 AAB(Android App Bundle)。两者都用于交付应用,但在用途、结构和安装流程上有显著差异。

面试问题

AAB 格式如何针对不同设备配置优化应用交付?相比传统 APK 分发有哪些优势?

APK(Android 安装包)

APK 是传统的 Android 应用分发/安装格式,是一个完整的可安装包,包含应用在设备上运行所需的所有资源、代码和元数据。

APK 是自包含的,会包含适配所有设备配置(如屏幕密度、CPU 架构、语言)的资源------这会导致文件体积较大,因为其中可能包含对当前设备无用的资源。

APK 可以直接安装到设备,也能在官方应用商店外分享或侧载。但开发者需要自行管理多设备的配置适配,APK 中往往会包含特定设备不需要的资源。

AAB(Android App Bundle)

AAB 是 Google 推出的发布格式,并非像 APK 那样的可直接安装格式。开发者将 AAB 上传到 Google Play,由商店在下载时生成适配目标设备的优化 APK

AAB 是模块化的,会将不同配置的资源和代码拆分成独立的 bundleGoogle Play 利用这种结构,只向用户交付对应设备所需的资源和代码(比如特定屏幕尺寸、CPU 架构、语言的版本),从而减小应用在设备上的体积。

由于 AAB 是在服务端处理的,它不能直接安装。开发者若要侧载,需要借助 bundletool 等工具生成可安装的 APK

APK 与 AAB 的核心区别

  1. 用途与结构

    • APK:包含所有配置资源和代码的完整安装包。
    • AAB :模块化的发布格式,会生成适配设备的 APK
  2. 文件体积

    • APK:包含所有设备的资源,体积较大。
    • AAB :可生成更小的优化 APK,减少用户端的应用体积。
  3. 分发方式

    • APK:可直接分享、侧载到设备。
    • AAB :需上传到 Google Play ,由商店生成优化 APK 后分发给用户。
  4. 管理方式

    • APK:开发者需手动管理资源和配置。
    • AAB :将配置管理交由 Google Play 自动化处理。
  5. 工具与兼容性

    • APK:支持所有 Android 设备和应用商店。
    • AAB :默认需要 Google Playbundletool 生成可安装 APK ,不兼容非 Google 应用商店。

总结

APK 是独立的可直接安装包,而 AAB 是面向现代分发的格式,能生成适配设备的 APK 。开发者使用 AAB 可以获得更小的应用体积和自动化的配置管理,而 APK 仍是侧载(绕过官方应用商店安装 App)和非 Google Play 分发的必要选择。理解两者的差异,能帮助开发者根据分发策略选择合适的格式。

R8 优化

R8 是 Android 构建流程中用于减小 APK/AAB 体积、提升运行性能的代码压缩与优化工具。它取代了旧的 ProGuard 工具,无缝集成到 Android 构建系统中,提供代码压缩、优化、混淆和资源管理等进阶功能。

面试问题

R8 优化如何提升应用性能并减小 APK/AAB 体积?

R8ProGuard 有什么区别?它带来了哪些优势?

R8 的工作原理

R8 在构建阶段处理应用代码,实现以下目标:

  • 代码压缩 :移除代码库中未使用的类、方法、字段和属性,减小最终 APK/AAB 的体积。
  • 代码优化:简化和重构代码以提升运行性能,包括内联方法、移除冗余代码、合并重复代码块等。
  • 代码混淆:重命名类、方法和字段的名称,增加逆向工程的难度。
  • 资源优化 :移除未使用的资源(如布局、Drawable、字符串),进一步减小应用体积。

R8 优化的核心特性

  • 无用代码移除:分析代码库,识别并删除应用无法访问或未使用的代码。
  • 方法内联:将短方法直接内联到调用处,减少方法调用开销,提升运行性能。
  • 类合并:将相似的类或接口合并,减小内存占用并提升效率。
  • 不可达代码消除:完全移除永远不会执行的代码路径。
  • 常量折叠与传播:简化表达式,将变量替换为其常量值。
  • 代码混淆:用更短、无意义的名称替换代码中的有意义命名,既减小体积又提升逆向难度。

R8 的配置

R8 使用 ProGuard 规则进行配置,你可以指定哪些代码需要排除在压缩、混淆或优化之外。常见场景包括:

  • 保留反射用代码 :通过反射访问的类或方法,必须在 ProGuard 规则中显式保留。
  • 排除第三方库:部分库可能需要特定规则才能避免功能异常。

示例:保留某个类的 ProGuard 规则

kotlin 复制代码
-keep class com.example.myapp.MyClass { *; }

R8 的优势

  • 深度集成 :内置到 Android 构建系统中,只需配置 ProGuard 规则,无需额外设置。
  • 更高效率 :将压缩、优化、混淆合并为单次处理,比 ProGuard 更快更高效。
  • 减小应用体积 :移除未使用的代码和资源,显著降低最终 APK/AAB 的大小。
  • 增强安全性:混淆功能增加了攻击者逆向工程的难度,保护知识产权。

R8 的局限性

  • 过度压缩风险 :若配置不当,R8 可能移除间接引用的代码或资源,导致运行时错误。
  • 配置复杂度 :对于使用反射或动态类加载的复杂项目,编写 ProGuard 规则会比较有挑战。
  • 调试难度提升:混淆会让堆栈跟踪包含无意义的名称,增加调试难度。

总结

R8 是现代 Android 开发中必不可少的工具,提供了全面的代码压缩、优化和混淆能力。它通过减小应用体积、提升运行性能、增强安全性,帮助开发者交付高效紧凑的应用。正确配置 ProGuard 规则是关键,能避免必要代码被误删,保证功能正常。

减小应用体积

优化 Android 应用体积对提升用户体验至关重要,尤其是对于存储有限或网络较慢的用户。可以通过多种策略在不影响功能的前提下减小应用体积。

面试问题

你的应用包含高清图片,导致 APK/AAB 体积大幅增加。如何在保证画质的前提下优化图片资源?应该用什么格式实现最高效的压缩?

你的应用包含多个功能,但大部分用户很少使用其中一些。如何实现方案来减小初始安装包体积,同时让这些功能在需要时可用?

移除未使用的资源

未使用的资源(如图片、布局、字符串)会不必要地增大 APK/AAB 体积。Android Studio 的 Lint 工具可以帮你识别这些资源。移除后,在 build.gradle 中开启 shrinkResources,让构建流程自动移除未使用资源:

kotlin 复制代码
android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
        }
    }
}

启用 R8 代码压缩

R8 是 Android 默认的代码压缩与优化工具,会移除未使用的类和方法,同时混淆代码以减小体积。正确配置 ProGuard 规则可以避免关键代码或反射类库被误删:

kotlin 复制代码
android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

优化资源

优化图片、XML 等资源可以显著减小应用体积:

  • 矢量图(Vector Drawables) :用矢量图替代 PNGJPEG 等位图,既能缩放又能节省空间。
  • 图片压缩 :使用 TinyPNGImageMagick 等工具压缩位图,在画质无明显损失的前提下减小体积。
  • WebP 格式 :将图片转为 WebP 格式,它比 PNGJPEG 的压缩率更高。

配置示例(启用矢量图支持):

kotlin 复制代码
android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

使用 AAB

切换到 AAB 格式后,Google Play 会生成适配目标设备的优化 APK,只包含对应设备所需的资源和代码(如特定屏幕密度、CPU 架构、语言),从而减小应用体积:

kotlin 复制代码
android {
    bundle {
        density {
            enableSplit true
        }
        abi {
            enableSplit true
        }
        language {
            enableSplit true
        }
    }
}

移除不必要的依赖

检查项目依赖,移除未使用或冗余的库。可以用 Android Studio 的 Gradle Dependency Analyzer 识别体积较大的库和传递依赖。

优化原生库

若应用包含原生库,可以通过以下策略减小其影响:

  • 排除未使用的架构 :在 build.gradle 中用 abiFilters 只保留所需的 ABI
  • 剥离调试符号 :用 stripDebugSymbols 移除原生库中的调试符号。

配置示例:

kotlin 复制代码
android {
    defaultConfig {
        ndk {
            abiFilters "armeabi-v7a", "arm64-v8a" // 只保留需要的 ABI
        }
    }
    packagingOptions {
        exclude "**/lib/**/*.so.debug"
    }
}

通过 ProGuard 规则减少调试信息

调试元数据会增大 APK/AAB 体积,可以在 proguard-rules.pro 中配置移除这些信息:

diff 复制代码
-dontwarn com.example.usedlibrary.**
-keep class com.example.important.** { *; }

使用动态功能模块

动态功能模块可以将不常用的功能拆分为按需加载的模块,减小初始下载包的体积:

kotlin 复制代码
dynamicFeatures = [":feature1", ":feature2"]

避免应用内包含大型资源

  • 将视频、高清图片等大型资源托管到 CDN,在运行时动态加载。
  • 媒体内容使用流式传输,而非打包到应用中。

总结

减小 Android 应用体积需要结合多种策略:移除未使用资源、启用 AAB 代码压缩、优化资源、使用 AAB 格式等。此外,检查依赖、优化原生库、模块化功能也能进一步减小体积。这些实践能让应用更轻量化、性能更好,同时提供出色的用户体验。

进程

在 Android 中,进程是应用组件的运行环境。每个 Android 应用都在独立进程中以单线程运行,与其他应用隔离,以此保证系统安全、内存管理和容错性。Android 进程由 Linux 内核管理,遵循严格的生命周期规则。默认情况下,同一应用的所有组件都运行在同一个进程和线程(即主线程)中。

面试问题

你正在开发一个应用,其中不同的 Android 组件需要运行在独立进程中。如何在 AndroidManifest 中配置?使用多进程有哪些潜在弊端?

Android 系统在内存不足时,会通过基于优先级的进程管理系统决定杀死哪些进程。请解释系统如何给进程排序优先级?开发者应该遵循哪些策略防止重要进程被终止?

工作原理

当启动一个 Android 应用时,系统会通过 Linux 的 fork() 系统调用为其创建新进程。每个进程都是 DalvikART 虚拟机的独立实例,支持代码的安全独立执行。Android 会为每个进程分配唯一的 Linux 用户 ID(UID),以此实现严格的安全边界,包括权限控制和文件系统隔离。

应用组件与进程的关联

默认情况下,同一应用的所有组件都运行在同一个进程中,大多数应用都遵循这个标准。不过开发者可以在 AndroidManifest.xml 中通过 android:process 属性自定义进程分配,该属性可用于 <activity><service><receiver><provider> 等组件,让组件运行在独立进程或选择性共享进程。

<application> 元素也支持该属性,用于定义所有组件的默认进程。

示例:

xml 复制代码
<service
    android:name=".MyService"
    android:process=":remote" />

在这个例子中,服务 MyService 运行在名为 :remote 的独立进程中,实现了独立运行和更高的容错性。

此外,不同应用的组件如果拥有相同的 Linux 用户 ID 且签名一致,可以共享同一个进程。Android 会根据系统资源需求动态管理进程:当内存不足时,会终止优先级较低的进程;而当关联组件需要工作时,系统会重启进程,以此保证系统性能和用户体验的最优。

进程与应用生命周期

Android 会根据系统内存和应用当前状态,按照严格的优先级层级管理进程和应用生命周期:

  1. 前台进程:正在与用户交互的进程,优先级最高,几乎不会被杀死。
  2. 可见进程 :对用户可见但未交互的进程(比如对话框后的 Activity)。
  3. 服务进程:运行后台服务的进程(比如同步数据、播放音乐)。
  4. 缓存进程:闲置的进程,保留在内存中以便快速重启,优先级最低,内存不足时会被优先杀死。

Android 系统会自动终止低优先级进程以释放内存,保证系统稳定。

安全与权限

每个 Android 进程都通过 Linux 安全模型实现沙盒隔离,强制基于权限的访问控制。这种隔离确保应用无法访问其他进程的数据,除非通过 Android 权限系统显式授予权限。这个安全模型是 Android 多任务环境的基础,同时保障了系统稳定性和数据隐私。

总结

Android 中的进程是应用组件的运行环境,保证了隔离、安全、高效的运行。进程由系统创建、调度和终止,依据内存约束、用户活动和应用优先级。开发者可以通过清单文件的配置和权限管理,进一步控制进程行为,实现健壮、可扩展的应用开发。

进阶:何为 Android 的四大组件

ActivityService、广播、ContentProvider 被称为 Android 四大组件,是因为它们是应用与系统、其他应用交互的核心构建块。这些组件管理应用的生命周期、定义应用行为、实现进程间通信,与 Android 的进程和应用生命周期模型紧密关联。

各组件与 Android 进程的关联

  1. Activity :代表一个带界面的屏幕,是用户交互的入口,与 Android 进程生命周期高度绑定。当用户打开应用时,系统会启动 Activity 并创建对应的进程;如果进程被杀死,Activity 也会销毁,重启应用会创建新进程。
  2. Service :在无界面的情况下执行后台操作,即使应用不可见也能运行(比如播放音乐、下载文件)。Service 可以运行在应用的默认进程,也可以通过清单中的 android:process 属性指定独立进程。
  3. 广播:让应用接收并响应系统级广播消息(比如网络变化、电池状态更新)。即使应用未运行,广播触发时系统也会启动对应的进程(如果需要)。
  4. ContentProvider:管理应用的共享数据,提供对集中式数据库的读写能力,支持进程间通信------这意味着它可以跨应用共享数据,需要系统安全高效地管理进程。

与 Android 进程的关联

这些组件与 Android 进程绑定,因为系统会根据应用使用情况、内存可用性和任务优先级管理进程。当组件被触发(比如打开 Activity、接收广播)时,如果进程未运行,Android 会启动对应的进程。每个组件也可以通过清单中的 android:process 属性分配独立进程,为资源密集型任务提供更大的灵活性。

这意味着四大组件都可以在 Android 系统中拥有专属进程。由于这些组件可以配置为运行在独立进程中,它们获得了系统级能力,比其他组件更强大、更独立。这种设计支持后台执行、进程间通信和系统级交互,让 Android 应用能高效处理复杂的多进程任务。

总的来说。

ActivityService、广播、ContentProvider 是 Android 的核心组件,因为它们实现了应用的核心功能、用户交互和应用间通信。它们与 Android 进程模型的紧密关联,保证了高效的进程管理、最优的资源利用和系统级任务协调,是 Android 应用开发的基础。

相关推荐
·云扬·2 分钟前
MySQL四大系统库详解:作用、核心表与实用SQL查询
android·sql·mysql
普马萨特2 分钟前
移动网络信号指标与单位整理(2G/3G/4G/5G Android vs IoT)
android·网络·物联网
de之梦-御风11 分钟前
【电视投屏】针对“局域网投屏开源项目(Android 手机 ↔ Android TV)
android·智能手机·开源
threelab26 分钟前
Merge3D 三维引擎中 GeoJSON 数据加载的整体设计
android·3d
优选资源分享1 小时前
Escrcpy 便携版 v2.0.0:安卓手机电脑同屏软件
android·智能手机·电脑
2501_915918411 小时前
介绍如何在电脑上查看 iPhone 和 iPad 的完整设备信息
android·ios·小程序·uni-app·电脑·iphone·ipad
TheNextByte11 小时前
如何通过蓝牙将照片从 iPhone 分享到Android ?
android·gitee·iphone
2501_916008892 小时前
没有 Mac 如何在 Windows 上创建 iOS 应用描述文件
android·macos·ios·小程序·uni-app·iphone·webview
Android系统攻城狮4 小时前
Android ALSA进阶之处理PCM的ioctl命令snd_pcm_lib_ioctl:用法实例(一百)
android·pcm·alsa·音频进阶
诸神黄昏EX12 小时前
Android Build系列专题【篇六:VINTF机制】
android