• 1. http://www.newer.com.cn第四章Android 应用程序结构
  • 2. 回顾Android 应用使用java 来开发; Android的class 文件是编译过程中的中间目标文件,需要链接成dex 文件才能在Dalvik 上运行; 每一个Dalvik 应用作为一个独立的Linux 进程执行;
  • 3. 本章相关词汇(蓝色为关键字)单 词说 明manifest清单、证明sample案例Activity活动resource资源asset资产
  • 4. 目 标Android应用程序组成结构 API参考文档的使用 数字签名
  • 5. Android应用程序组成结构
  • 6. Android程序结构 在建立HelloAndroid程序的过程中,ADT会自动建立一些目录和文件,这些目录和文件有其固定的作用,有的允许修改,有的不能修改。下面逐一的介绍
  • 7. Android程序结构在“Package Explore”中,ADT以工程名称HelloAndroid作为根目录,将所有字段生成的和非自动生成的文件都保存在这个根目录下 根目录包含四个子目录:src、assets、res和gen,一个库文件android.jar,以及两个工程文件Androidmanifest.xml和default.properties
  • 8. Android程序结构src目录是源代码目录,所有允许用户修改的java文件和用户自己添加的java文件都保存在这个目录中 HelloAndroid工程建立初期,ADT根据用户在工程向导中的“Create Activity”选项,自动建立HelloAndroid.java文件
  • 9. Android程序结构HelloAndroid.java是Android工程向导根据Activity名称创建的java文件,这个文件完全可以手工修改。为了在Android系统上显示图形界面,需要使用代码继承Activity类,并在onCreate()函数中声明需要显示的内容 HelloAndroid.java文件的代码如下 package edu.hrbeu.HelloAndroid; import android.app.Activity; import android.os.Bundle; public class HelloAndroid extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }
  • 10. Android程序结构第3行和第4行的代码通过android.jar从Android SDK中引入了Activity和Bundle两个重要的包,用以子类继承和信息传递 第6行代码声明HelloAndroid类继承Activity类 第8行代码表明需要重写onCreate()函数 第9行代码的onCreate()会在Activity首次启动时会被调用,为了便于理解,可以认为onCreate()是HelloAndroid程序的主入口函数 第10行代码调用父类的onCreate()函数,并将savedInstanceState传递给父类,savedInstanceState是Activity的状态信息 第11行代码声明了需要显示的用户界面,此界面是用XML语言描述的界面布局,保存在res/layout/main.xml资源文件
  • 11. Android程序结构gen目录是1.5版本新增的目录,用来保存ADT自动生成的java文件,例如R.java或AIDL文件 R.java文件是ADT自动生成的文件,包含对drawable、layout和values目录内的资源的引用指针,Android程序能够直接通过R类引用目录中的资源
  • 12. Android程序结构R.java文件不能手工修改,如果向资源目录中增加或删除了资源文件,则需要在工程名称上右击,选择Refresh来更新R.java文件中的代码 R类包含的几个内部类,分别与资源类型相对应,资源ID便保存在这些内部类中,例如子类drawable表示图像资源,内部的静态变量icon表示资源名称,其资源ID为0x7f020000。一般情况下,资源名称与资源文件名相同
  • 13. Android程序结构HelloAndroid工程生成的R.java文件的代码package edu.hrbeu.HelloAndroid; public final class R { public static final class attr { } public static final class drawable { public static final int icon=0x020000; } public static final class layout { public static final int main=0x030000; } public static final class string { public static final int app_name=0x040001; public static final int hello=0x040000; } }
  • 14. Android程序结构引用资源 资源引用有两种情况:一种是在代码中引用资源;另一种是在资源中引用资源 代码中引用资源,需要使用资源的ID,可以通过R.资源类型.资源名称[R.resource_type.resource_name]或[android.R.resource_type.resource_name]获取资源ID resource_type代表资源类型,也就是R类中的内部类名称 resource_name代表资源名称,对应资源的文件名或在XML文件中定义的资源名称属性 资源中引用资源,引用格式:@ [package:]type:name @表示对资源的引用 package是包名称,如果在相同的包,package则可以省略
  • 15. Android程序结构android.jar文件是Android程序所能引用的函数库文件,Android通过平台所支持API都包含在这个文件中 assets目录用来存放原始格式的文件,例如音频文件、视频文件等二进制格式文件。此目录中的资源不能被R.java文件索引。,所以只能以字节流的形式读取。一般情况下为空
  • 16. Android程序结构res目录是资源目录,有三个子目录用来保存Android程序所有资源 drawable目录用来保存图像文件 layout目录用来保存与用户界面相关的布局文件 values目录保存文件颜色、风格、主题和字符串等 在Hello Android工程中,ADT在drawable目录中自动引入了icon.png文件,作为HelloAndroid程序的图标文件;在layout目录生成了main.xml文件,用于描述用户界面
  • 17. Android程序结构main.xml文件,是界面布局文件,利用XML语言描述的用户界面 界面布局的相关内容将在用户界面设计中进行详细介绍
  • 18. Android程序结构main.xml文件的代码 第7行的代码说明在界面中使用TextView控件,TextView控件主要用来显示字符串文本 第10行代码说明TextView控件需要显示的字符串,非常明显,@string/hello是对资源的引用
  • 19. Android程序结构Strings.xml文件的代码 通过strings.xml文件的第3行代码分析,在TextView控件中显示的字符串应是“Hello World, HelloAndroid!” 如果修改strings.xml文件的第3行代码的内容,重新编译、运行后,模拟器中显示的结果也应该随之更改 Hello World, HelloAndroid! HelloAndroid
  • 20. Android程序结构AndroidManifest.xml是XML格式的Android程序声明文件,包含了Android系统运行Android程序前所必须掌握的重要信息,这些信息包含应用程序名称、图标、包名称、模块组成、授权和SDK最低版本等,而且每个Android程序必须在根目录下包含一个AndroidManifest.xml文件"
  • 21. Android程序结构AndroidManifest.xml文件的代码
  • 22. Android程序结构AndroidManifest.xml文件的根元素是manifest,包含了xmlns:android、package、android:versionCode和android:versionName共4个属性 xmlns:android定义了Android的命名空间,值为http://schemas.android.com/apk/res/android package定义了应用程序的包名称 android:versionCode定义了应用程序的版本号,是一个整数值,数值越大说明版本越新,但仅在程序内部使用,并不提供给应用程序的使用者 android:versionName定义了应用程序的版本名称,是一个字符串,仅限于为用户提供一个版本标识
  • 23. Android程序结构manifest元素仅能包含一个application元素,application元素中能够声明Android程序中最重要的四个组成部分,包括Activity、Service、BroadcastReceiver和ContentProvider,所定义的属性将影响所有组成部分 第6行属性android:icon定义了Android应用程序的图标,其中@drawable/icon是一种资源引用方式,表示资源类型是图像,资源名称为icon,对应的资源文件为res/drawable目录下的icon.png 第7行属性android:label则定义了Android应用程序的标签名称
  • 24. Android四大天王1--Activity我是整个应用程序的门面,当然必须靓丽啦!我主要负责数据的显示
  • 25. Android四大天王2- Broadcast Receiver我是Android王国的秘密警察,你们虽然看不到我,可是我却监听系统中的所有事件。
  • 26. Android四大天王3-Service我是Android王国的劳模,你们虽然看不到我,可是我却承担了大部分数据处理工作。
  • 27. Android四大天王4—Content Provider我是Android王国的国家档案馆,我负责存放数据,并允许有需要的 应用程序访问这些数据。
  • 28. Android程序结构activity元素是对Activity子类的声明,必须在AndroidManifest.xml文件中声明的Activity才能在用户界面中显示 第8行属性android:name定义了实现Activity类的名称,可以是完整的类名称,也可以是简化后的类名称 第9行属性android:label则定义了Activity的标签名称,标签名称将在用户界面的Activity上部显示,@string/app_name同样属于资源引用,表示资源类型是字符串,资源名称为app_name,资源保存在res/values目录下的strings.xml文件中 intent-filter中声明了两个子元素action和category,intent-filter使HelloAndroid程序在启动时,将.HelloAndroid这个Activity作为默认启动模块
  • 29. Android程序结构可视化编辑器 双击AndroidManifest.xml文件,直接进入可视化编辑器,用户可以直接编辑Android工程的应用程序名称、包名称、图标、标签和许可等相关属性
  • 30. Android程序结构default.properties文件记录Android工程的相关设置,该文件不能手动修改,需右键单击工程名称,选择“Properties”进行修改 在default.properties文件中只有第12行是有效代码,说明Android程序的编译目标# This file is automatically generated by Android Tools. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # # This file must be checked in Version Control Systems. # # To customize properties used by the Ant build system use, # "build.properties", and override values to adapt the script to your # project structure. # Project target. target=android-3
  • 31. Android消息和数据传递-Intent我是运输大队长,应用程序的所有数据都由我传送
  • 32. 显示图像增加 ImageView
  • 33. Android应用
  • 34. Activity活动1最基本的Android 应用程序组件,应用程序中,一个活动通常就是一个单独的屏幕。每一个活动都被实现为一个独立的类,并且从Activity基类中继承而来,活动类将会显示由视图控件组成的用户接口,并对事件做出响应。 大多数的应用是由多个屏幕显示组成。 例如:一个文本信息的应用也许有一个显示发送消息的联系人列表屏幕,第二个屏幕用来写文本消息和选择收件人,再来一个屏幕查看消息历史或者消息设置操作等。这里每一个这样的屏幕就是一个活动,很容易实现从一个屏幕到一个新的屏幕并且完成新的活动。 在某些情况下当前的屏幕也许需要向上一个屏幕活动提供返回值--比如让用户从手机中挑选一张照片返回通讯录做为电话拨入者的头像。
  • 35. Activity活动2当一个新的屏幕打开后,前一个屏幕将会暂停,并保存在历史堆栈中。用户可以返回到历史堆栈中的前一个屏幕。当屏幕不再使用时,还可以从历史堆栈中删除。默认情况下,Android 将会保留从主屏幕到每一个应用的运行屏幕。 简单理解Activity 代表一个用户所能看到的屏幕,Activity 主要是处理一个应用的整体性工作,例如,监听系统事件(按键事件、触摸屏事件等)、为用户显示指定的View,启动其他Activity 等。所有应用的Activity都继承于android.app.Activity 类,该类是Android 提供的基层类,其他的Activity 继承该父类后,通过重写父类的方法来实现各种功能,这种设计在其他领域也较为常见。
  • 36. 为什么要签名1)发送者的身份认证 由于开发商可能通过使用相同的Package Name来混淆替换已经安装的程序,以此保证签名不同的包不被替换 2)保证信息传输的完整性 签名对于包中的每个文件进行处理,以此确保包中内容不被替换 3)防止交易中的抵赖发生,Market对软件的要求
  • 37. Android Application Market
  • 38. Android项目 数字签名
  • 39. 签名的说明1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序 2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证 3)如果要正式发布一个Android应用,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布
  • 40. 4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能 5)签名后需使用zipalign优化程序 6)Android将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,而不是用来决定最终用户可以安装哪些应用程序
  • 41. 签名的方法1)用eclipse插件方式签名 a)调试签名 eclipse插件默认赋予程序一个DEBUG权限的签名,此签名的程序不能发布到market上,此签名有效期为一年,如果过期则导致你无法生成apk文件,此时你只要删除debug keystore即可,系统又会为你生成有效期为一年的新签名
  • 42. b)开发者生成密钥并签名 右键点击项目名,在菜单中选择Android Tools,然后选择Export Signed Application Package…,即可通过eclipse自定义证书并签名 c)开发者导出未签名的包,右键点击项目名,在菜单中选择Android Tools,然后选择Export Signed Application Package…,即可导出未签名的包,之后可通过命令行方式签名
  • 43. 2)用命令行方式签名 使用标准的java工具keytool和jarsigner来生成证书和给程序签名 a)生成签名 $ keytool -genkey -keystore keyfile -keyalg RSA -validity 10000 -alias yan 注:validity为天数,keyfile为生成key存放的文件,yan为私钥,RSA为指定的加密算法(可用RSA或DSA)
  • 44. b)为apk文件签名 $ jarsigner -verbose -keystore keyfile -signedjar signed.apk base.apk yan 注:keyfile为生成key存放的文件,signed.apk为签名后的apk,base.apk 为未签名的apk,yan为私钥 c)看某个apk是否经过了签名 $ jarsigner -verify my_application.apk d)优化(签名后需要做对齐优化处理) $ zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk
  • 45. 在源码中编译的签名a)使用源码中的默认签名 在源码中编译一般都使用默认签名的,在某源码目录中用运行 $ mm showcommands能看到签名命令 Android提供了签名的程序signapk.jar,用法如下:
  • 46. Android签名密钥种类$ signapk publickey.x509[.pem] privatekey.pk8 input.jar output.jar *.x509.pem为x509格式公钥,pk8为私钥 build/target/product/security目录中有四组默认签名可选: testkey, platform, shared, media(具体见README.txt),应用程序中Android.mk中 有一个LOCAL_CERTIFICATE字段,由它指定用哪个key签名,未指定的默认用testkey.
  • 47. b)在源码中自签名 Android提供了一个脚本mkkey.sh(build/target/product/security/mkkey.sh),用于生成密钥,生成后在应用程序中通过Android.mk中的 LOCAL_CERTIFICATE字段指名用哪个签名
  • 48. c)mkkey.sh介绍 i.生成公钥 openssl genrsa -3 -out testkey.pem 2048 其中-3是算法的参数,2048是密钥长度,testkey.pem 是输出的文件 ii.转成x509格式(含作者有效期等) openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 -subj ‘/C=US/ST=California/L=Mountain
  • 49. iii.生成私钥 openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt 把的格式转换成PKCS #8,这里指定了-nocryp,表示不加密,所以签名时不用输入密码
  • 50. 签名的相关问题一般在安装时提示出错:INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES 1)两个应用,名字相同,签名不同 2)升级时前一版本签名,后一版本没签名 3)升级时前一版本为DEBUG签名,后一个为自定义签名
  • 51. 4)升级时前一版本为Android源码中的签名,后一个为DEBUG签名或自定义签名 5)安装未签名的程序 6)安装升级已过有效期的程序
  • 52. 相关工具1)查看某个x509证书的的有效日期 在SignApk.java中打印出publicKey.getNotAfter()即可
  • 53. API参考文档的使用
  • 54. Android API参考文档参考文档的内容: 包的索引 类的索引 包(Package)的内容: Interfaces Classes Enums Exceptions
  • 55. 类(Class)中包含的内容: 扩展和实现的内容 按包名的继承关系(可用于反找包) Overview(概览) XML Attributes(XML的属性) Constants(常量) Constructors(构造函数) Methods(方法) Android API参考文档
  • 56. Activity类的帮助信息:public class Activity extends ContextThemeWrapper implements ComponentCallbacks KeyEvent.Callback LayoutInflater.Factory View.OnCreateContextMenuListener Window.Callback java.lang.Object ↳ android.content.Context ↳ android.content.ContextWrapper ↳ android.view.ContextThemeWrapper ↳ android.app.Activity Known Direct Subclasses ActivityGroup, AliasActivity, ExpandableListActivity, ListActivity Known Indirect Subclasses LauncherActivity, PreferenceActivity, TabActivityAndroid API参考文档
  • 57. public class:表示只是一个公开的类; extends [……]: 标明了这个类继承的父类(Java不支持多继承,因此每个类只有一个唯一的父类),后面的内容表示这个类从祖先开始继承的关系。这里的类使用的是包含了其所在包名称的全名,因此在这里可以得知类及其祖先类属于哪个包; Implements [……]: 标明了这个类实现的接口(可以有多个); Known Direct Subclasses [……]:这个类的直接继承者; Known Indirect Subclasses [……]:这个类的间接继承者。 Android API参考文档
  • 58. 主配置文件 AndroidManifest
  • 59. 重要包的描述Android.app :提供高层的程序模型、提供基本的运行环境 Android.content :包含各种的对设备上的数据进行访问和发布的类 Android.database :通过内容提供者浏览和操作数据库 Android.graphics :底层的图形库,可以将它们直接绘制到屏幕上. Android.location :定位和相关服务的类 Android.media :提供一些类管理多种音频、视频的媒体接口 Android.net :提供帮助网络访问的类,超过通常的java.net.* 接口 Android.os :提供了系统服务、消息传输、IPC 机制 Android.opengl :提供OpenGL 的工具 Android.provider :提供类访问Android 的内容提供者 Android.telephony :提供与拨打电话相关的API 交互 Android.view :提供基础的用户界面接口框架 Android.util :涉及工具性的方法,例如时间日期的操作 Android.webkit :默认浏览器操作接口 Android.widget :各种UI 元素(大部分可见)在应用程序的屏幕中使用
  • 60. android的AndroidManifest.xml文件AndroidManifest.xml是每一个应用都需要的文件, 位于应用根目录下,它描述了程序包的全局变量, 包括暴露的应用组件(activities, services等等)和每个组件的实现类,什么样的数据可以操作,以及在什么地方运行。 主要包括以下各个元素。 包名(package):指定本应用内java主程序包的包名。当没有指定apk的文件名时,编译后产生程序包将以此命名。本包名应当在Android系统运行时唯一。 认证(certificate):指定本应用程序所授予的信任级别,目前有的认证级别有platform(system)、shared、media以及应用自定义的认证。不同的认证可以享受不同的权限。
  • 61. android的AndroidManifest.xml文件权限组(permission-group):权限组的定义是为了描述一组具有共同特性的权限。 权限(permission):权限用来描述是否拥有做某件事的权力。Android系统中权限是分级的,共分为普通级别(Normal),危险级别(dangerous),签名级别(signature)和系统/签名级别(signature or system)。 系统中所有预定义的权限根据作用的不同,分别属于不同的级别。对于普通和危险级别的权限,我们称之为低级权限,应用申请即授予。其他两级权限,我们称之为高级权限或系统权限,应用拥有platform级别的认证才能申请。当应用试图在没有权限的情况下做受限操作,应用将被系统杀掉以警示。 权限树(permission-tree)权限树的设置是为了统一管理一组权限,声明于该树下的权限所有者归属该应用。系统提供了API,应用可以在运行时动态添加。 PackageManager.addPermission() 使用权限(uses-permission):应用需要的权限应当在此处申请,所申请的权限应当被系统或某个应用所定义,否则视为无效申请。同时使用权限的申请需要遵循权限授予条件,非platform认证的应用无法申请高级权限。
  • 62. android的AndroidManifest.xml文件SDK(uses-sdk):标识本应用运行的SDK版本。高兼容性的应用可以忽略此项。 application:application是Android应用内最高级别(top level)的模块,每个应用内最多只能有一个application,如果应用没有指定该模块,一个默认的application将被启用。application将在应用启动时最先被加载,并存活在应用的整个运行时生命周期。因此一些初始化的工作适合在本模块完成. Application元素有许多属性,其中:“persistent”表示本应用是否为常驻内存,“enable”表示本应用当前是否应当被加载。
  • 63. android的AndroidManifest.xml文件在AndroidManifest.xml文件中,运行时模块的定义都作为本模块的子元素。当运行时模块被调度时,如果应用没有启动,将首先启动应用进行初始化,然后调度对应模块。 activity:activity是application模块的运行时子元素,标识了一个UI。除了application,一个应用可以声明并实现零至多个其它运行时模块,activity也同样。activity也包含了许多定义它工作状态的属性,其中:“name”是必须的,它指定了该activity所在的文件名,如果该文件所属包不同于该应用的包名(即本描述文件的最开始处),那么名字前面需要加入所在包名。activity通过增加intent-fliter来标识哪些intent可以被处理,同时intent也是调度activity的主要参数。 receiver:receiver也是application的运行时子元素。receiver通过增加intent-fliter来标识它需要接受哪些intent。当收到intent后,receiver将根据不同的intent进行不同的处理。当一个Intent发出后,所有注册了该intent的receiver都将会收到,系统会根据receiver在系统中的注册次序顺序发送。当一个receiver处理完该Intent后,系统才会向下一个receiver发送。当一个receiver有多个未接收的intent时,将按照intent发送的次序顺序接收。
  • 64. android的AndroidManifest.xml文件例,intent-filter如下: service:service也是application的运行时子元素。Service属于后台模块,启动后将长时间运行,除非停止该service或所在应用进程被杀死。 provider:provider也是application的运行时子元素。它继承于ContentProvider,是对该应用管理的用户数据的结构化接入,是基于数据库操作方式的封装。如果应用允许外部应用访问/管理它的用户数据,provider是Android平台提供的最佳方式。 activity-alias:顾名思义,是已有activity的别名。 uses-library:标识应用启动所必须的共享库。
  • 65. AndroidManifest.xml 的结构大纲 文件根节点, 描述了程序包的所有内容. 请求一个安全授权, 必须被授予该权限, 您的程序包才能正确的操作. 0~N 声明一个安全授权, 用来限制哪些应用可以访问您的程序包内的组件和特有机制. 0~N 描述程序包内应用级别组件的根节点. 该节点能够描述应用程序的全局(和/或)默认属性, 例如标签, 图标, 主题, 需要的授权, 等等.包含零个或一个这样的节点 Activity 是应用于用户交互的最主要机制. 当一个应用运行的时候, 用户看到的第一个屏幕就是activity, 并且, 用户所使用的其他绝大多数屏幕(界面)也会是 一个IntentReceiver 可以让应用接收到一次数据变化和一次行为发生的通知, 甚至这个应用没有在运行也可以. 同activity 标签一样, 你可以选择包含一个或多个元素 Service 是一个在后台任意时刻都可以运行的组件. 同activity 标签一样, 你可以选择包含一个或多个元素 ContentProvider组件是用来管理数据持久化及数据发布的, 发布的数据可以被其他的应用访问.
  • 66. AndroidManifest.xml 文件详细解释AndroidManifest.xml是每一个应用都需要的文件. 位于应用根目录下, 描述了程序包的一个全局变量, 包括暴露的应用组件(activities, services等等)和为每个组件的实现类, 什么样的数据可以操作, 以及在什么地方运行. 这个文件的一个重要方面(概念)是其中的intent过滤器. 这个过滤器描述了何时何种情况下让activity 启动. 当一个activity(或是操作系统)想要执行一个动作, 例如打开一个Web页或是打开一个联系人选取屏幕, 会创建一个Intent对象. 该对象包含了很多的描述信息, 描述了你想做什么操作, 你想处理什么数据, 数据的类型, 以及一些其他的重要信息. Android拿这个Intent的信息与所有应用暴露的intent过滤器比较, 找到一个最能恰当处理请求者要求的数据和action的activity. intents的更多信息在Intent页. 另外还要声明您的应用的Activities, Content Providers, Services, 和 Intent Receivers, 你也可以在AndroidManifest.xml文件中指定权限和instrumentation(安全控制和测试). xmlns:android 属性是 XML 名空间声明语句,用来告诉 Android 工具将使用 Android 名空间中定义的公共属性。每个 Android 布局文件的最外层的标签必须有该属性。 在manifest中,定义多个activity时,系统在启动这个application时,该如何判断哪个activity是入口activity。经过测试发现,在manifest中定义的activity中,如果该activity的action是MAIN属性,并且category 是LAUNCHER属性,那么该activity就是入口程序。如果manifest中有多个这样情况的activity存在,那么系统会将第一个查找到的符合条件的activity作为入口程序。manifest中至少应该有一个复合该条件的activity存在。
  • 67. 一个AndroidManifest.xml文件的例子
  • 68. 总结AndroidManifest.xml是每一个应用都需要的文件, 位于应用根目录下,它描述了程序包的全局变量, 包括暴露的应用组件(activities, services等等)和每个组件的实现类,什么样的数据可以操作,以及在什么地方运行;