ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

移动应用开发实验报告背后的真实工程能力:从Activity到Intent的完整链路

移动应用开发实验报告背后的真实工程能力:从Activity到Intent的完整链路 简介这份实验报告面向软件学院修读移动应用软件开发技术课程的学生聚焦Android平台开发入门帮助读者完成从环境搭建到界面设计的完整实验流程。资源包内含1个doc文档约1.63MB以文字与截图结合的形式记录实验过程便于对照操作与整理成册。报告围绕三大实验模块展开一是Android系统环境搭建涵盖JDK安装与JAVA_HOME环境变量配置、Eclipse解压使用、Android SDK在线更新与离线安装、ADT插件安装等关键步骤二是Activity运用实验涉及Activity的创建、启动与生命周期管理以及Intent跳转与数据传递三是Android应用UI设计包括TextView、Button、ImageView等基础控件LinearLayout、RelativeLayout、GridLayout等布局管理器以及自定义View与XML布局文件设计。目前已有766人学习下载适合需要提交实验报告或系统梳理Android开发基础流程的初学者参考可帮助读者理解开发工具链配置与界面构建思路为后续独立开发简单应用打下基础。1. 移动应用开发实验报告背后的真实工程能力从 Activity 到 Intent 的完整链路很多人以为「软件学院移动应用软件开发技术实验报告」只是交一份带截图的 Word 文档把 Android Studio 里跑出来的 Hello World 贴上去就完事。但真正做过企业级 Android 项目的人都知道一份能打的实验报告背后考察的是你对 Activity 生命周期、Intent 传参、UI 布局层级、SDK 版本兼容这四件事的掌控程度。我带过几届学生的课程设计也审过不少校招简历发现一个反直觉的结论实验报告写得漂亮的人往往在真实项目里连一个content://分享都调不通而能把实验报告里的每个参数讲清楚的人上手 Flutter 跳转原生 Activity、处理abort background activity starts from这类报错时几乎不需要查文档。这篇笔记就按一线开发的路径把移动应用开发实验从环境搭建、Activity 与 Intent 实战、UI 布局与卡顿排查、SDK 版本管理到实验报告的技术表达完整拆一遍。适合正在做课程实验的软件学院学生也适合想从「能跑就行」进阶到「知道为什么能跑」的 Android 初学者。2. 实验环境搭建Android Studio 安装、SDK 配置与项目移植2.1 Android Studio 下载安装与中文环境设置实验第一步永远是环境。Android Studio 的安装本身不复杂但版本选择和 SDK 组件勾选直接决定后面会不会翻车。我一般建议用当前稳定版不要追 Canary 通道因为课程实验用的第三方库往往还没适配最新 API。安装时重点看三个组件组件作用是否必选Android SDK Platform编译目标 API 的核心库必选Android SDK Build-Tools打包和资源编译工具必选Android SDK Platform-Toolsadb、fastboot 等调试工具必选Android Emulator模拟器运行环境建议选安装完成后很多人第一反应是「android studio怎么设置中文」。这里说清楚Android Studio 本身没有官方中文语言包社区有第三方汉化插件但我不建议在实验环境里装。原因有两个一是汉化插件版本滞后会导致菜单错位二是实验报告里如果出现中文菜单截图答辩时老师问「这个选项在英文版对应哪个」你会卡住。保持英文界面用两三天就习惯了。SDK 路径配置在Settings → Languages Frameworks → Android SDK。如果你遇到「android sdk离线包下载」的需求通常是因为校园网限制。离线包的做法是下载对应版本的platform-XX.zip和build-tools-XX.zip解压到 SDK 目录下的platforms/和build-tools/文件夹然后在 SDK Manager 里勾选「Show Package Details」手动指定路径。注意SDK 路径中不要包含中文和空格否则 Gradle 同步时会报Could not find method之类的玄学错误。2.2 移植 Android Studio 项目的四个关键检查点「移植android studio项目」是实验里高频出现的需求比如从学长那里拿到一份往届代码或者从 GitHub 克隆一个 demo。直接File → Open打开后大概率一片红按下面顺序排查第一步检查build.gradle里的 Gradle 插件版本和gradle-wrapper.properties里的 distributionUrl 是否匹配。常见做法是把 wrapper 版本改成你本地能下载的版本比如// gradle/wrapper/gradle-wrapper.properties distributionUrlhttps\://services.gradle.org/distributions/gradle-8.0-bin.zip第二步检查compileSdk和targetSdk。如果项目写的是 33 而你本地只装了 31要么改低要么去 SDK Manager 补装。第三步检查local.properties里的sdk.dir。这个文件通常不会随项目提交需要手动创建# local.properties sdk.dir/Users/yourname/Library/Android/sdk第四步检查依赖仓库。老项目可能用的是jcenter()而 jcenter 已经停止服务需要替换成mavenCentral()或google()。// build.gradle (Project级) repositories { google() mavenCentral() // jcenter() 已废弃删掉 }这四步走完90% 的移植项目能正常同步。剩下 10% 通常是签名配置或 NDK 版本问题实验阶段可以先注释掉signingConfigs块。2.3 SDK 版本选择与 targetSdk 的取舍「android sdk」的版本选择是实验报告里必须写清楚的一个参数。很多同学随便选一个 API 33 就开跑结果在旧模拟器上装不上。我的建议是compileSdk用你本地装的最新稳定版它只影响编译期。minSdk根据实验要求定课程实验一般设 24Android 7.0就够覆盖率高且不用处理太多兼容代码。targetSdk设成和 compileSdk 一致但要注意 Android 12 以上对android:exported的强制要求。!-- AndroidManifest.xml -- activity android:name.MainActivity android:exportedtrue !-- targetSdk 31 必须显式声明 -- intent-filter action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.LAUNCHER / /intent-filter /activityandroid:exported这个属性在 targetSdk 31 之后变成必填不写直接编译失败。现象是Manifest merger failed原因就是系统要求每个带 intent-filter 的组件明确是否对外暴露。解决方式就是加上android:exportedtrue主 Activity或false内部组件。3. Activity 与 Intent 实战从生命周期到跨应用跳转3.1 Activity 生命周期在实验中的可观测验证「Android Activity」是移动应用开发实验的核心考点。生命周期方法不是背出来的是打 Log 看出来的。在实验报告里我建议你做一个最简单的双 Activity 应用在每个生命周期回调里打 Logpublic class MainActivity extends AppCompatActivity { private static final String TAG MainActivityLifecycle; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, onCreate: 界面初始化); } Override protected void onStart() { super.onStart(); Log.d(TAG, onStart: 界面可见但不可交互); } Override protected void onResume() { super.onResume(); Log.d(TAG, onResume: 界面可交互); } Override protected void onPause() { super.onPause(); Log.d(TAG, onPause: 失去焦点); } Override protected void onStop() { super.onStop(); Log.d(TAG, onStop: 完全不可见); } Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, onDestroy: 销毁); } }这段代码的逻辑说明每个回调对应 Activity 的一个状态阶段。onCreate做初始化onStart表示可见onResume表示可交互onPause是失去焦点但还可见onStop是完全不可见onDestroy是销毁。参数方面savedInstanceState用于恢复状态实验里可以故意旋转屏幕观察onSaveInstanceState的调用时机。跑起来后按 Home 键、返回键、旋转屏幕观察 Logcat 输出顺序。这个实验做一遍比背十遍生命周期图都管用。3.2 Intent 显式跳转与数据传递的完整写法「Intent」是 Activity 之间通信的桥梁。实验报告里最常见的需求是Activity A 跳转到 Activity B并传递一个字符串和一个整数。// MainActivity 中发起跳转 Intent intent new Intent(MainActivity.this, DetailActivity.class); intent.putExtra(user_name, 张三); intent.putExtra(user_age, 20); startActivity(intent);// DetailActivity 中接收数据 Intent intent getIntent(); String name intent.getStringExtra(user_name); int age intent.getIntExtra(user_age, 0); // 第二个参数是默认值 TextView tv findViewById(R.id.tv_detail); tv.setText(姓名 name 年龄 age);逻辑说明putExtra的键值对通过 Intent 携带getStringExtra和getIntExtra按类型取出。注意getIntExtra必须给默认值否则数据缺失时会返回 0 而不是报错容易埋坑。参数方面Intent 传递的数据类型有限制基本类型和 String 没问题自定义对象需要实现Serializable或Parcelable。实验里如果传对象建议用Parcelable性能更好但代码量大可以用 Android Studio 的 Parcelable 插件自动生成。3.3 隐式 Intent 与跨应用跳转的边界隐式 Intent 不指定具体类名而是声明一个 action让系统去找能响应的应用。实验里常见的场景是打开浏览器、拨打电话、分享文本。// 打开网页 Intent browserIntent new Intent(Intent.ACTION_VIEW, Uri.parse(https://www.example.com)); startActivity(browserIntent); // 分享文本 Intent shareIntent new Intent(Intent.ACTION_SEND); shareIntent.setType(text/plain); shareIntent.putExtra(Intent.EXTRA_TEXT, 这是分享内容); startActivity(Intent.createChooser(shareIntent, 选择分享应用));逻辑说明ACTION_VIEW配合Uri打开网页ACTION_SEND配合createChooser弹出分享面板。参数方面setType必须设置否则系统不知道用什么应用处理。这里会遇到一个高频报错android.content.ActivityNotFoundException。现象是点击按钮后应用崩溃原因是设备上没有能响应该 Intent 的应用。解决方式是用resolveActivity先判断if (browserIntent.resolveActivity(getPackageManager()) ! null) { startActivity(browserIntent); } else { Toast.makeText(this, 没有可用的浏览器, Toast.LENGTH_SHORT).show(); }另一个坑是content://协议的分享。从 Android 7.0 开始直接传file://会触发FileUriExposedException必须用FileProvider生成content://URI。实验里如果要做文件分享需要在 Manifest 里注册 provider并配置file_paths.xml。这个点很多同学的实验报告里直接跳过但答辩时老师一问就露馅。3.4 Activity 动画设置与跳转体验优化「activity动画设置」是实验报告里容易加分的小细节。默认的跳转动画比较生硬可以在startActivity后调用overridePendingTransitionstartActivity(intent); overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);!-- res/anim/slide_in_right.xml -- translate xmlns:androidhttp://schemas.android.com/apk/res/android android:fromXDelta100% android:toXDelta0 android:duration300 /逻辑说明overridePendingTransition接收两个动画资源第一个是新 Activity 进入的动画第二个是旧 Activity 退出的动画。参数方面duration建议 200 到 300 毫秒太短看不出来太长显得卡顿。注意overridePendingTransition在 Android 14 上行为有变化推荐用ActivityOptions或overrideActivityTransition。实验环境如果 targetSdk 较低用传统写法没问题但实验报告里最好提一句版本差异体现你对新 API 的关注。4. UI 布局与卡顿排查从 XML 到协调布局4.1 常用布局的性能差异与选择依据「UI」在实验报告里通常只要求「界面美观」但真实工程里布局层级直接影响渲染性能。四种基础布局的性能排序是ConstraintLayoutLinearLayoutRelativeLayoutFrameLayout嵌套场景下。实验里画一个登录界面很多同学用LinearLayout嵌套三层每层一个orientation。这种写法在简单界面没问题但嵌套超过三层后测量和布局的耗时呈指数增长。我的建议是能用ConstraintLayout就用它扁平化层级。!-- 用 ConstraintLayout 实现登录界面 -- androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:apphttp://schemas.android.com/apk/res-auto android:layout_widthmatch_parent android:layout_heightmatch_parent EditText android:idid/et_username android:layout_width0dp android:layout_heightwrap_content android:hint用户名 app:layout_constraintTop_toTopOfparent app:layout_constraintStart_toStartOfparent app:layout_constraintEnd_toEndOfparent android:layout_marginTop100dp android:layout_marginHorizontal32dp / EditText android:idid/et_password android:layout_width0dp android:layout_heightwrap_content android:hint密码 android:inputTypetextPassword app:layout_constraintTop_toBottomOfid/et_username app:layout_constraintStart_toStartOfparent app:layout_constraintEnd_toEndOfparent android:layout_marginTop16dp android:layout_marginHorizontal32dp / Button android:idid/btn_login android:layout_width0dp android:layout_heightwrap_content android:text登录 app:layout_constraintTop_toBottomOfid/et_password app:layout_constraintStart_toStartOfparent app:layout_constraintEnd_toEndOfparent android:layout_marginTop24dp android:layout_marginHorizontal32dp / /androidx.constraintlayout.widget.ConstraintLayout逻辑说明layout_width0dp配合constraintStart_toStartOf和constraintEnd_toEndOf实现水平撑满layout_marginHorizontal控制左右边距。参数方面layout_constraintTop_toBottomOf建立垂直链避免嵌套。4.2 协调布局与 Banner 的实现思路「android中协调布局banner」是实验里常见的组合需求。CoordinatorLayout配合AppBarLayout可以实现滚动时标题栏折叠的效果Banner 通常用ViewPager2加定时器实现。androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:apphttp://schemas.android.com/apk/res-auto android:layout_widthmatch_parent android:layout_heightmatch_parent com.google.android.material.appbar.AppBarLayout android:layout_widthmatch_parent android:layout_heightwrap_content com.google.android.material.appbar.MaterialToolbar android:idid/toolbar android:layout_widthmatch_parent android:layout_height?attr/actionBarSize app:layout_scrollFlagsscroll|enterAlways / /com.google.android.material.appbar.AppBarLayout androidx.recyclerview.widget.RecyclerView android:idid/recycler_view android:layout_widthmatch_parent android:layout_heightmatch_parent app:layout_behaviorstring/appbar_scrolling_view_behavior / /androidx.coordinatorlayout.widget.CoordinatorLayout逻辑说明layout_scrollFlags控制 Toolbar 的滚动行为scroll|enterAlways表示向上滚动时隐藏向下滚动时立即显示。layout_behavior告诉 RecyclerView 它是滚动内容。参数方面?attr/actionBarSize是主题定义的标准高度不要写死 56dp否则不同主题下会错位。4.3 UI 界面卡顿的定位与优化「ui界面卡顿」是实验报告里容易被忽略但答辩时容易被问的点。卡顿的本质是主线程被阻塞。定位工具是 Android Studio 自带的 Profiler看 CPU 和 Memory 曲线。常见卡顿原因和解决方式现象原因解决列表滑动掉帧在onBindViewHolder里做耗时操作把耗时逻辑移到异步任务点击无响应主线程做网络请求用Thread或Coroutine界面跳转慢onCreate里初始化太多 View延迟初始化或懒加载图片加载卡直接加载原图用 Glide 或 Coil 压缩实验里如果要做性能对比可以在onCreate里打时间戳看setContentView到onResume的耗时。超过 200 毫秒用户就能感知到卡顿。提示Profiler 的 System Trace 功能可以精确到方法级别但实验阶段用 CPU Profiler 看个大概就够了。5. 避坑与排查实验报告里不会写但一定会遇到的五个问题5.1 应用启动崩溃Logcat 报ClassNotFoundException现象点击运行应用闪退Logcat 里出现android.activity class {com.liqun.sh/com.liqun.sh.MainActivity} does not exist。原因Manifest 里注册的 Activity 类名和实际包名不一致或者 Activity 没有在 Manifest 里注册。解决检查AndroidManifest.xml里的android:name是否写全路径。如果 Activity 在子包下必须写完整包名比如.ui.MainActivity而不是.MainActivity。5.2 后台启动 Activity 被系统拦截现象应用在后台时收到通知点击通知无法拉起 ActivityLogcat 报abort background activity starts from。原因Android 10 开始限制后台应用启动 Activity必须满足特定条件如前台服务、通知点击等。解决实验里如果要做通知跳转用PendingIntent并设置FLAG_IMMUTABLEIntent intent new Intent(this, DetailActivity.class); PendingIntent pendingIntent PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE );参数说明FLAG_IMMUTABLE表示 PendingIntent 不可变Android 12 以上必须加否则报IllegalArgumentException。5.3 Flutter 跳转原生 Activity 时 SDK 版本不匹配现象Flutter 项目里通过 MethodChannel 跳转原生 Activity编译报The current configured Flutter SDK is not known to be fully supported。原因Flutter SDK 版本和 Android 嵌入层版本不兼容。解决在android/app/build.gradle里检查compileSdk和 Flutter 插件要求的版本是否一致。常见做法是运行flutter doctor看提示按提示升级或降级 Flutter SDK。5.4 分享文件时FileUriExposedException现象调用系统分享传递file://URI 时崩溃报FileUriExposedException。原因Android 7.0 以上禁止在应用间传递file://URI。解决用FileProvider生成content://URI。在 Manifest 里注册provider android:nameandroidx.core.content.FileProvider android:authorities${applicationId}.fileprovider android:exportedfalse android:grantUriPermissionstrue meta-data android:nameandroid.support.FILE_PROVIDER_PATHS android:resourcexml/file_paths / /provider!-- res/xml/file_paths.xml -- paths external-path nameexternal_files path. / /paths然后用FileProvider.getUriForFile生成 URI。5.5 Gradle 同步失败报Could not resolve依赖现象打开项目后 Gradle 同步一直失败提示某个依赖找不到。原因仓库地址失效如 jcenter 停服或网络问题。解决把build.gradle里的jcenter()替换成mavenCentral()并在settings.gradle里检查dependencyResolutionManagement的仓库配置。如果公司内网有镜像优先用镜像地址。6. 实验报告的技术表达把踩坑记录变成加分项实验报告最容易丢分的地方不是代码跑不通而是「只写结果不写过程」。老师想看的是你怎么定位问题、怎么验证假设、怎么对比方案。我一般建议在报告里加一个「问题与解决」章节把上面那些踩坑记录按「现象 → 原因 → 解决 → 验证」四步写清楚。比如FileUriExposedException这个坑不要只写「加了 FileProvider 就好了」要写现象是点击分享崩溃Logcat 报FileUriExposedException原因是 Android 7.0 收紧了文件 URI 权限解决是用 FileProvider 生成content://URI验证是在 Android 13 模拟器上跑通分享并检查 Logcat 无异常。这样写老师一眼就能看出你是真做过实验不是抄的。另一个加分项是对比表格。比如 Activity 传参方式可以列一个表方式适用场景性能代码量Intent putExtra简单类型高少Bundle批量数据高中Serializable自定义对象低少Parcelable自定义对象高多这种表格放在报告里比大段文字描述更有说服力。参数方面Parcelable的性能优势在数据量大时明显实验里如果只传一两个字段用Serializable也能接受但报告里要说明取舍理由。最后说一个我自己的习惯每次实验做完我会把 Logcat 里的关键日志截图保存按时间顺序命名。写报告时直接引用不用回忆。这个习惯让我在答辩时被问到「你当时怎么确定是这个问题」时能直接翻出日志说「你看这里报了ClassNotFoundException我顺着包名查就找到了」。希望帮到你。本文还有配套的精品资源点击获取
返回列表