简介:这是一份面向高校计算机类专业学生与Android初学者的移动开发实战项目资源,适用于课程设计、期末大作业、毕设选题及技能进阶训练。项目实现了一个功能完整的个人账本APP,包含收支记录、分类统计、数据持久化等核心模块,配套提供经实测可运行的源代码、详细文档说明及开发环境配置指南。压缩包共103个文件,涵盖22个Java业务逻辑文件、52个XML布局与资源定义文件、14个UI图标PNG资源,以及build.gradle、gradlew.bat等构建脚本和README.md说明文档,整体仅1.65MB,轻量易解压、结构清晰、便于逐模块学习。已有576人下载学习,资源由一线高级安卓工程师整理上传,代码稳定可靠,附带常见编译报错解决方案指引,支持在原基础上快速二次开发或功能拓展,是理解Android四大组件、SQLite本地存储与Material Design实践的优质入门范例。
1. 为什么一个账本APP能成为Android期末大作业的“通关密钥”?
很多同学拿到“安卓移动开发课程设计”任务时,第一反应是:做点炫酷的动画?接个天气API?或者硬啃一个电商首页?结果代码写到一半卡在Activity跳转传参、RecyclerView列表刷新异常、或者SharedPreferences存取乱码上,最后交了个半成品。但真实教学场景中,账本APP恰恰是最能覆盖Android核心知识链的最小可行项目——它天然串联起UI控件(EditText/DatePicker/RecyclerView)、数据持久化(Room/SQLite/SharedPreferences)、生命周期管理(onPause/onResume处理未保存草稿)、权限控制(存储读写)、以及Gradle构建全流程。更重要的是,它不依赖后端服务,所有逻辑可本地闭环验证;同时又具备真实业务扩展性,比如后续加图表统计、导出Excel、多账户切换等。本文不讲空泛理论,只聚焦你打开Android Studio后从新建项目到生成APK包的每一步实操细节,包括build.gradle里必须改的3个关键配置、gradlew命令如何绕过常见编译失败、以及文档说明里最容易被忽略的「运行环境声明」该怎么写才让老师一眼认可专业度。
2. 用Android Studio 2023+创建账本APP工程:从空项目到可运行界面
2.1 创建新项目时的关键选项选择与避坑指南
新建项目时,模板选择直接影响后续开发效率。不要选“Empty Activity”——它默认不带Material Design组件支持,后期要手动添加依赖;也不要选“Basic Activity”——它自动生成的AppBar和Navigation Drawer对账本类应用属于冗余结构。正确做法是选择“Empty Activity” + 手动启用Material主题,并在app/src/main/res/values/themes.xml中确认以下配置:
<!-- app/src/main/res/values/themes.xml --> <style name="Theme.AccountBook" parent="Theme.Material3.DayNight"> <item name="colorPrimary">@color/md_theme_light_primary</item> <item name="colorOnPrimary">@color/md_theme_light_onPrimary</item> <!-- 必须保留此行,否则FloatingActionButton无法显示 --> <item name="floatingActionButtonTint">@color/md_theme_light_primary</item> </style>提示:Android Studio 2023.2.1(Iguana)起,默认使用Material 3主题。若发现FloatingActionButton点击无反馈,大概率是
themes.xml中缺失floatingActionButtonTint属性。该属性控制按钮着色,不设置会导致按钮不可见或交互失效。
2.2 构建脚本配置:build.gradle (Module: app) 的4处必改参数
Gradle配置是编译失败的高发区。以下4处参数必须按Android 12+(API 31)及以上目标版本要求调整,否则gradlew build会报错tag number over 30 is not supported(常见于使用旧版AGP插件时):
// app/build.gradle android { namespace 'com.example.accountbook' // 必须与包名完全一致,区分大小写 compileSdk 34 // 推荐设为最新稳定版,避免兼容性警告 defaultConfig { applicationId "com.example.accountbook" minSdk 21 // 账本APP无需支持Android 4.1以下,设21可减少60%以上兼容代码 targetSdk 34 // 必须与compileSdk一致,否则Android Studio 2023+强制报错 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false // 学期作业禁用混淆,避免调试困难 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') } } // 必须添加此段,否则RecyclerView无法识别Material组件 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }2.2.1namespace与applicationId的区别与同步逻辑
namespace:仅用于R类生成和资源引用,影响R.layout.activity_main等调用;applicationId:真正决定APK安装包唯一标识,影响Google Play发布和Intent隐式启动;- 二者必须完全一致,否则
findViewById(R.id.xxx)会返回null,且Logcat中无明确错误提示,仅表现为UI控件空白。
2.2.2minSdk 21的实际影响与测试验证方法
设minSdk 21意味着放弃Android 4.4(KitKat)及更早系统。验证是否生效:
- 在模拟器中创建AVD时,选择Android 5.0 (Lollipop) API 21;
- 运行APP,观察Logcat中是否出现
E/AndroidRuntime: FATAL EXCEPTION: main开头的NoSuchMethodError; - 若无报错且界面正常渲染,则证明低版本兼容逻辑已剔除。
3. 核心功能实现:用Room数据库替代SQLiteOpenHelper完成收支记录管理
3.1 定义实体类与DAO接口:账本数据模型的最小完备结构
账本APP的核心是“一笔记录”,需包含时间、金额、类型(收入/支出)、分类、备注。Room要求实体类必须有主键,且推荐使用@PrimaryKey(autoGenerate = true)而非long id手动赋值:
// app/src/main/java/com/example/accountbook/data/Transaction.java @Entity(tableName = "transactions") public class Transaction { @PrimaryKey(autoGenerate = true) public long id; @ColumnInfo(name = "amount") public double amount; // 金额用double,避免float精度丢失 @ColumnInfo(name = "type") public String type; // "income" or "expense" @ColumnInfo(name = "category") public String category; // "salary", "food", "transport"... @ColumnInfo(name = "note") public String note; @ColumnInfo(name = "timestamp") public long timestamp; // 毫秒级时间戳,便于排序和范围查询 }注意:
@ColumnInfo注解中的name值必须小写且无下划线(如"amount"),否则Room生成的SQL语句会因字段名大小写敏感导致table transactions has no column named AMOUNT错误。
3.2 DAO接口编写:3个必须实现的方法及其SQL含义
DAO(Data Access Object)是Room的数据操作入口。以下3个方法覆盖账本APP90%操作场景:
// app/src/main/java/com/example/accountbook/data/TransactionDao.java @Dao public interface TransactionDao { // 插入单条记录,返回插入后的id(autoGenerate时有效) @Insert(onConflict = OnConflictStrategy.REPLACE) long insert(Transaction transaction); // 查询全部记录,按时间倒序排列(最新在前) @Query("SELECT * FROM transactions ORDER BY timestamp DESC") List<Transaction> getAll(); // 按时间范围查询,参数用:startDate/:endDate占位符,避免SQL注入 @Query("SELECT * FROM transactions WHERE timestamp BETWEEN :startDate AND :endDate ORDER BY timestamp DESC") List<Transaction> getInRange(long startDate, long endDate); }3.2.1OnConflictStrategy.REPLACE在账本场景下的实际作用
当用户修改某笔记录并重新保存时,若直接insert()会生成新id,导致重复数据。REPLACE策略会在主键冲突时先删除原记录再插入新记录,本质是“更新”行为。这比手写@Update方法更简洁,且避免了UPDATE ... WHERE id = ?可能遗漏的条件判断。
3.2.2 时间范围查询的毫秒级精度陷阱
System.currentTimeMillis()返回毫秒值,但DatePicker获取的日期默认是当天0点。若用户选择“2024-05-01”,需转换为:
Calendar cal = Calendar.getInstance(); cal.set(year, month, day, 0, 0, 0); long startMillis = cal.getTimeInMillis(); cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 59); cal.set(Calendar.SECOND, 59); long endMillis = cal.getTimeInMillis();否则BETWEEN查询会漏掉当天所有记录。
4. 构建与调试:用gradlew命令精准控制APK生成与安装流程
4.1 本地构建APK的最小命令链与各环节输出验证
在项目根目录执行以下命令,每步都需验证输出结果,避免静默失败:
# 步骤1:清理旧构建产物(关键!避免缓存导致的class not found) ./gradlew clean # 步骤2:编译并生成debug APK(注意是assembleDebug,不是build) ./gradlew assembleDebug # 步骤3:验证APK是否生成成功(检查文件大小和签名) ls -lh app/build/outputs/apk/debug/app-debug.apk # 正常输出应类似:-rw-r--r-- 1 user staff 3.2M May 10 14:22 app-debug.apk # 步骤4:安装到已连接设备(需提前开启USB调试) adb install -r app/build/outputs/apk/debug/app-debug.apk # 成功时返回:Success提示:
./gradlew build会执行test任务,而期末作业通常未写单元测试,导致build命令卡在testDebugUnitTest阶段。务必用assembleDebug替代build,这是学生最常踩的坑。
4.2 常见gradlew失败场景与对应修复方案
| 错误现象 | 根本原因 | 修复命令 |
|---|---|---|
Could not find method android() for arguments [...] | 项目根目录build.gradle中缺少plugins { id 'com.android.application' } | 在build.gradle顶部添加plugins { id 'com.android.application' version '8.2.2' apply false } |
Failed to notify project evaluation listener | gradle/wrapper/gradle-wrapper.properties中distributionUrl版本与Android Studio不匹配 | 将distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip改为与AS版本匹配的Gradle版本(AS 2023.2.1对应Gradle 8.2) |
Execution failed for task ':app:processDebugResources' | res/values/strings.xml中存在未闭合标签或非法字符 | 用VS Code打开strings.xml,检查所有<string>标签是否成对出现,且内容不含&、<等未转义字符 |
4.2.1gradlew与Android Studio GUI构建的本质区别
- Android Studio点击“Run”按钮时,实际调用的是
./gradlew installDebug,它内部包含assembleDebug+install两步; - 而
./gradlew assembleDebug仅生成APK,不安装,适合批量打包多个版本; - 期末作业提交源码时,必须确保
app/build/outputs/目录为空,否则Git会误提交二进制文件,导致仓库臃肿且老师无法直接编译。
5. 文档说明撰写要点:让老师30秒内确认你的技术完整性
5.1 运行环境声明表:必须包含的4项硬性参数
文档中“运行环境”章节不能只写“Android手机”,需精确到API级别和硬件特征。以下表格是评审时的扣分/加分项:
| 环境类型 | 具体参数 | 说明 |
|---|---|---|
| 操作系统 | Android 5.0 (API 21) 至 Android 14 (API 34) | 明确标注最低和最高支持版本,体现兼容性意识 |
| 开发工具 | Android Studio 2023.2.1 (Iguana) | 版本号必须与你实际使用的IDE一致,避免“用2022版写2023版文档”的穿帮 |
| 构建工具 | Gradle 8.2, AGP 8.2.2 | gradle/wrapper/gradle-wrapper.properties和build.gradle中声明的版本需完全匹配 |
| 测试设备 | Pixel 4a (Android 13), Samsung Galaxy A52 (Android 12) | 列出2台真实机型,证明跨厂商适配能力 |
5.2 源码结构说明:用树状图呈现模块划分逻辑
文档中需用纯文本树状图展示app/src/main/目录结构,重点突出三层职责分离:
app/src/main/ ├── java/ │ └── com/example/accountbook/ │ ├── AccountBookApplication.java # Application子类,初始化全局配置 │ ├── MainActivity.java # 主界面,含FloatingActionButton触发添加 │ └── data/ # 数据层(Room相关) │ ├── Transaction.java # 实体类 │ ├── TransactionDao.java # 数据访问接口 │ └── AccountBookDatabase.java # Database抽象类 ├── res/ │ ├── layout/ │ │ ├── activity_main.xml # 主界面布局(RecyclerView+Fab) │ │ └── item_transaction.xml # 列表单项布局(含金额、类型、时间) │ └── values/ │ └── strings.xml # 所有字符串常量,禁止硬编码 └── AndroidManifest.xml # 声明WRITE_EXTERNAL_STORAGE权限(若需导出CSV)注意:
AndroidManifest.xml中若用到存储权限,必须在<application>外添加:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
android:maxSdkVersion="28"表示仅在Android 9及以下需要该权限,Android 10+使用分区存储,此声明可避免高版本系统弹窗警告。
5.3 功能验证清单:用可执行步骤代替功能描述
文档末尾需提供“教师快速验证表”,每项对应一条可立即执行的操作指令:
| 验证项 | 操作步骤 | 预期结果 |
|---|---|---|
| 新增记录 | 点击右下角FloatingActionButton → 输入金额“1000”、类型“income”、分类“salary” → 点击保存 | 主界面RecyclerView第一条显示“+¥1000.00 · salary · 今天” |
| 数据持久化 | 新增记录后退出APP → 重新打开APP | 记录仍存在于列表中,证明Room写入成功 |
| 时间排序 | 连续新增3笔记录(间隔1分钟) → 观察列表顺序 | 最新记录始终在顶部,验证ORDER BY timestamp DESC生效 |
| APK安装 | 将app-debug.apk发送至Android手机 → 点击安装 | 安装完成后桌面出现“账本”图标,点击可正常启动 |
最后一行不总结,而是给出一个具体技巧:
在MainActivity.java的onCreate()方法末尾添加一行日志,用于快速确认APK签名一致性:
Log.d("AccountBook", "Build time: " + BuildConfig.BUILD_TIME);该字段由Gradle在构建时自动注入,若老师用不同环境重编译你的代码,BUILD_TIME值会变化,从而直观验证你提交的确实是原始可构建源码。
本文还有配套的精品资源,点击获取