Android毕设简易App实战:导航、设置与真机兼容方案 简介本资源是一份面向Android开发初学者的实战入门指南聚焦使用Android Studio 4.x及Java语言构建基础功能App适用于高校移动应用开发课程实践、自学入门者快速上手和求职前项目练手。文档以图文结合方式详解三页面简易App的完整开发流程从新建Empty Activity项目、配置最低SDKAndroid 4.0、创建MainActivity/AboutActivity/SettingsActivity三大核心Activity到编写onCreate方法加载布局、注册Activity至AndroidManifest.xml再到设置页面集成PreferenceFragmentCompat实现偏好管理。资源为单文件PDF格式共1个498KB的便携式技术文档内容精炼、代码可直接参考含关键类结构、XML布局调用逻辑与Intent跳转提示。目前已有447人学习下载适合零基础读者按步骤复现项目结构、理解Android四大组件基础协作关系并建立标准工程目录认知。1. 这不是“Hello World”一个能过答辩、能装进真机、能被导师点开就看懂的 Android 毕设级简易 App 方案你手头那份标着“androidstudio简易app实例.pdf”的文档大概率是某位学长导出的笔记截图或是某次课设压缩包里没删干净的 PDF。它列了 11 步但没告诉你为什么选 Empty Activity 而不是 BottomNavigationView Activity为什么最低版本敢设到 Android 4.0API 14——这在 2024 年连模拟器都懒得启动更关键的是它把onCreate()代码贴出来就收工却没说明R.layout.activity_main这个资源 ID 是怎么生成的、XML 布局里缺了tools:context会导致预览器一片红、AndroidManifest.xml里category android:nameandroid.intent.category.INFO/实际上根本不会出现在系统设置页——这些不是细节是答辩时被问住的起点。这份方案就是为解决这类「看着会、一做就卡、一跑就崩、一讲就虚」的真实毕设/课设场景而写的。它不教你怎么点菜单而是带你亲手搭起一个有导航逻辑、有状态保存、有可扩展结构、能通过 Gradle 构建、能在 Android 8.0 到 14.0 真机上稳定运行的最小可行 App。适合正在赶 Android 课程设计 deadline 的同学也适合需要快速交付一个演示原型的初级工程师——它不炫技但每一步都经得起追问。2. 总体架构设计三层结构与四个核心模块的职责划分这个简易 App 表面只有三个页面但若按工程化思路组织必须明确分层边界。我通常采用「Activity 层 Fragment 层 Resource 层」三层结构避免所有逻辑堆在MainActivity里变成黑匣子。四个核心模块分别是启动入口模块Launcher、主功能容器模块Home Container、信息展示模块About、偏好配置模块Settings。它们之间不直接耦合全部通过 Intent 显式跳转且每个模块只负责自己范围内的 UI 渲染与轻量交互。2.1 启动入口模块从AndroidManifest.xml开始的第一次校验很多同学在AndroidManifest.xml里随手写action android:name.MainActivity /结果发现图标不显示、应用打不开。根本原因是Launcher Activity 的 intent-filter 必须同时满足 action 为ACTION_MAIN、category 为CATEGORY_LAUNCHER且 action 名称不能自定义。正确写法如下activity android:name.MainActivity android:exportedtrue android:labelstring/app_name intent-filter action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.LAUNCHER / /intent-filter /activity提示android:exportedtrue是 Android 12API 31强制要求漏写会导致安装失败。若目标 SDK ≥ 31所有含 intent-filter 的 Activity 都必须显式声明 exported 属性。2.2 主功能容器模块用ConstraintLayout承载可复用的导航按钮组主页面不是空白画布而是导航中枢。我坚持用ConstraintLayout而非LinearLayout或RelativeLayout作为根布局原因很实际它支持链式约束能让「关于」「设置」两个按钮在不同屏幕尺寸下保持等宽居中且 XML 结构扁平无嵌套。activity_main.xml关键片段如下?xml version1.0 encodingutf-8? androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:apphttp://schemas.android.com/apk/res-auto xmlns:toolshttp://schemas.android.com/tools android:layout_widthmatch_parent android:layout_heightmatch_parent tools:context.MainActivity Button android:idid/btn_about android:layout_width0dp android:layout_heightwrap_content android:layout_marginStart32dp android:layout_marginEnd16dp android:textstring/title_about app:layout_constraintBottom_toBottomOfparent app:layout_constraintEnd_toStartOfid/btn_settings app:layout_constraintHorizontal_bias0.5 app:layout_constraintStart_toStartOfparent app:layout_constraintTop_toTopOfparent app:layout_constraintVertical_bias0.4 / Button android:idid/btn_settings android:layout_width0dp android:layout_heightwrap_content android:layout_marginStart16dp android:layout_marginEnd32dp android:textstring/title_settings app:layout_constraintBottom_toBottomOfparent app:layout_constraintEnd_toEndOfparent app:layout_constraintHorizontal_bias0.5 app:layout_constraintStart_toEndOfid/btn_about app:layout_constraintTop_toTopOfparent app:layout_constraintVertical_bias0.4 / /androidx.constraintlayout.widget.ConstraintLayout注意app:layout_constraintVertical_bias0.4—— 这比硬写android:layout_marginTop200dp更健壮它让按钮始终位于屏幕垂直方向 40% 处适配全面屏和折叠屏。2.3 信息展示模块AboutActivity的静态内容封装与版本自动注入AboutActivity不该只是展示固定文字。我习惯在strings.xml中定义占位符并在onCreate()中动态注入当前 App 版本号让信息具备可信度!-- res/values/strings.xml -- string nameabout_version版本%1$s/string string nameabout_copyright© %1$d %2$s/string// AboutActivity.java Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_about); TextView versionText findViewById(R.id.text_version); TextView copyrightText findViewById(R.id.text_copyright); try { PackageInfo pInfo getPackageManager().getPackageInfo(getPackageName(), 0); String versionName pInfo.versionName; int versionCode pInfo.versionCode; int currentYear Calendar.getInstance().get(Calendar.YEAR); String appName getString(R.string.app_name); versionText.setText(getString(R.string.about_version, versionName)); copyrightText.setText(getString(R.string.about_copyright, currentYear, appName)); } catch (PackageManager.NameNotFoundException e) { versionText.setText(版本未知); copyrightText.setText(© 2024 应用); } }这样哪怕你改了build.gradle里的versionNameAbout 页面也会自动同步不用每次手动改字符串。2.4 偏好配置模块PreferenceFragmentCompat的现代用法与兼容性兜底SettingsActivity是最容易翻车的模块。原文档里混用了PreferenceFragment和PreferenceFragmentCompat而后者才是 AndroidX 推荐的兼容方案。关键在于SettingsFragment必须继承PreferenceFragmentCompat且SettingsActivity的布局必须包含一个FrameLayout容器用于动态加载 Fragment!-- activity_settings.xml -- FrameLayout xmlns:androidhttp://schemas.android.com/apk/res/android android:idid/settings_container android:layout_widthmatch_parent android:layout_heightmatch_parent /// SettingsFragment.java public class SettingsFragment extends PreferenceFragmentCompat { Override public void onCreate(Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注意setPreferencesFromResource 的第一个参数是 R.xml.xxx不是 R.layout.xxx setPreferencesFromResource(R.xml.preferences, null); } }R.xml.preferences是一个标准 preference XML 文件定义了 ListPreference、SwitchPreferenceCompat 等控件。这种分离方式让设置逻辑完全脱离 Activity便于单元测试和未来迁移到 Jetpack Compose。3. 核心功能实现从按钮跳转到偏好持久化的完整链路光有页面骨架不够用户点击「关于」后得真跳过去改了主题色得下次打开还在。这一章把「导航」和「数据保存」两条主线串起来给出可直接复制粘贴的代码并解释每一行为什么这么写。3.1 导航跳转Intent显式调用的三要素与防错处理MainActivity中按钮的onClick方法不能只写startActivity(new Intent(this, AboutActivity.class))。必须补全三要素Context、目标 Class、异常捕获。否则在某些定制 ROM 上可能因 Activity 未注册而崩溃public void onAboutButtonClick(View view) { Intent intent new Intent(MainActivity.this, AboutActivity.class); // 添加 FLAG_ACTIVITY_CLEAR_TOP 防止多次点击产生多个 AboutActivity 实例 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 启动前校验目标 Activity 是否存在防御性编程 if (intent.resolveActivity(getPackageManager()) ! null) { startActivity(intent); } else { Toast.makeText(this, 关于页面暂不可用, Toast.LENGTH_SHORT).show(); } }注意FLAG_ACTIVITY_CLEAR_TOP是血泪经验。曾有个学生做毕设用户狂点「关于」按钮退出时按返回键要连按 5 次才能回到桌面——就是因为没清栈。3.2 偏好数据读写SharedPreferences的线程安全封装与实时监听设置页面的开关、列表选择项最终都要存到SharedPreferences。但直接用getSharedPreferences().edit().putString().apply()容易出错apply()是异步的若紧接着读取可能拿到旧值commit()又阻塞主线程。我的做法是封装一个工具类PrefUtils统一管理// PrefUtils.java public class PrefUtils { private static final String PREF_NAME app_settings; private static SharedPreferences sPrefs; public static void init(Context context) { sPrefs context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); } public static void putString(String key, String value) { sPrefs.edit().putString(key, value).apply(); // apply() 在这里安全因无后续立即读取 } public static String getString(String key, String defValue) { return sPrefs.getString(key, defValue); } // 提供监听器当设置变更时自动回调如主题切换需刷新 UI public static void registerOnSharedPreferenceChangeListener( SharedPreferences.OnSharedPreferenceChangeListener listener) { sPrefs.registerOnSharedPreferenceChangeListener(listener); } }在SettingsFragment的onCreate()中初始化监听Override public void onCreate(Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setPreferencesFromResource(R.xml.preferences, null); // 监听主题设置变化 findPreference(theme_preference).setOnPreferenceChangeListener( (preference, newValue) - { // 这里可触发 UI 重绘或发广播通知 MainActivity requireActivity().recreate(); // 简单粗暴适合毕设 return true; }); }3.3 字符串资源与多语言支持strings.xml的结构化组织技巧别把所有字符串塞进一个strings.xml。我按模块拆分为strings.xml默认中文strings-en.xml英文用于国际化演示arrays.xml存放 ListPreference 的 entries/entryValues例如arrays.xml?xml version1.0 encodingutf-8? resources string-array namefont_size_entries item小/item item中/item item大/item /string-array string-array namefont_size_values item12/item item16/item item20/item /string-array /resources然后在preferences.xml中引用ListPreference android:keyfont_size_preference android:title字体大小 android:entriesarray/font_size_entries android:entryValuesarray/font_size_values android:defaultValue16 /这样即使不做多语言结构也清晰导师一眼看出你懂资源管理。3.4 构建配置build.gradleModule: app的关键参数设定Gradle 配置决定项目能否编译通过、能否在新设备运行。以下是毕设级最简但完备的配置基于 Android Studio Giraffe 2022.3.1 AGP 8.1.0android { namespace com.example.simpleapp compileSdk 34 defaultConfig { applicationId com.example.simpleapp minSdk 19 // 改为 19放弃 Android 4.0API 14兼容性与开发效率平衡点 targetSdk 34 versionCode 1 versionName 1.0 testInstrumentationRunner androidx.test.runner.AndroidJUnitRunner } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { implementation androidx.appcompat:appcompat:1.6.1 implementation com.google.android.material:material:1.10.0 implementation androidx.constraintlayout:constraintlayout:2.1.4 implementation androidx.preference:preference:1.2.1 implementation androidx.fragment:fragment:1.6.2 }提示minSdk 19Android 4.4是当前最低合理值。API 14 已淘汰近十年连 Google Play Console 都不再接受 API 19 的新应用上传。4. 常见问题排查毕设中最容易踩的 4 个坑及现场急救方案这些问题我在带三个不同高校的 Android 课设时反复遇到学生常卡在最后一步调试两小时找不到原因。以下按「现象 → 原因 → 解决」给出可立即执行的方案。4.1 现象App 安装后桌面无图标点击 Run 按钮报错Installation did not succeed原因AndroidManifest.xml中 Launcher Activity 缺少android:exportedtrueAndroid 12 强制要求或intent-filter写错如 action 名称不是android.intent.action.MAIN。解决检查AndroidManifest.xml中 Launcher Activity 的intent-filter是否严格匹配action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.LAUNCHER /确认该 Activity 声明了android:exportedtrue清理项目Build → Clean Project再Build → Rebuild Project卸载设备上残留的同包名旧版本adb uninstall com.example.simpleapp。4.2 现象点击「关于」按钮后黑屏或闪退Logcat 报ActivityNotFoundException原因AboutActivity未在AndroidManifest.xml中声明或声明的android:name与 Java 类名不一致如大小写错误、缺少包名前缀。解决打开AndroidManifest.xml确认存在activity android:name.AboutActivity android:exportedfalse /检查AboutActivity.java的包声明是否为package com.example.simpleapp;与applicationId一致在MainActivity的onAboutButtonClick中用Log.d(DEBUG, AboutActivity class: AboutActivity.class.getName());打印类名确认路径正确。4.3 现象设置页面打开后空白Logcat 显示No view found for id ...原因SettingsActivity的布局文件activity_settings.xml中没有 ID 为settings_container的容器或SettingsFragment的setPreferencesFromResource()加载了错误的 XML如误用R.layout.xxx而非R.xml.xxx。解决检查activity_settings.xml是否包含FrameLayout android:idid/settings_container ... /检查SettingsFragment.java中setPreferencesFromResource(R.xml.preferences, null)的第一个参数是否为R.xml.xxxXML 文件必须放在res/xml/目录下确认res/xml/preferences.xml文件存在且格式正确根节点为PreferenceScreen。4.4 现象修改设置后重启 App选项恢复默认值原因SharedPreferences的 key 写错如putString(theme, ...)但读取时用getString(theme_preference, ...)或ListPreference的defaultValue未在 XML 中设置。解决统一检查所有Preference的android:key属性确保与PrefUtils.putString()中的 key 完全一致在preferences.xml中为每个 Preference 设置android:defaultValue例如SwitchPreferenceCompat android:keydark_mode android:title深色模式 android:defaultValuefalse /使用 Device File Explorer 查看/data/data/com.example.simpleapp/shared_prefs/app_settings.xml确认值已写入。5. 答辩与验收用一份「可演示、可讲解、可验证」的交付物打动导师答辩不是背诵步骤而是证明你真正掌控了这个 App。我建议准备三样东西一个 3 分钟演示视频、一份精简版技术说明文档PDF、以及一个「答辩问答速查表」。下面说具体怎么做。5.1 演示视频脚本聚焦「用户旅程」而非「开发过程」不要录「我点 File → New Project → …」导师不关心你点了几下菜单。要录真实用户会做的操作开场0:00–0:20解锁手机找到 App 图标点击启动主流程0:20–1:50点击「关于」→ 展示版本号与版权信息 → 返回 → 点击「设置」→ 切换「深色模式」开关 → 点击「字体大小」→ 选择「大」→ 返回主页面观察按钮文字变大若做了适配压轴1:50–3:00卸载 App → 重新安装 → 打开设置验证「深色模式」和「字体大小」仍为上次选择的值证明SharedPreferences持久化生效。视频用手机录屏即可导出为 MP4命名simpleapp_demo_2024.mp4。答辩时直接播放比你口头描述十遍都管用。5.2 技术说明文档一页纸讲清架构与关键决策这份 PDF 就是你交作业的「说明书」控制在一页 A4 内。我用 Markdown 写好用 Typora 导出 PDF。结构如下项目说明架构图文字描述「Activity 层MainActivity/AboutActivity/SettingsActivity仅负责页面跳转与生命周期Fragment 层SettingsFragment承载设置逻辑Resource 层strings.xml / xml/preferences.xml管理文本与配置」技术选型理由「选用 Java 而非 Kotlin课程要求统一语言选用PreferenceFragmentCompat兼容 Android 5.0避免PreferenceActivity过时minSdk19放弃 Android 4.x提升开发效率与安全性」核心功能验证点「1. 三个页面可通过按钮正常跳转2. 设置项修改后重启 App 仍保留3. 在 Android 8.0API 26、11API 30、14API 34真机上均能安装并运行」文件清单「共 12 个关键文件MainActivity.java,AboutActivity.java,SettingsActivity.java,SettingsFragment.java,activity_main.xml,activity_about.xml,activity_settings.xml,preferences.xml,strings.xml,arrays.xml,AndroidManifest.xml,build.gradleModule: app」5.3 答辩问答速查表预判导师最可能问的 5 个问题把这些问题写在一张便签纸上答辩前默读三遍Q为什么不用 Navigation ComponentANavigation Component 适合复杂单 Activity 架构本项目为典型多 Activity 模式用 Intent 显式跳转更直观符合课程教学目标。QSharedPreferences存敏感数据安全吗A本项目仅存储 UI 偏好字体、主题不涉及密码、Token 等敏感信息。若需存敏感数据应使用EncryptedSharedPreferencesAndroidX Security 库。Q如何扩展「关于」页面加入开发者邮箱A在strings.xml新增string nameabout_emaildevsimpleapp.com/string在activity_about.xml中加TextView并在AboutActivity.java的onCreate()中findViewById().setText(getString(R.string.about_email))。Q如果想加「退出」按钮怎么实现A在MainActivity布局中加 ButtononClick方法内调用finishAffinity()关闭所有 ActivitySystem.exit(0)彻底退出进程但需提醒用户Android 不鼓励强制退出更推荐按返回键自然退出。Q这个 App 能发布到应用商店吗A可以但需补充应用图标mipmap、隐私政策链接在About页面添加、签名 APKBuild → Generate Signed Bundle/APK以及 Google Play 要求的targetSdk≥ 33当前为 34已满足。从那以后我每次带学生做 Android 课设都会强制他们在git commit前先跑一遍「演示视频脚本」里的三步操作启动 → 设置 → 重启验证。只要这三步通答辩基本稳了。希望帮到你。本文还有配套的精品资源点击获取