我的Android 4 学习系列之创建应用程序和Activity:Manifest、Application、Activity
目录
- 介绍Android应用程序组件,以及使用这些组件构建的各种Android应用程序
- Android应用程序的生命周期
- 如何创建应用程序Manifest
- 如何使用外部资源提供对位置、语言和硬件配置的支持
- 如何实现和使用自己的Application类
- 如何创建新的Activity
- 理解Activity的状态转换和生命周期
Android应用程序的组成部分
Android应用程序是由松散耦合的组件构成的,并使用应用程序Manifest绑定到一起。
Manifest描述了每一个组件以及他们之间的交互方式,用于指定元数据、硬件和平台要求、外部库以及必须的权限。
- Activity 应用程序的表示层。
- Service 应用程序中不可见的工作者。
- Content Provider 一个可共享的持久数据存储器。
- Intent 一个强大的应用程序间的消息传递框架。
- Broadcast Receiver Intent侦听器。
- Widget 通常添加到设备主屏幕的可视化应用程序组件。
- Notification Notification 允许向用户发送信号,但却不会过分吸引他们的注意力或者打断他们当前的Activity。
Manifest
包含 Acitity、Service、Content Provider 和 Broadcast Receiver 节点,并使用Intent Filter 和权限来确定这些组件之间以及这些组件和其他应用程序是如何交互的。
结构:
由一个根manifest标签构成,该标签带有一个设为项目包的 package 属性。
通常包含一个 xmlns:android 属性来提供文件内使用的某些系统属性。
versionCode 将当前应用程序版本定义为一个整数,每次迭代时这个整数会增加。
versionName 可以定义一个显示给用户的版本号。
installLocation 是否允许(或首选)将应用程序安装到外部存储器(SD卡等)而不是内部存储器上。其值,preferExternal--只要有可能就会安装到外部存储器;auto--要求系统决定;不指定installLocation属性,用户无法将应用程序移动到外部存储器。
由于外部存储器存在取出或者拒绝外部存储器的问题,安装到外部存储器对一些应用程序不合适,这些应用程序包括:
- 具有Widget、Live Wallpaper和Live Folder的应用程序。
- 提供不中断服务的应用程序。
- 输入法引擎(Input Method Engine, IME)。
- 设备管理器 DeviceAdminReceiver 及管理能力将呗禁用。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hello"
android:versionCode="1"
android:versionName="1.0" >
…
</manifest>
Manifest文件详解
- uses-sdk: minSDKVersion,maxSDKVersion :
设备上必须具有的最低和最高 SDK 版本;targetSDKVersion -- 为应用程序设计的目标SDK。
如果不指定minSDKVersion,默认值为 1,这样应用程序在调用不可用的API就会报错。
一般不指定 maxSDKVersion, 除非你知道应用程序在比它更新的版本上不能工作。
targetSDKVersion 指定你在开发和测试应用程序时使用的平台。将targetSDKVersion设为最新平台版本,这被认为是一种最佳实践。
- uses-configuration 指定应用程序支持的每种输入机制的组合,一般不需要这个node
reqFiveWayNav、reqHardKeyboard、reqKeyboardType、reqNavigation、reqTouchScreen
- uses-feature 安装所需的硬件功能
1) 音频:用于要求低延迟音频管道的应用程序。
2) 蓝牙:
3) 摄像头:自动聚焦功能,闪光灯,前向摄像头,或者把他们设为可选项。
4) 位置:
5) 麦克风:
6) NFC:近场通信支持
7) 传感器:
8) 电话服务:
9) 触摸屏:
10) USB:
11) Wi-Fi:
<uses-feature
android:name="android.hardware.microphone"
android:required="false"/> --可以支持语音
<uses-feature
android:name="android.hardware.camera"/> --暗含摄像头要支持自动聚焦
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false"/> -- 重新指定为可选
<uses-feature
android:name="android.hardware.camera.flash"
android:required="false"/> -- 重新指定为可选
<uses-feature
android:glEsVersion="0x00010001"/> -- OpenGL 最低版本,高十六位为主版本号,低16位为此版本号,所以表示:版本1.1。
OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。
12) supports-screens:
- smallScreens: QVGA 分辨率比传统的HVGA小。
- normalScrees:典型手机屏幕,至少是HVGA:WVGA和WQVGA。
- largeScreens:大屏手机
- xlargeScreens:更大的,平板。
- requiresSmallestWidthDp:指定设备最小屏幕宽度。
- compatibleWidthLimitDp:指定一个上限,如果屏幕分辨率超出上限启动兼容模式。
- largestWidthLimitDp:指定一个绝对上限,如果屏幕分辨率超出上限强制启用兼容模式,而用户无法禁用此模式。
<supports-screens
android:smallScreens="false"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:requiresSmallestWidthDp="480"
android:compatibleWidthLimitDp="600"
android:largestWidthLimitDp="720"/>
13) supports-gl-texture: 用于声明应用程序能够提供以一种特定的GL纹理压缩格式的纹理资源。
<supports-gl-texture
android:name="GL_OES_compressed_ETC1_RGB8_texture"/>
14) uses-permission: 在安装程序时,你所设定权限将告诉给用户,由他们来决定同意与否。
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/>
15) instrumentation: 测试框架。每一个测试类,都需要创建一个新的节点。
<instrumentation android:name=".My Test Class"
android:label="My Test"
android:targetPackage="com.paad.package">
</instrumentation>
16) application: 一个Manifest只能包含一个application。
application 可以包含 Activity、Service、Content Provider 和 Broadcast Receiver 节点的容器。
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
- Activity:
启动一个没有Manifest中定义的Activity时会抛出异常。每一个Activity节点都允许使用 intent-filter 子标签来定义用于启动该Activity的Intent。android:name=".MainActivity" 句点号代表被省略的应用程序包名。
- service:
每一个service类对应一个service标签。service标签也支持使用 Intent-filter 标签来允许运行时迟绑定。
- provider: Content Provider
<provider android:name=".MyContentProvider"
android:authorities="com.paad.myapp.MyContentProvider"/>
- uses-library:
指定应用程序所需的共享库。required:true -- 缺少该库无法安装;false -- 使用库之前,必须使用反射机制来检查该库是否存在。
<uses-library android:name="com.google.android.maps"
android:required="false"/>
Resource
把非代码资源和代码分离始终是一种好的做法。
Resource:values、drawable-ldpi、drawable-mdpi、drawable-hdpi、layout。
R类文件:它包含了加入到项目中的每一个资源的引用。可在代码中引用资源,其优势在设计时检查语法。
资源类型:简单值、Drawable、颜色、布局、动画、样式、菜单、XML 文件(包括 searchable)和原始资源。
1. 简单值 : 字符串、颜色、尺寸、样式和字符串数组或者整数数组,位于res/values文件夹下。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name1">To Do List</string>
<plurals name="androidPlural">
<item quantity="one">one android</item>
<item quantity="other">%d androids</item>
</plurals>
<color name="app_background">#ffffff</color>
<dimen name="default_border">5px</dimen>
<string-array name="string_array">
<item>item 1</item>
<item>item 2</item>
<item>item 3</item>
</string-array>
<array name="integer_array">
<item>3</item>
<item>2</item>
</array>
</resources>
以上包含简单值资源所有类型。习惯上将资源的每一种类型存储到单独的文件当中,例如:res/values/string.xml 只包含字符串类型。
- 字符串
可以保证程序内部的一致性,而且更容易的国际化它们。
支持简单的文本样式:粗体、斜体、下划线。
<string name="app_name1"><b>To Do List</b></string>
支持 string.format,但不支持上面描述的文本样式。为了格式化使用了样式的字符串,需要转义HTML标签:
<string name="app_name1"><b>stop.</b>.%s1$</string>
Code 中调用可用Html.fromHtml方法将字符串转回样式字符序列。
字符串定义的复数形式,比如英语中复数表达方式跟汉语是不同的,通常用s等修饰:
<plurals name="androidPlural"><item quantity="one">one android</item>
<item quantity="other">%d androids</item>
</plurals>
Code 需要使用应用程序的Resources 对象的getQuantityString 方法。
Resources resources = getResources();
String unicornStr = resources.getQuantityString(R.plurals.androidPlural, unicornCount, unicornCount);
- 颜色
# + 可选的alpha通道 + 一个或者两个十六进制值来表示红、绿、蓝:#RGB #RRGGBB #ARGB #AARRGGBB
<color name="app_background">#ffffff</color>
- 尺寸
尺寸单位:px(像素尺寸),in(物理尺寸),pt(物理点),mm(物理毫米),dp(非密度制约的像素),sp(缩放比例无关(scale-independent)的像素).
推荐使用dp、sp 以适应不同屏幕分辨率和密度,从而简化在不同硬件上的缩放。
<dimen name="default_border">5sp</dimen>
<dimen name="default_border1">5dp</dimen>
2. 样式和主题
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
<item name="android:textSize">14sp</item>
<item name="android:textColor">#111</item>
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:textSize">8sp</item>
</style>
包含一个style标签 和name属性;每一个item包含指定样式属性的name属性(字体,大小或者颜色等);有继承特点,使用parent。
3. Drawable
包括位图和NinePatch(可拉伸的PNG)图像,也包含复合的Drawable。
4. 布局
布局可以用来定义任何可视组件(包括Activity、Fragment和Widget)的用户界面。Activity中使用setContentVIew方法完成(通常在onCreate中);Fragment则是使用传入Fragment的onCreateView处理程序的Inflator对象的infalate方法完成的。
每一个布局定义都在res/loyout下一个单独的文件中,每一个文件都包含一个单一的布局,文件名就是他的资源标识符。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.hello.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
setContentView(R.layout.activity_main);
5. 动画
Android支持三种动画:
- 属性动画:一种补间动画(tweened animation), 通过在目标对象的任何属性的两个值之间应用增量变化,可以生成一种动画效果。
- 视图动画:一种补间动画,可以用来旋转,移动和拉伸一个视图。
- 帧动画:逐帧的格子动画,用来显示一系列的drawable图片。
(1)属性动画:
每一个属性动画都存储在项目的res/animator 文件夹下一个单独的文件中,动画的文件名就是资源的标识符。
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="alpha"
android:duration="1000"
android:valueFrom="0"
android:valueTo="1"/>
(2)视图动画:
位置:res/anim 文件夹下,文件名即资源标识符。
方式:alpha(淡出)、scale(缩放)、translate(移动)或者rotate(旋转)。
可用的set标签:
duration -- 动画持续时间,以毫米为单位。
startOffset -- 动画开始之前的延迟,以毫米为单位。
fillBeforetrue -- 在动画开始之前应用动画变形。
fillAftertrue -- 在动画开始之后应用动画变形。
interpolator -- 这种效果随时间改变的速度。要指定一个插值器,需要引用 android:anim/interpolatorName 处的系统动画资源。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="500"
android:duration="1000"/>
<scale
android:fromXScale="1.0"
android:toXScale="0.0"
android:fromYScale="1.0"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="500"
android:duration="500"/>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:startOffset="500"
android:duration="500"/>
</set>
功能: 目标在旋转360度的同时,逐渐收缩并淡出。
(3)逐帧动画:
位置:res/drawable, 文件名为资源ID。
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable-mdpi/ic_laucher1" android:duration="500" />
<item android:drawable="@drawable-mdpi/ic_laucher2" android:duration="500" />
<item android:drawable="@drawable-mdpi/ic_laucher3" android:duration="500" />
</animation-list>
Code 中调用:
ImageView androidIV = (ImageView)findViewById(R.id.icon);
androidIV.setBackground(R.drawable.abc_textfield_searchview_right_holo_light);
AnimationDrawable androidAnimation = (AnimationDrawable)androidIV.getBackground();
androidAnimation.start();
6. 菜单
菜单资源可以用来定义应用程序内的Activity和上下文菜单,它们可以提供与使用代码构建菜单相同的选项。
调用:通过使用MenuInflator Service的inflate方法(通常位于 onCreateOptionsMenu 方法中)把菜单填充到Activity中。
位置:res/menu 文件夹下,文件名即资源标识符。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.hello.MainActivity" >
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never"/>
<item
android:id="@+id/menu_refresh"
android:title="@string/refresh_mi"/>
</menu>
Code 调用:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
使用 Resource
1. 在代码中使用资源:
R:静态类,在编译时创建。R中的每一个子类都把它的相关资源表示为变量的的形式,变量名称和资源标识符相匹配,例如:R.string.app_name, 这些变量值是整数,代表资源在资源表中相应位置,而不是资源本身的实例。
Resources myResources = getResources();
CharSequence styleText = myResources.getText(R.string.abc_action_bar_up_description);
Drawable icon = myResources.getDrawable(R.drawable.abc_ab_bottom_solid_dark_holo);
int opaqueBlue = myResources.getColor(R.color.abc_search_url_text_holo);
float boardWidth = myResources.getDimension(R.dimen.abc_action_bar_default_height);
Animation tranOut;
tranOut = AnimationUtils.loadAnimation(this, R.anim.anim_ok);
ObjectAnimator animator =
(ObjectAnimator)AnimatorInflater.loadAnimator(this, R.anim.abc_fade_out);
String[] stringArray;
stringArray = myResources.getStringArray(R.array.string_array);
int[] intArray = myResources.getIntArray(R.array.integer_array);
AnimationDrawable androidAnimation;
androidAnimation = (AnimationDrawable)myResources.getDrawable(R.drawable.abc_ab_bottom_solid_dark_holo);
2. 资源内引用资源:
格式: attribute=”@[packagename:]resourceType/resourceidentifer">attribute=”@[packagename:]resourceType/resourceidentifer”
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.hello.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
3. 使用系统资源:android.R 方法完成。
Code: CharSequence httpError = getString(android.R.string.httpErrorBadUrl);
XML:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:textColor="@android:color/darker_gray"/>
4. 在当前主题中引用样式:
主题是保证应用程序的UI一致性的非常好的方法。
格式:?android: 而不是@android。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:textColor="?android:textColor"/>
为不同的语言和硬件创建资源
通过res目录下并行的目录结构来实现特定的语言,位置和硬件配置,android将会在运行时使用其动态资源选择机制自动的从这些值中做出选择。
Lifetime
- Activity 进程 : 正在和用户交互的应用程序的进程。
包括:
1) 处于活动状态的Activity。
2) 正在执行onReceive事件处理程序的Broadcast Receiver
2) 正在执行onStart,onCreate或者onDestroy事件处理程序的Service
3) 正在运行、且已标记为在前台运行的Service
Android Application 类简介
每次应用程序运行,Application保持实例化状态。与Activity不同,配置改变并不会导致应用程序重启。通过Application类,可完成三项工作:
- 对Android运行时广播的应用程序级事件(低内存)做出反应。
- 在应用程序组件之间传递对象。
- 管理和维护多个应用程序组件使用的资源
重写应用程序生命周期事件:
onCreate -- 创建应用程序时调用,可以重写这个方法来实例化应用程序单态,以及创建和实例化任何应用程序状态变量和共享资源。
onLowMemory -- 一般后台进程已经终止,但前台应用程序仍然缺少内存时调用,释放资源。
onTrimMemory – onLowMemeory 特定应用程序的替代选择。
onConfigurationChanged – 与 Activity 不同,在配置改变时,应用程序不会终止和重启。
Activity
1. 创建Activity。
public class AboutUsActivity extends BaseActivity {
@Override
protected void onCreate(Bundle bundle) {
// TODO Auto-generated method stub
super.onCreate(bundle);
setContentView(R.layout.main_base);
// 显示闪屏
showFragment(R.id.main_base_view, AboutUsFragment.class, false);
}
}
视图是用来显示数据和提供用户交互的UI控件,Android 提供了多个布局类,称为ViewGroup,它可以包含多个视图来帮助布局UI。
Fragment 用来封装UI的各个部分,从而能够方便的创建动态界面,这些界面能够针对不同的屏幕尺寸和方向重新排列,起到优化UI布局的效果。
要把UI分配给一个Activity,需要在Activity的onCreate方法中调用setContentView。
为了在应用程序中使用一个Activity,需要在Manifest中进行注册.
<activity
android:name="com.isockets.module.aboutus.AboutUsActivity"
android:screenOrientation="portrait" >
</activity>
在Activity节点中,可以添加intent-filter 节点来制定能够用来启动该Activity的Intent。
2. Activity 的生存周期。
- Activity 栈
应用程序的优先级受其最高优先级的Activity的影响。当Android的内存管理器决定终止那个应用程序来释放资源时,它会使用这个栈来决定应用程序的优先级。
- Activity 状态
1)活动状态 -- 栈顶。可见的,有焦点的,可接受用户输入的。
2)暂停状态 -- Activity 是可见的,但没有焦点。极端情况下会被终止。
3)停止状态 -- 不可见。仍然停留在内存,被终止的首选对象。
4)非活动状态 -- 非活动状态。显示和使用前须重启。
3. 监控状态改变
完整生存期 – onCreate <->onDestroy 之间的时间范围
可见生存期 – onStarte <->onStop 之间的时间范围
对用户是可见的;但有可能不具有焦点,或者部分被遮挡;可能会经历多个可见生存期;极端情况可能会被终止,而并不调用onStop。
onStop 用来暂停或者停止动画、线程、传感器监听器、GPS查找、定时器、Service或者其他专门用来更新用户界面的进程。
onRestart 用来恢复和重启这些进程。
活动生存期 – onResume <-> onPause 之间的时间范围
onPause之前执行onSaveInstanceState,这是UI状态保存到Bundle中的一个机会。
Q & A
Q: The project target (Android L (Preview)) was not properly loaded.
A:将SDK版本升级到支持的版本或者最新即可。