第一章 前言
大概在两年前,我第一次决定学习安卓编程,在大约两三周的学习之后,由于缺乏JAVA开发基础和经验,单纯的视频教程看得我云里雾里,不过在此期间学会了使用代码进行页面布局,这给我此后学习Web编程,使用html、css进行页面布局打下了基础。
两年前,我使用的还是联想的i5五系列cpu、机械硬盘、4g内存,这个电脑配置使得我当时用eplise开发安卓程序非常麻烦,打开一个安卓虚拟机需要花很长的时间。半年前,我更换了Surface,用上了8+128G内存+固态硬盘。也更新了最新的i5八系列cpu,电脑配置有了显著提高,运行安卓开发程序也游刃有余了。
而这次重启安卓学习之旅,我将使用AS进行安卓开发。虽然AS目前已支持C/C++做程序开发,但我仍将选择JAVA作为开发语言,以提高我的JAVA水平。
第二章 安装Android Studio
从 https://developer.android.com/studio 下载IDE和SDK后,进行相应安装和配置。安装教程,从网课和CDSN论坛均可找到。不再赘述。
此处说明安装时遇到的坑。
SDK安装后,在SDK管理工具中添加SDK目录即andriod-sdk提示
android sdk location should not contain whitespace
问题1解决后紧接着出现提示
Target folder is neither empty nor does it point to an existing SDK installtion.
问题分析和解决办法:
- 提示意思为SDK的目录路径中出现空格。在我的问题中是,Program Files文件夹名称中间有空格,于是我在根路径重新创建了一个以Andriod为名的文件夹,并将andriod-sdk移到此路径下。
- 提示为,选择的文件夹既不是空的也不是sdk的文件夹,原因是我将sdk目录指向了Andriod为名的文件夹,正确的路径是上步创建Andriod文件下的andriod-sdk。
安装好SDK后,还要给AS安装虚拟机,运行AS后,在Tools菜单下找到AVD Manager(虚拟机管理器),添加合适分辨率、Andriod版本的虚拟机即可。
第三章 应用的资源访问
3.1 认识Android目录
res资源
- drawable-?dpi(l,h,m,x):不同分辨率下的资源文件,如图片的大小。
- values:安卓应用界面上需要显示的各类文本标签文字。
- layout:界面布局文件。
- menu:存放菜单
gen(ADT中)或JAVA(AS中)
由IDE自动生成的包文件
3.2 通用资源访问
基于Java代码访问资源
- Java代码访问方式:
1 | [\<packge-name>.]R. //R类所在包路径可省略 |
Java访问示例
//从drawable目录中加载图片,设置为背景图片
1 | getWindow().setBackgroundDrawableResource(R.drawable.back) |
- //从string设置字符串资源,设置为文本框的显示内容
1 | TextView title=(TextView)findViewById(R.id.title); |
在XML配置文件中访问资源
- XML资源访问方式:
1 | @[<package_name>:] |
- XML资源定义示例
1 | <resources> |
在XML中使用资源示例
- XML资源使用实例片段
1 | <EditText android:layout_width="match_parent" |
3.3 安卓中字符串、颜色和尺寸应用
资源列表
字符串、颜色、尺寸资源,存放在XML文件内,位于/res/values目录下。
如字符串资源:/res/values/strings.xml。R类中名称:R.string
颜色表示方法
使用Color类的常量
如:
int color = Color.BLUE;//创建一个蓝色
使用Color类的静态方法argb创建颜色
int color = Color.argb\(127.255.0.255\);//半透明紫色
在XML资源文件定义颜色值
1 | <resources> |
使用示例
res和assets区别
res内的文件被映射到R.java,基于资源ID直接访问。
assets需通过资源管理器访问。
res下不可以创建子目录,assets可以有目录结构。
读取文件资源的方式不同
- 读取res/raw下的文件资源,通过当前Activity中的
getResources()
方法:
- 读取res/raw下的文件资源,通过当前Activity中的
1 | InputStream is = getResources(). |
- 读取assets下的文件资源,通过当前活动的资源管理器assetmanager读取相应的资源文件:
1 | AssetManager am = getAssets();//通过当前的Activity的getAsset()方法。 |
3.4 Drawable资源
Drawable资源
主要是需要绘制的资源,比如图片资源。
主要格式有*.png、*.jpg等。
图片放入/res/drawable-xxx目录下。
安卓SDK会在编译应用自动加载图片。
资源文件在R.java资源类中生成该资源的索引。
Drawable资源类型
- StateListDrawable资源(动态切换背景)
- LayerDrawable资源(图层叠加)
- ShapeDrawable资源(绘图)
- ClipDrawable资源
- AnimationDrawable资源(动画)
3.5 安卓项目布局文件
什么是安卓布局文件?
- 定义用户界面上各个组建之间的组织结构。
- XML格式文件,安卓系统负责初始化。
- 实现界面布局和逻辑代码的分离。
- 修改和更新界面非常简便,无需修改代码。
- 布局文件是树形结构,使用根节点。
- 一般在布局控件中放置界面显示组建LinearLayout中放入textview文本标签
- 通过节点属性设置显示界面组建的属性:大小、颜色和边距等。
布局示例
布局文件节点属性示例
android:id="@+id/button_id"
- @表示XML解析器应该解析ID字符串把它作为ID资源。
- +符号表示一个新的资源名字,会被创建且加入到资源列表中(R.java)
- @string/@color等可用于访问其他资源。
- 组建id在android应用中是唯一的。
主题 | 内容 |
---|---|
资源位置 | res/layout/my_layout.xml |
布局XML文件格式 | 使用<?xml version= “1.0”encoding=”utf-8” ?> <布局类xmlns:android=”http://schemas.android. Com/apk/res/android” id= “@id+/string_na <br> me”(属性)><视图组件或者其他嵌套布局类> <requestFocus/> </布局类> |
获得XML资源的方法 | Activity.setContentView() |
引用XML资源的格式 | Java代码中:R.layout.my_layout。 XML文件中:@[package:]layout/my_layout |
资源位置 | res/layout/my_layout.xml |
3.6 AndroidManifest.xml项目配置文件
什么是AndroidManifest.xml
位于根目录下,文件名不可修改。
该文件中 <manifest>和 <application>是必需的且只能出现一次。
描述Android应用使用的组建和系统配置信息
- 应用使用的组建及其实现类(Activity/Service等)
- 需要使用的安卓系统权限。
- 声明其他应用程序与该应用程序交互需要的权限
- 该应用程序所需的安卓API版本。
- 列出该应用程序所需类库。
第四章 界面编程任务分析与设计
4.1 循序渐进
Activity简介
- 安卓的视图组件,四大组件之一。
- 定义用户可以看到触摸到的界面。
- 活动内使用各种界面组件,实现交互动作。
- 通过活动,用户界面之间切换跳转、进行数据传递。
Activity概念
- 用来包装用户界面组件的容器,实现用户和界面组件之间的交互。
案列分析教学特点和注意事项
- 界面编程案例分析教学特点
- 案例:基于安卓系统的计算器
- 特点:案例驱动,实践先行
- 优势:在实践中学习抽象的概念
- 界面编程案例分析注意事项
- 知识要点:活动的概念和使用
- 分析技巧:如何将实际中的问题进行分析;分析问题和解决问题的方法
- 编码技巧:在案例中学习编码技巧
- 界面编程案例分析教学特点
计算器案例
操作过程:
用户输入两个计算数;
选择计算类型;
点击计算按钮,进行计算
将结果展示给用户
4.2 活动的创建和使用
创建活动应用程序
- 应用程序通常由多个活动松耦合的组成
- 活动是界面上的组件在屏幕上展示的容器
- 活动通过布局文件展示界面布局的内容
- 活动的生命周期,利用周期的方法扩展
创建活动步骤
- 声明活动类名,继承于活动
- 实现
onCreate(Bundle bundle)
方法,在系统初始化完成活动对象之后,进行用户自定义的初始化活动 - 在
onCreate(View view)
设置用户界面的布局文件 - 通过活动中的
findViewById(int id)
获取各个界面组件,并基于其属性和方法进行相应的操作 - 如果需要在销毁活动进行处理,可以实现
onDestroy()
的方法。
4.3 活动的声明和配置
活动的声明和配置
活动定义后需在AndroidManifest.xml中声明
`<application…/>·节点内添加·<activity…/>·子元素
在
<activity>
子节点内定义Activity的类型(入口活动)
1 | <activity android:name="com.quck.android.calculator" |
配置活动——示例分析
活动的主要配置属性有如下三个:
name:指定该活动的类名
icon:是定该活动对象的图标(可选)
label:指定该活动的标签
在
<activity>
节点中指定一个或者多个<intent-filter.../>
元素Intent的类型和Action决定活动是否会接收消息。
4.4 活动之间的数据交换和调用
活动之间的数据交换和调用
- 活动之间跳转,需传递数据信息
- 通过Intent来进行数据传递
- 数据需要放入Intent或者Bundle之内
什么是Bundle?
- Bundle类是一个key-value对,一个映射,把字符串映射为各种类型。
数据交换
- 写入数据
putExtras(Bundle data)
向Intent中放入需要携带的Bundle数据putXXX(String key, Xxx data)
向Bundle放入Int,Long,String等各种类型的数据putSerializable(String key, Serialzable data)
:向Bundle中放入一份可序列化对象
- 读取数据
getExtras()
从Intent中读取需要携带的Bundle数据getXXX(String key)
从Bundle,Intent读取int,Long,String等各种类型的数据getSerializable(String key)
从Bundle,Intent中读取一个可序列化的对象
- 活动交换示例
- Intent vs Bundle
- 相同点:传递数据时,作用相同
- 不同点:在多个活动之间传递相同数据时,推荐使用Bundle来储存和传递数据,减少重复的读写操作
- 例:活动跳转A->B->C传递相同数据
- 如果使用Intent,则需要在A、B、C的Intent之间进行数据的复制
- 如果使用Bundle,则可直接传递Bundle对象即可
- 写入数据
返回数据
startActivityForResult(Intent intent, int requestCode)
跳转到指定的活动
参数intent:指定目的活动类名
参数requestCode:由程序中自定义的识别码,用以区分不同的七点活动
setResult(int resultCode, Intent data)
设置resultCode表示结果的Activity,第二个参数保存传递的结果数据
onActivityResult(int requestCode, int resultCode, Intent data)
参数requestCode:起点活动定义唯一值
参数resultCode:目的活动定义的唯一标识值
参数data:从墓地活动返回的数据
数据使用步骤
- 起点活动,调用
startActivityForResult()
跳转目的活动 - 在目的活动中调用
setResult()
- 在起点活动覆写
onActivityResult()
在方法内获取目的活动返回的数据
- 起点活动,调用
第五章 服务开发和广播事件
5.1 循序渐进
案列:音乐播放器
任务概述
功能分析
界面设计
实现暂停、播放和停止
播放同时,显示歌手和音乐名称
用户界面设计
主界面
技术要点
服务的创建、调用
服务和活动之间的通信
Intent对象的使用
案例演示
案例任务分析和设计
音乐播放器界面分析
核心代码设计和实现
核心代码编写步骤:
- 创建安卓项目MusicBox
- 在res/loyout目录,创建播放器的主界面布局文件
- 定义一个MusicBoxContant的常量类存放程序中用到的静态或不变的信息
- 创建音乐播放器的服务类
- 在全局配置文件中,声明服务类
- 定义实现音乐播放器的主界面
- 定义事项ActicityReciver事件接收器,接受音乐服务状态变化广播事件的接收器
- 定义实现按钮事件接收器,播放和停止按钮,发送广播事件
5.2 安卓中的系统服务
安卓将诸多常用功能内置为系统服务
提供简单的获取系统服务的方式
系统服务涵盖了安卓绝大部分常用功能,如,拨打电话,发送短信
安卓中获取系统服务
获取系统服务代码示例
TelephonyManager phoneManager=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
强制类型转化
- 在程序运行过程中,将父类型对象转化为子类型对象。
- 由于子类型相比父类型的内涵丰富,属性方法更多,所以要把父类型转化为子类型时,需要强制转化,成为强制类型转换。
- 并不是所有父类型都可以转化为子类型,要根据具体的使用情况来做具体的判断。
5.3 广播接收机制
广播消息
- 广播是一种在应用程序之间传输信息的计指
- BroadcastReceiver广播接收者
- 广播消息Intent(消息载体)
- 被订阅广播的多个广播接收者接收
- 消息订阅者不了解发送者
广播接收者
- BroadcastReceiver对发出的广播事件进行过滤,应用程序通知其他应用程序某些数据已经下载完毕。
- 广播接收者没有图形界面
- 广播可以有多个接收者,彼此不知晓。广播接收者之间匿名
监听广播机制
- 广播和事件监听器是分离的
- 通过安卓系统进行广播、接收广播事件
- 注册和移除监听通过安卓系统来完成
- 安卓系统提供很多广播定义在
android.content.Intent
类中
广播方法
sendBroadcast()
:普通模式- 所有注册了广播的接收者会获得事件通知
- 接收者接受顺序不确定并发地在各自的应用进程中执行
- 接收者和发送者不知晓
sendOrderedBroadcast()
:有序广播模式接收者依照设定的优先级高低依次接受
高优先级接收者可以中断后续广播的接收,
BroadcastReceiver.abortBroadcast()
终止这个广播事件的传播,低优先级的触发器组件不再有机会接收高优先级接收者可添加额外信息给后续接收者
BroadcastReceiver.setResult()
监听广播实现
- 获取广播事件的消息接口名称
- 事件定制的广播接收器,添加相应的处理逻辑
- 注册广播接收器到安卓系统中
监听广播实现示例
1 | public class MyBroadcastReceiver extends BroadcastReceiver{ |
监听广播注册
在manifest中注册监听器
1 | <!--声明接收器--> |
在运行代码中注册广播监听器
1 | //创建监听器对象 |
广播事件生命周期
- 广播消息到来,新建BroadcastReceiver对象
- 调用
onReceive()
方法,执行操作 - 操作完成后,对象被销毁
- 事件出发—>创建事件监听器对象—>调用监听器的
onReceiver()
—>销毁事件监听器的对象—>结束操作,返回
广播事件注意事项
- 在广播接收器中响应逻辑中不能执行比较耗时的操作
- 在onReceive()方法中执行超过10秒,就会弹出无响应对话框。