《Android移动应用开发(微课版)》陈轶老师等编著课后答案分享

发布时间:2024年01月11日

一、前言

其实这篇博客没必要写的,只是在期末复习之时偶然想起这事,本人发博客主打就是一个兴致,兴致一来就写,路过勿喷(ノへ ̄、)。

资源仅用于分享,切勿用于不当途径。(其实你在原版书上扫码,然后访问一下下载链接,把它发到你的邮件上面,很容易就能get资源,你也可以去我主页里面看得到资源。拒绝盗版!拒绝盗版!!拒绝盗版!!!)

二、目录

目录

第 1章 Android的开发环境

第 2章 Kotlin语言基础

第 3章 Android活动组件

第 4章 Android的界面开发

第 5章 Android的并发处理

第 6章 Android的广播机制

第 7章 Android的服务组件

第 8章 Android的网络应用

第 9章 持久化处理和 ContentProvider组件

第 10章 Android JetPack


三、各章内容

第 1章 Android的开发环境

一、选择题

(1)D (2)B (3)A (4)D (5)C (6)A (7)B (8)A

二、填空题

(1)操作系统 编程平台

(2) Apache开源许可证

(3) 应用层 应用框架层 Android核心库和 Android运行时 HAL硬件抽象层 Linux

内核层

(4) 应用框架 Application Framework Binder进程通信代理 Binder IPC PROXIES Android系统服务 Android System Services 硬件抽象层 HAL Linux内核

(5)dex oat

三、

1.

2.

3.

APK文件,转换扩展名为 rar或 zip,利用解压工具解压,打开文件目录,有如下目录和文件结构:

AndroidManifest.xml是移动应用的系统配置清单信息,设置了移动应用的名称、版本、访问权限等;

assets目录:包括了应用中没有编译的资源.

res目录:包括了应用中已经编译的资源,例如字符串、布局、尺寸大小等.

META_INF:目录中包括了 CERT.RSA和 CERT.SF,应用的签名文件,说明移动应用的数字签名。MANIFEST.MF说明移动应用的包和扩展的信息.

resources.arsc:为已经编译的资源 res目录下的资源指定资源编号 ID.

classes.dex:运行在 Dalvik虚拟机的压缩的字节码代码.

lib目录:保存了运行移动应用的本地库.

启动模拟器,然后将 APK文件直接拖放到模拟器即可。参考微课视频.

第 2章 Kotlin语言基础

一、选择题

(1)D (2)B (3)A (4)D (5)B (6)A (7)C (8)C (9) A (10)D

二、填空题

(1) Kotlinc -include-runtime -d (2) .kt

(3) “你好,$name”

(4) 非空,非空

(5) Map

(6) MutableMap

(7) Import 包名

(8) 调用该函数的对象本身

(9) Lambda函数块的最后一个语句或指定 return表达式

(10) ?.

三、上机实践

(1)编写程序,实现从键盘输入一个年份,将该年的所有月历打印输出。

package chenyi.book.android.chapter0(2)exercises

import java.time.LocalDate

import java.util.*

/**

*@author 南昌大学计算机系陈轶

* (1)编写程序,实现从键盘输

* 入一个年份,将该年的所有

* 月历打印输出。

*/

fun main(){

val sc = Scanner(System.`in`)

print("输入指定的年份:")

val year = sc.nextInt()

val calendar = MyCalendar(year) print(calendar.getCalendarStr()) }

/**

* 定义年历类

* @property year Int

* @constructor

*/

