Android应用结构分析
Android项目必须的文件结构:
|---res
|---values
|---layout
|---drawable-ldpi, drawable-mdpi, drawable-hdpi
|---src
|---存放Java源文件
|---AndroidMainfest.xml
|---bin
|---gen
Res---目录存放着Android项目的各种资源文件,比如layout存放界面布局文件,value目录下存放各种XML格式的资源文件(字符串资源文件String.xml, 颜色资源文件color.xml)
尺寸资源目录:drawable-ldhi(大图片文件), drawable-mdpi(中图片文件), drawable-hdpi(小图片文件)
Src---目录用来保存Java源文件的目录
androidMainfest.xml---文件是android系统的清单文件,控制着android应用的名称、图标、访问权限等整体属性。
Bin---目录用于存放生成的目标文件,如Java二进制文件,Dalvik虚拟机的可执行文件(.dex)
Gen---该目录用于保存Android自动生成的一个清单文件R.java.
R.Java文件说明:
R.java文件是由aapt工具根据应用中的资源文件来自动生成的,因些我们可以把R.java理解成Android应用的资源字典。
aapt生成R.java文件的规则主要是两条:
1、每类资源对应R类的一个内部类。比如:界面的布局资源对应于layout内部类。所有标识符资源对应id内部类。
2、每个具体的资源项对应于内部类的一个public static final int类型的Field(字段)。例如:在界面布局文件中用到了ok,cancel两个标识符,因此R.id类内部就包含了这两个Field;
drawable-xxx文件夹里包含了icon图片,则R.drawable类内部包含了名称为icon的Filed
res目录说明
该目录存放了android应用的全部资源。包括图片资源、字符串资源,颜色资源,尺寸资源等。将不同的资源放在不同的文件夹内,方便的让AAPT工具来扫描这些资源,并为它们生成对应的资源清单类:R.java.
例如:string.xml资源文件中定义一个Hellword的字符串:
<?xml version=”1.0” encode=”utf8”?>
<resources>
<string name=”app_name”>HelloWord</string>
</resources>
上面定义了一个字符串常量,值为:HelloWord,名称为:app_name。android项目允许在java代码、xml文件中使用这个资源文件中定义的字符串资源。
AAPT会为android项目自动生成一份R.java文件,其中每个资源项对应于内部类里的一个int类型的Field。上面的字符串资源对应于R.java里的如下内容:
public static final class string{
//对应一个资源项
public static final int app_name = 0x7f040000;
}
xml文件中使用资源
xml文件中使用资源的格式为:@<资源对应的内部类名>/<资源项的名称>
例如:要访问上面定义的字符串常量”HelloWord”,则使用如下格式:@string/app_name
我们在xml文件中使用标识符时,这些标识符不用使用专门的资源进行定义,直接在xml文档中直接分配标识符即可:@+id/<标识符>
例如:如下代码为一个组件分配标识符:
android:id = “@+id/ok”。接下来我们可以在程序中直接引用该组件。
Android应用的清单文件:AndroidMainfest.xml
androidManifest.xml清单文件是整个android应用的全局描述文件。说明了该应用的名称,所使用图标,以及包含的组件等。通常包含如下信息:
1、 应用程序的包名,该包将会作为该应用的唯一标识。
2、 应用程序所包含的组件,如Activity, Service, BroadcastReceiver和Content Provider等。
3、 应用兼容的最低版本
4、 应用程序使用系统所需的权限声明
5、 其他程序访问该程序所需的权限声明
应用程序权限说明
1、声明该应用自身所拥有的权限:
通过为<manifest../>元素添加<uses-permission../>子元素即可为自身声明权限:
<!---声明该应用本身需要打电话的权限>
<uses-permission android: name=”android.permission.CALL_PHONE”/>
2、声明调用该应用自身所需的权限
通过向应用的各个组件,如<activity../>元素中添加<uses-permission../>子元素即可声明调用该程序所需的权限。例如:在<activity../>元素中添加如下代码:
<!---声明该应用本身需要发送短信的权限--->
<uses-permission android:name = “android.permission.SEND_SMS”/>
Android提供了大量的权限,这些权限都位于Manifest.permission类中。
Activity和View组件介绍
Activity是android中负责与用户交互的组件。Activify是Window的容器,通过Activify的getWindow()方法可以获得所包含的窗口。
Activity为android应用提供了可视化的用户界面,如果该应用包含多个用户界面,则将会包含多个Activity。
多个Activity组成Activity栈,当前活动的Activity位于栈顶。
Activity包含了一个setTheme(int resid)方法来设置其窗口的风格,例如:我们希望窗口不显示标题,以对话框的形式显示,都可以通过该方法实现。
View组件是所有UI控件,容器控件的基类,View组件是与用户交互过程中可以看得到的部分。但是View组件需要放到容器组件中,使用Activity将它显示出来(调用Activity的SetContentView()方法)
//创建一个一个线性布局管理器
LinearLayout layout = new LinearLayout(this);
//设置Activity显示layout
super.setContentView(layout);
LinearLayout对象(它是ViewGroup的子类,ViewGroup又是View的子类)。
setContentView()方法也可以将一个布局管理资源的ID作为参数。例如以下代码:
//设置该Activity显示main.xml文件定义的View
setContentView(R.layout.main);
Service组件介绍
Service与Activity的地位是相同的,区别在于Service通常运行于后台,一般不需要与用户交互。Service组件没有图形用户界面,拥有自已的生命周期。
BroadcastReceiver组件
BroadcastReceiver表示广播消息接收器。类似于事件编程中的监听器。普通事件监听器监听的事件源是程序中的对象。BroadcastReceiver监听的事件源是Android应用中的其他组件。
BroadcastReceiver组件接收广播消息比较简单,只需实现自已的BroadcastReceiver子类,并重写OnReceiver(Context context, Intent intent)方法即可。
实现了自已的BroadcastReceiver之后,需要注册系统级的“事件监听器”。在java代码中通过Context.registReceiver()方法注册;在androidManifest.xml文件中使用<receiver…/>元素完成。
组件发送广播消息的函数为:SendBroadcast()、SendStickyBroadcast()、sendOrderedBroadcast()
ContentProvider组件
对于Android应用而言,它们相互独立,各自运行在自已的Dalvik虚拟机实例中。如果应用之间需要实现数据交换。Android为跨应用的数据交换提供了一个标准:ContentProvider。用户实现自已的ContentProvider时,需要实现如下抽象方法:
Insert(Uri, ContentValues); //向ContentProvider中插入数据
Delete(uri, ContentValues); //删除ContentProvider中指定数据
Update(Uri, ContentValues, string, String[]) //更新ContentProvider中指定数据。
Query(Uri, String[], String, String[], string); //从ContentProvider查询数据
一个应用程序使用ContentProvider来暴露自已的数据,其它的应用程序则通过ContentResolver来访问数据。
Intent和IntentFilter组件
严格来说,Intent和IntentFilter并不是Android应用的组件。它是Android应用程序内不同组件通信的载体。当Android应用运行时需要连接不同的组件时,要借助于Intent来实现。Intent可以启动应用中的另一个Activity,也可以启动一个Service组件,还可以发送一条广播消息来触发系统中的BroadcastReceiver组件。Activity,Service,BroadcastReceiver三种组件之间的通信都以Intent作为载体。
Ö启动一个Activity时,调用Content的StartActivity(Intent intent)方法,方法中的intent参数封装了需要启动的目标Activity的信息。
Ö启动一个Service时,可以调用Context的StartService(Intent intent)方法,或bindService(Intent intent, ServiceConnection conn, int flags);这两个方法中的Intent参数封装了要启动的目标Service相关信息。
Ö触发一个BroadcastReceiver时,可调用Context的senderBroadcast(Intent intent)、sendStickBroadcast(Intent intent)、sendOrderedBroadcast(Intent intent, String receiverPermission)方法来发送广播消息。
当一个组件通过Intent表示了启动或触发另一个组件的“意图”后,这个意图可分为两类:
1、 显示Intent:明确指定需要启动或触发的组件的类名
2、 隐式Intent:只是指定需要启动或触发的组件应满足的条件。
对于显示Intent,Android系统无须对该Intent做任何解析,系统直接找到指定目标组件,启动或触发它即可。
对于隐式Intent, Android系统需要对该Intent进行解析,解析出它的条件,然后去系统中查找与之匹配的组件,进行启动。
Android系统中的被调用组件通过IntentFilter来声明自已所满足的条件,也就是声明自已能处理哪些隐式Intent。
其实通俗一点的理解是显示Intent包含了组件类名等信息,隐式的Intent包含了要查找的目标组件的判断条件。与整型数字与长整型数字的有一点小类似。