第1章:课程概览与前置准备
1.1 Android 开发环境搭建
本课程所有代码实现基于 Android Studio 官方集成开发环境。请确保你已安装以下最小版本工具链:
- Android Studio Hedgehog (2023.1.1) 或更高版本
- Gradle 8.2+ 与 AGP 8.2+
- compileSdk 34、minSdk 21
- JDK 17
环境搭建核心步骤
- 从
developer.android.com/studio下载安装 Android Studio。 - 启动后,通过 SDK Manager 安装
Android 14.0 (API 34)系统映像与平台工具。 - 创建新项目,选择 Empty Views Activity,语言 Kotlin。
- 在
build.gradle.kts (Module: app)中确认以下配置:
android { compileSdk = 34 defaultConfig { minSdk = 21 targetSdk = 34 } } - 连接模拟器或真机,运行
Empty Activity验证环境可用性。
# 通过命令行验证设备连接
adb devices
# 输出示例:
# List of devices attached
# emulator-5554 device
1.2 模拟器 / 真机蓝牙配置
蓝牙是本章课程的核心硬件依赖。不同运行环境的配置方式如下表:
| 运行环境 | 配置要点 | 验证命令 / 操作 |
|---|---|---|
| 模拟器 | AVD 必须选择 API 28+ 且包含 Google Play 的系统映像;在 AVD 扩展设置中开启 Bluetooth 支持 | adb shell dumpsys bluetooth_manager 查看状态 |
| 真机 | Android 6.0+ 设备;在 设置 → 开发者选项 中开启 蓝牙 HCI 信息收集日志 | 手动打开蓝牙并配对另一台设备 |
真机调试时,必须动态请求
BLUETOOTH_CONNECT 和 ACCESS_FINE_LOCATION 权限。Android 12+ 不再允许通过清单静态授权完成蓝牙扫描。// AndroidManifest.xml 中声明(Android 12+ 仅声明,运行时仍需请求)
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
1.3 SharedPreferences 基础概念
SharedPreferences 是 Android 提供的轻量级键值存储方案,以 XML 文件形式保存在 /data/data/<package>/shared_prefs/ 目录下。其核心特征如下:
- 同步与异步:
SharedPreferences.Editor.commit()同步写入磁盘;apply()异步写入,推荐高频场景使用。 - 数据类型支持:
String、Set<String>、Int、Long、Float、Boolean。 - 适用场景:存储配置开关、用户偏好、设备标识、蓝牙配对信息等小规模数据。
- 限制:不适合存储超过 100KB 的结构化数据;跨进程访问需使用
ContentProvider或FileProvider。
本课程将使用 SharedPreferences 持久化蓝牙设备地址、配对状态及用户自定义名称,实现“断开连接后仍可识别历史设备”的特性。
| API 方法 | 说明 | 本课程使用位置 |
|---|---|---|
getString(key, default) |
读取字符串值 | 加载上次连接的蓝牙地址 |
putString(key, value) |
写入字符串值 | 存储已配对设备的名称 |
edit() |
获取 Editor 对象 | 所有写操作入口 |
apply() |
异步提交 | 蓝牙连接状态变更时 |
基本使用流程:
// 获取 SharedPreferences 实例(私有模式)
val prefs = context.getSharedPreferences("bluetooth_cache", Context.MODE_PRIVATE)
// 写入数据
prefs.edit()
.putString("last_device_address", "00:11:22:AA:BB:CC")
.putBoolean("is_paired", true)
.apply()
// 读取数据
val address = prefs.getString("last_device_address", null)
val paired = prefs.getBoolean("is_paired", false)