class MyCalendar(val year:Int){

/**

* 闰年判断

* @return Boolean

*/

fun isLeapYear()= year%4==0 && year%100==0 || year%400==0

/**

* 获得指定月份的天数

*/

fun getDayByMonth(month:Int):Int=when(month){ 1,3,5,7,8,10,12->31

2-> if(isLeapYear()) 29 else 28

4,6,9,11->30

else-> 0

}

/**

* 获得指定月份第一天的星期数

* @param month Int

* @return String

*/

fun getFirstWeek(month:Int):Int = LocalDate.of(year,month,1).dayOfWeek.value

/**

* 获得指定月份的月历

* @param month Int

*/

fun getDaysExp(month:Int):String{

val week = getFirstWeek(month)

val result = StringBuilder()

result.append(String.format("\n%20s\n","$month 月"))

result.append(String.format("%5s%5s%5s%5s%5s%5s%5s\n","Sun","Mon","Tue","Wed","Thu","Fri","Sat"))

for(i in 0 until week)

result.append(String.format("%5s"," "))

val days = getDayByMonth(month)

for(i in 0..days+1){

if((i+week)%7==0)

result.append("\n")

result.append(String.format("%5d",(i+1)))

}

return result.toString() }

/**

* 获得年历的字符串表示

* @return String

*/

fun getCalendarStr():String{

val result = StringBuilder()

result.append(String.format("%20s","${year} 年的年历\n")) for(month in (1).12){

result.append(getDaysExp(month))

}

return result.toString()

(2) 编写程序,要求从键盘输入一个学生的百分制成绩,要求判断并输出成绩的等级。其中,优:90~100,良:80~89,中:70~79,及格:60~69,小于 60分表示不及格。package chenyi.book.android.chapter0(2)exercises import java.util.*

/**

* @author 南昌大学计算机系陈轶

* 编写程序,要求从键盘输入一个学生的百分制成绩, * 要求判断并输出成绩的等级。其中,优:90~100,

* 良:80~89,中:70~79,及格:60~69,小于 60分

* 表示不及格。

*/

fun main(){

val sc = Scanner(System.`in`)

print("输入一个学生的成绩:")

val score = sc.nextInt()

val grade = when{

score in 90..100->"优秀"

score in 80..89->"良好"

score in 70..79->"中等"

score in 60..69->"及格"

else->"不及格"

}

print("成绩等级:$grade")

}

(3)编写程序,利用列表结构存放学生的姓名,要求向指定班级学生发送通知。通知内容如下:

XXX同学,

请与今天下午 2:00~4:00在信工楼 B104室参加班级会议,届时请准时参加。

班委会

package chenyi.book.android.chapter0(2)exercises

/**

* @author 南昌大学计算机系陈轶

*/

fun main(){

val lst = listOf("张三","李四","王五","刘六","漆七","巴芳") val message="""

同学,

请与今天下午 2:00~4:00在信工楼 B104室参加班级会议,届时请准时参加。

班委会

""".trimIndent()

lst.forEach {

print(it+message+"\n")

}

}

(4)编写程序,从键盘输入一段英文句子,统计句子中单词出现次数。 package chenyi.book.android.chapter0(2)exercises

import java.util.*

/**

* @author 南昌大学计算机系陈轶

* 编写程序,从键盘输入一段英文句子,统计句子中单词出现次数。

*/

fun main(){

val sc = Scanner(System.`in`)

print("输入一段英文:")

val sentence = sc.nextLine()

val words = sentence.split(" |,|\\.".toRegex())

val map = mutableMapOf()

words.forEach {

var count = map[it]

if(count==null)

map[it] = 1

else

map[it] = count+1

}

map.forEach { (t, u) ->

print("$t 出现次数:$u\n")

}

}

(5) 编写程序,结合面向对象实现发红包的应用。要求:群主可以发红包,普通用户可

以接受红包。并按照接受红包金额升序排序输出。

package chenyi.book.android.chapter0(2)exercises import java.util.*

/**

* @author 南昌大学计算机系陈轶

* 编写程序,结合面向对象实现发红包的应用。

* 要求:群主可以发红包,普通用户可以接受红包。

* 并按照接受红包金额升序排序输出。

*/

//定义用户

open class User(val name:String,var money:Double){ fun displayInfo(){

print("$name 目前的金额是: $money \n")

}

}

class GroupOwner(name:String,money:Double):User(name,money){

val rand = Random()

/**

* 发红包

* totalMoney:总金额

* number:红包的份数

*/

fun sendMoney(totalMoney:Double,number:Int):List{ if(totalMoney>money)

throw MoneyException()

val moneyLst = mutableListOf()

var tmp = totalMoney

var afterMoney = 0

for(i in 1..number){

if(tmp == 0.0) {

moneyLst.add(0.0)

continue

}

//生成随机金额

var m = rand.nextInt(tmp.toInt())

tmp -= m

afterMoney += m

moneyLst.add(m.toDouble())

}

//修改现金总数

money -= afterMoney

return moneyLst

}

}

/**

* 群成员

* @constructor */

class GroupMember(name:String,money:Double,var hongbao:Double):User(name,money){ fun receiveMoney(m:Double){

if(m>0) {

money += m

hongbao=m

}

}

}

fun main(){

val groupOwner = GroupOwner("群主",2000.0)

groupOwner.displayInfo()

//定义红包

val moneyLst = groupOwner.sendMoney(300.0,10)

val users = mutableListOf()

for(i in 1..10)

users.add(GroupMember("用户$i",Random().nextInt(1000).toDouble(),0.0))

var index = 0

moneyLst.forEach {

users[index].receiveMoney(it)

index++

}

users.sortedBy {-it.hongbao }.forEach {

if(it.hongbao>0) {

print("${it.name} 接受到红包,金额:${it.hongbao} 元 现在拥有的总金额:${it.money} \n")

}else{

print("${it.name} 没有抢到红包,现有的总金额:${it.money} \n")

}

}

groupOwner.displayInfo()

}

class MoneyException: Exception() {

override fun toString():String="金额不够!" }

第 3章 Android活动组件

一、选择题

1. D (2)A (3)B (4)(1)C (2)D (5)D (6)A (7)B (8) C

二、填空题

(1) AndroidManifest.xml stardand singleTop singleInstance singleTask (2) finish() exitProcess(0)

(3) 任务栈 或 Back Stack

(4) onAttach()

(5) onCreateView()

(6) onPause()

(7) fragmnt

android:name=”chenyi.ch0

MainFragment

三、上机实践

第 4章 Android的界面开发

一、选择题

(1)C (2)A (3)B (4)C (5)A (6)B (7)B (8)B (9)

二、填空题

(1) 事件源 事件监听器

(2) 水平方向约束条件 垂直方向约束条件

(3) 此事件已经处理完毕 事件未被处理会向后传递

(4) 基于监听的事件处理 基于回调的事件处理

(5) RecyclerView.Adapter

(6) onCreateVIewHolder() onBindViewHolder()

三、上机实践

第 5章 Android的并发处理

一、选择题

(1)C (2)A (3)B (4)A (5)A (6)B (7)A (8)A (9)B

二、填空题

(1) launch async

(2) 线程

(3) 进程 UI主线程

(4) (1)在 UI线程收到事件(2)在非 UI线程中处理相应事件(3)UI根据处理结果

进行刷新

(5) CorountineScope

三、上机实践

第 6章 Android的广播机制

一、选择题

(1) C (2)A.(3)B (4)A (5)B

二、问答题

( 1)静态注册方式:定义一个 BroadcastReceiver的子类如 MyReceiver为

BroadcastReceiver组件,然后在应用模块对应的配置清单文件 AndroidManifest.xml进行配置。形如:

移动应用的系统配置清单文件 AndroidManifest.xml注册 MyReceiver这个BroadcastReceiver组件,AndroidManifest.xml内容如下所示:

package="chenyi.book.android.ch06_1">

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/AppTheme">

android:enabled="true"

android:exported="true" />

??

动态注册方式:定义一个 BroadcastReceiver的子类如 MyReceiver为 BroadcastReceiver组件,无需在应用模块的配置清单文件 AndroidManifest.xml进行配置。需要调用活动Activity的 registerReceiver()函数动态注册 BroadcastReceiver组件。形式如下:

val intentFilter = IntentFilter()

filter.setAction(“book.android.ch0(6)Broadcast”)

val receiver = MyReceiver()

registerReceiver(receiver,intentFilter)

当已经注册的广播接收器 BroadcastReceiver组件不再需要的时候,可以在活动 Activity调用 unregisterReceiver()函数取消注册。形式如下:

unregisterReceiver(receiver)

(2)标准广播方式:标准广播是一种完全异步执行的广播,在广播发出后所有的广播接收器会在同一时间接收到这条广播,之间没有先后顺序,效率比较高,且无法被截断。标准广播需要调用活动的 sendBroadcast()函数来发送意图广播。

有序广播方式:有序广播是一种同步执行的广播,在广播发出后同一时刻只有一个广播接收器能够接收到, 优先级高的广播接收器会优先接收,当优先级高的广播接收器的 onReceiver() 函数运行结束后,广播才会继续传递,且前面的广播接收器可以选择截断广播,这样后面的广播接收器就无法接收到这条广播了。有序广播是调用活动中的sendOrderedBroadcast()函数可以实现有序广播,使得广播接受器依次接受意图广播。

粘性广播方式:粘性广播是不同的,即使广播已经接受并处理了,它仍会在移动应用系统中一直存在。可以通过 reigsterReceiver()函数在广播意图中存储数据。活动可以通过 sendStickyBroadcast(Intent intent)来发送粘性广播。发送者需要声明

“android.permission.BROADCAST_STICKY “权限,也可通过 removeStickyBroadcast()在任何时候对粘性广播进行移除。在 Android API 21中,对 sendStickBroadcast()一系列的函数,因为安全性的问题不赞成使用。

三、上机实践

第 7章 Android的服务组件

一、选择题

(1)B (2)A (3)A (4)B (5)B (6)C (7)B (8)D

二、填空题

(1) onCreate onStartCommnd() onDestroy

(2) onCreate onBind onUnbind onDestroy

(3) 提高 Service的优先级 设置服务为系统服务 利用 Android的系统广播 前台服务 三、上机实践

第 8章 Android的网络应用

一、选择题

1. A (2)B (3)B (4)B (5) C (6)C (7)

二、问答题

(1) HttpURLConnection分为五个步骤来实现基于 HTTP协议在线访问网络资源:(a)创建 HttpURLConnection连接对象;(b)配置连接的相关参数,例如设置 HTTP访问所使用 POST(向指定的资源提交要处理的数据)方式、建立连接需要时间、读取在线资源的限定时间等;(c)根据连接对象,创建当前连接的输入和输出流对象;(d)通过输

入输出流实现对资源的读取;(e)关闭连接。

(2) 要使用 Retrofit库访问网络资源

(a)需要在模块的构建文件 build.gradle增加依赖:

dependencies {

??

implementation 'com.squareup.retrofit2:retrofit:(2)(9)0'

implementation 'com.squareup.retrofit2:converter-gson:(2)(9)0'

??

}

(b)定义实体,用于将请求的数据转换成对象的实体对象。

(c)创建服务接口类,定义服务的主要方法。

(d)定义创建服务对象

(e)完成对网络资源的访问和数据的转换

三、上机实践

第 9章 持久化处理和 ContentProvider组件

一、选择题

(1)B (2)B (3)C (4)C (5) A (6)B (7)C (8)C (9)D (10)C

二、问答题

(1) SharedPreferences是 Android系统种一种轻量级的数据存储方案,只在移动应用内部中使用,主要对短而少的数据进行处理。为了实现对数据的处理,

SharedPreferences提供了键值对的数据存储方式,存放在应用程序私有的文件夹下。利用 SharePreferences保存数据的步骤:(a)创建 SharedPreferences对象(b)通过调用 SharedPreferences对象的 edit()方法获得 SharedPreferences.Editor对象(c)通过 SharedPreferences.Editor对象实例来修改 SharedPreferences存储的数据;通过调用 SharedPreferences.Editor对象 put系列的方法来设置键值对数据(d)执行

SharePreferences对象的 apply提交保存记录。

(2) 可以结合 FileInputStream文件按输入字节流和 FileOutputStream文件输出字节流实现移动应用的私有文件夹 data数据进行读写操作。可以通过 FileOutputStream类的 openFileOutput(name:String,mode:Int)方法用来打开相应的输出流,以及

FileInputStream类的 openFileInput(name:String)方法用来打开相应的输入流,形如: //创建文件输出字节流

val outputStream:FileOutputStream = Context.openFileOutput(fileName,mode)

参数 mode表示打开文件的模式,可以取值为:MODE_PRIVATE和 MODE_APPEND。其中,

MODE_PRIVATE:只能被当前程序读写,MODE_APPEND:以追加方式打开文件。

可以调用 outputStream执行 write系列方法实现数据写入文件

//创建文件输出字节流

val inputStream:FileInputStream = Context.openFileInput(fileName)

可以调用 inputStream执行 read系列方法实现从文件读取数据

(3) 升级 SQLite数据库步骤:(1)DatabaseOpenHelper子类中的 onUpdate()方法实现

数据库的更新。

//打开数据库

val db = dbHelper.readableDatabase

//检索记录返回 Cursor游标对象

val cursor = class DistrictDBHelper(val context: Context, val name:String, val

version:Int)

:SQLiteOpenHelper(context,name,null,version) {

//定义创建数据表的 SQL语句字符串

private val createSQL = "create table city(" +

"id integer primary key autoincrement," +

"state text," +

"city text," +

"county text," +

"code text," +

"demo text)"

private val dropSQL = "drop table if exists city"

/**

* 创建数据库

*/

override fun onCreate(db: SQLiteDatabase?) {

db?.execSQL(createSQL)

}

/**

* 升级数据库

*/

override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {

db?.execSQL(dropSQL)

onCreate(db)

}

}

(4)修改数据库创建的版本,只需要比上一次的版本加 1即可;

DistrictDBHelper(this,"district.db",2)

(5)SQLiteDatabase提供了一系列的 query方法实现对数据的检索

如果要检索 district.db数据库的 city中指定省份的所有记录,可以写成如下形式:

db.query("city",arrayOf("state","city","county"),"state

= ?",arrayOf(state),null,null,"city"))

//判断并将游标指向第一条记录

if(cursor.moveToFirst()){

do{

//获取指定列的取值

val state = cursor.getString(cursor.getColumnIndex("state"))

val city = cursor.getString(cursor.getColumnIndex("city"))

val county = cursor.getString(cursor.getColumnIndex("county"))

Log.d(“DB”,”${state}-${city}-${county}”)

}while(cursor.moveToNext())//游标向下移动直至结束

cursor.close()

}

(6)一些权限严重影响了用户的隐私安全,例如获得用户的隐私数据和设备的控制权等,需要在运行时请求用户授予这些权限。这些必须在运行时由用户授予权限称为运行时权限,因为这些权限涉及到用户隐私安全,也称为危险权限 Dangerous Permission。这些危险权限,必须要用户同意授权才可以使用。

三、上机实践

第 10章 Android JetPack

一、填空题

1.基础组件(Foundation)、架构组件(Architecture)、行为组件(Behavior)、界面组件(UI)

2.Data Binding Lifecycles LiveData Navigation Paging

ViewModel Room WorkManager

3.行为

4.ViewModel

5.Lifecycle.State.INITIALIZED

Lifecycle.State.CREATED

Lifecycle.State.STARTED

Lifecycle.State.RESUMED

Lifecycle.State.DESTROYED

6.Lifecycle.Event.ON_ANY

7.LiveData

8.viewBinding tools:viewBindingIgnore 9.dataBinding data 单向绑定 双向绑定 10.NavController argument app:argType

二、上机实践

文章来源:https://blog.csdn.net/m0_63944500/article/details/135523248
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。