原文链接:http://blog.csdn.net/duqiuke/article/details/7648865
一、四大组件的详细介绍:
活动(Activity)
1.1Activity的创建
1.1.1定义Activity
定义类继承Activity
在AndroidManifest.xml的<application>节点中声明<activity>
1.1.2显式意图创建方式
Ÿ 构造函数,代码少
new Intent(this, NewActivity.class);
Ÿ 类名形式,灵活,可扩展性强
intent.setClassName(this, "com.it.activity.NewActivity");
Ÿ 包名类名形式,可启动其他程序中的Activity
intent.setClassName("com.it.downloader","com.itt.downloader.MainActivity");
1.1.2隐式意图创建Activity
Ÿ 显式意图是指在创建意图时指定了组件,而隐式意图则不指定组件,通过动作、类型、数据匹配对应的组件
Ÿ 在清单文件中定义<activity>时需要定义<intent-filter>才能被隐式意图启动
Ÿ <intent-filter>中至少配置一个<action>和一个<category>,否则无法被启动
Ÿ Intent对象中设置的action、category、data在<intent-filter>必须全部包含才能启动
Ÿ <intent-filter>中的<action>、<category>、<data>都可以配置多个,Intent对象中不用全部匹配,每样匹配一个即可启动
Ÿ 如果一个意图可以匹配多个Activity,Android系统会提示选择
1.1.3创建Activity并传递数据
Ÿ 在意图对象中封装了一个Bundle对象,可以用来携带数据
Ÿ 在新Activity中可以获得意图对象以获取其中Bundle保存的数据
1.1.4创建Activity获取返回数据
Ÿ 使用startActivityForResult(Intent intent, int requestCode) 方法打开Activity
Ÿ 重写onActivityResult(int requestCode,intresultCode, Intent data) 方法
Ÿ 新Activity中调用setResult(intresultCode, Intent data) 设置返回数据之后,关闭Activity就会调用onActivityResult方法
1.2生命周期
1.2.1Acitivity三种状态
运行:activity在最前端运行
暂停:activity可见,但前端还有其他acti vity,被覆盖一部分,或者前端activity透明
停止:activity不可见,完全被覆盖
1.2.2生命周期相关方法
onCreate:创建时调用,或者程序在暂停、停止状态下被杀死之后重新打开时也会调用
onStart:onCreate之后或者从停止状态恢复时调用
onResume:onStart之后或者从暂停状态恢复时调用,从停止状态恢复时由于调用onStart,也会调用onResume
onPause:进入暂停、停止状态,或者销毁时会调用
onStop:进入停止状态,或者销毁时会调用
onDestroy:销毁时调用
onRestart:从停止状态恢复时调用
1.2.3生命周期:
1.2.4保存信息相关方法
onSaveInstanceState:在Activity被动的摧毁或停止的时候调用,用于保存运行数据,可以将数据存在在Bundle中
onRestoreInstanceState:该方法在Activity被重新绘制的时候调用,例如改变屏幕方向,savedInstanceState为onSaveInstanceState保存的数据
1.3.启动模式
在AndroidManifest.xml中的<activity>标签中可以配置android:launchMode属性,用来控制Actvity的启动模式
在Android系统中我们创建的Acitivity是以栈的形式呈现的:
Ÿ standard:每次调用startActivity()启动时都会创建一个新的Activity放在栈顶,可以重复放以前存在过的Activity,比如:A-B-A….
Ÿ singleTop:如果启动的Activity时,指定Activity不在栈顶就创建,如在栈顶,则不再创建.如果栈顶存放的是A,则不再创建,如果不是A,你插入的Activity是A,则不再重新创建。
Ÿ singleTask:如果启动的Activity不存在就创建,如果存在直接跳转到指定的Activity所在位置。如果这个栈内存在A和B,你要是再插入一个A,则不会创建,而是直接跳转到指定的Activity所在位置。
Ÿ singleInstance:如果启动的Activity不存在就创建,如果存在就将指定的Activity移动到栈顶。经常用,这样可以避免创建一些重复的Activity。
注意
Ÿ 一个Activity通常展现为一个可视化的用户界面。例如,一个activity可能展现为一个用户可以选择的菜单项列表或者展现一些图片以及图片的标题。一个消息服务应用程序可能包含一个显示联系人列表的activity,一个编写信息的activity,以及其它一些查看信息和修改应用程序设置的activity。虽然这些activity一起工作,共同组成了一个应用程序,但每一个activity都是相对独立的。每一个activity都是Activity(android.app.Activity)的子类。
Ÿ 一个应用程序可能只包含一个,或多个activity。一个应用程序包含几个activity以及各个activity完成什么样的功能完全取决于应用程序以及它的设计。通常每个应用程序都包含一个在应用程序启动后第一个展现给用户的activity。在当前展现给用户的activity中启动一个新的activity,可以实现从一个activity转换到另外一个activity。
Ÿ 每个activity都会有一个用于绘制用户界面的窗口。通常这样一个窗口会填充整个屏幕,当然这个窗口也可以比屏幕小并漂浮在其他窗口之上。activity还可以使用一些额外的窗口,例如一个要求用户响应的弹出式对话框,或者是当用户在屏幕上选择一个条目后向用户展现一些重要信息的窗口。
Ÿ 通过调用Activity.setContentView()方法来设置展现activity的窗口的视图。内容视图则是视图层次结构中的根节点视图
Ÿ 展示activity窗口的可视化内容区域是一些具有层次关系(很像数据结构中的树)的视图,而视图则是由类View的子类表示的。每个视图控制窗口中的一个矩形区域。父视图包含一些子视图并管理子视图的布局。位于叶节点的视图直接控制并响应用户的动作。因此视图就是activity与用户交互的接口。例如,一个显示图片的视图,当用户单击的时候它可能会启动一个动作。Android有许多开发人员可以直接使用的视图,包括按钮,文本域,滚动条,菜单,复选框等。
二.内容提供者(ContentProvider)
2.1什么是内容提供者
Ÿ 内容提供者是Android中的四大组件之一,可以将应用中的数据对外进行共享
Ÿ 内容提供者将数据的访问方式统一,不必针对不同数据类型采取不同的访问策略
Ÿ 内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据
Ÿ 内容提供者中数据更改可被监听
2.2创建内容提供者
Ÿ 定义类继承ContentProvider,根据需要重写内部方法
Ÿ 在清单文件的<application>节点下进行配置,<provider>标签中需要指定name和authorities属性
name为类名,包名从程序Package开始,以“.”开始
authorities:是访问Provider时的路径,要唯一
Ÿ URI代表要操作的数据,由scheme、authorites、path三部分组成
content://com.it.provider.it/person
scheme:固定为content,代表访问内容提供者
authorites:<provider>节点中的authorites属性
path:程序定义的路径,可根据业务逻辑定义
2.3完成CRUD方法
Ÿ 当程序调用CRUD方法时会传入Uri
Ÿ 我们通过Uri判断调用者要操作的数据
可以使用工具类UriMatcher来判断Uri
addURI方法可以添加Uri
match方法可以匹配一个Uri判断其类型
Ÿ 根据业务逻辑操作数据
2.4访问内容提供者
Ÿ 通过Context获得ContentResolver对象
Ÿ 调用ContentResolver对象的方法即可访问内容提供者
2.5完成getType方法
Ÿ 如果返回数据是单条数据:vnd.android.cursor.item
Ÿ 如果返回数据是多条数据:vnd.android.cursor.dir
2.6监听内容提供者数据变化
Ÿ 在内容提供者中可以通知其他程序数据发生变化
通过Context的getContentResolver()方法获取ContentResolver
调用其notifyChange()方法发送数据修改通知
Ÿ 在其他程序中可以通过ContentObserver监听数据变化
通过Context的getContentResolver()方法获取ContentResolver
调用其registerContentObserver()方法指定对某个Uri注册ContentObserver
自定义ContentObserver,重写onChange()方法获取数据
2.7监听发送短信
Ÿ Android系统提供了Provider对短信进行查询,当发出短信时也会发送更改通知
Ÿ 定义一个Observer监听"content://sms"
Ÿ 在onChange()方法中查询"content://sms/outbox"
Ÿ 短信发送数据库在 com.android.providers.telephony
Ÿ 需要权限android.permission.READ_SMS
2.8操作联系人
Ø 获取所有联系人
Ÿ Android系统中的联系人也是通过ContentProvider来对外提供数据的
Ÿ 数据库路径为:/data/data/com.android.providers.contacts/database/contacts2.db
Ÿ 我们需要关注的有3张表
raw_contacts:其中保存了联系人id
data:和raw_contacts是多对一的关系,保存了联系人的各项数据
mimetypes:为数据类型
Ÿ Provider的authorites为com.android.contacts
Ÿ 查询raw_contacts表的路径为:contacts
Ÿ 查询data表的路径为:contacts/#/data
这个路径为连接查询,直接查询“mimetype”字段就可以根据“mimetype_id”查询到mimetypes表中的数据
Ÿ 先查询raw_contacts得到每个联系人的id,在使用id从data表中查询对应数据,根据mimetype分类数据
Ø 通过电话号码获取联系人
Ÿ 系统内部提供了根据电话号码获取data表数据的功能,路径为:data/phones/filter/*
Ÿ 用电话号码替换“*”部分就可以查到所需数据,获取“display_name”可以获取到联系人显示名
Ø 添加联系人
Ÿ 先向raw_contacts表插入id,路径为:raw_contacts
Ÿ 得到id之后再向data表插入数据,路径为:data
Ø 使用事务添加联系人
Ÿ 在添加联系人得时候是分多次访问Provider,如果在过程中出现异常,会出现数据不完整的情况,这些操作应该放在一次事务中
Ÿ 使用ContentResolver的applyBatch(String authority,ArrayList<ContentProviderOperation> operations) 方法可以将多个操作在一个事务中执行
注意
应用程序可以通过content provider访问其它应用程序的一些私有数据,这是Android提供的一种标准的共享数据的机制。共享的数据可以是存储在文件系统中、SQLite数据库中或其它的一些媒体中。content provider扩展自ContentProvider类,通过实现此类的一组标准的接口可以使其它应用程序存取由它控制的数据。然而应用程序并不会直接调用ContentProvider中的方法,而是通过类ContentResolver。ContentResolver能够与任何一个ContentProvider通信,它与ContentProvider合作管理进程间的通信。
任何时候当Android系统收到一个需要某个组件进行处理的请求的时候,Android会确保处理此请求的组件的宿主进程是否已经在运行,如果没有,则立即启动这个进程,当请求的组件的宿主进程已经在运行,它会继续查看请求的组件是否可以使用,如果不能立即使用,它会创建一个请求的组件的实例来响应请求。
三.广播接收者(BroadcastReceiver)
3.1定义广播接收者
Ÿ 定义类继承BroadcastReceiver,重写onReceive方法
Ÿ 当接收到匹配广播之后就会执行onReceive方法
Ÿ 清单文件中声明<receiver>,需要在其中配置<intent-filter>指定接收广播的动作和类型
Ÿ BroadcastReceiver除了在清单文件中声明,也可以在代码中声明,使用registerReceiver方法注册Receiver
3.2发送广播
Ø 无序广播
Ÿ 使用sendBroadcast方法发送
Ÿ 被所有广播接收者接收,无序,不可中断
Ÿ 广播时可设置接收者权限,仅当接收者含有权限才能接收
Ÿ 接收者的<receiver>也可设置发送方权限,只接收含有权限应用的广播
Ø 有序广播
Ÿ 使用sendOrderedBroadcast方法发送
Ÿ 接收者可以在<intent-filter>中定义android:priority定义优先级,数字越大优先级越高
Ÿ 被各个广播接收者逐个接收,中途可以中断或者添加数据
abortBroadcast()
getResultExtras(true).putString("data","新增数据");
3.3监听短信接收
Ÿ Android系统在收到短信的时候会发送一条有序广播,我们如果定义一个接收者接收这个广播,就可以得到短信内容,也可以拦截短信
Ÿ 定义广播接收者接收广播android.provider.Telephony.SMS_RECEIVED
Ÿ 在onReceive方法内部调用Intent的getExtras()再调用get(String)获取其中pdus字段,得到一个Object[],其中每一个元素都是一个byte[]
Ÿ 通过SmsMessage类的createFromPdu方法创建SmsMessage对象
Ÿ 从SmsMessage对象中即可获取发送者号码、短信内容、发送时间等信息
Ÿ 需要接收短信权限:<uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>
Ÿ Android系统中收到短信的通知是一个有序通知,我们如需拦截垃圾短信,可以配置较高的priority,收到信息进行判断是否abortBroadcast()
3.4监听呼出电话
Ÿ 定义广播接收者接收 android.intent.action.NEW_OUTGOING_CALL
Ÿ 需要权限 <uses-permissionandroid:name="android.permission.PROCESS_OUTGOING_CALLS"/>
Ÿ 在onReceive方法中使用getResultData() 和 setResultData() 方法获取和设置电话号码
3.5生命周期
Ÿ 广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
Ÿ 广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框
Ÿ 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉
Ÿ 耗时的较长的工作最好放在服务中完成
注意
BroadcastReceiver的使用:broadcase receiver不执行任何任务,仅仅是接受并响应广播通知的一类组件。大部分广播通知是由系统产生的,例如改变时区,电池电量低,用户选择了一幅图片或者用户改变了语言首选项。应用程序同样也可以发送广播通知,例如通知其他应用程序某些数据已经被下载到设备上可以使用。
一个应用程序可以包含任意数量的boradcase reveiver来响应它认为很重要的通知。所有的broadcast receiver都扩展自类BroadcastReceiver。
broadcastreceiver不包含任何用户界面。然而它们可以启动一个activity以响应接受到的信息,或者通过NotificationManager通知用户。可以通过多种方式使用户知道有新的通知产生:闪动背景灯、震动设备、发出声音等等。通常程序会在状态栏上放置一个持久的图标,用户可以打开这个图标并读取通知信息。
通过intentFilter.setPriority(2000);设置广播接收的优先级。
系统级应用的一般在-1000~1000。
当接收到广播之后还可以调用abortBroadcast();将广播中断。
四.服务(Service)
4.1基本概念
Ÿ Service是一种在后台运行,没有界面的组件,由其他组件调用开始。
Ÿ 创建Service,定义类继承Service,AndroidManifest.xml中定义<service>
Ÿ 开启Service,在其他组件中调用startService方法
Ÿ 停止Service,调用stopService方法
4.2电话录音
TelephonyManager manager =(TelephonyManager) getSystemService(TELEPHONY_SERVICE);
manager.listen(new MyListener(),PhoneStateListener.LISTEN_CALL_STATE);
private final class MyListener extends PhoneStateListener {
private Stringnum;
private MediaRecorderrecorder;
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
num = incomingNumber;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
try {
File file = new File(Environment.getExternalStorageDirectory(),num +"_" + System.currentTimeMillis()+".3gp");
recorder = new MediaRecorder();
recorder.setAudioSource(AudioSource.MIC);
recorder.setOutputFormat(OutputFormat.THREE_GPP);
recorder.setAudioEncoder(AudioEncoder.AMR_NB);
recorder.setOutputFile(file.getAbsolutePath());
recorder.prepare();
recorder.start();
} catch (Exception e) {
e.printStackTrace();
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (recorder !=null) {
recorder.stop();
recorder.release();
}
break;
}
}
}
4.3绑定本地服务
Ÿ 使用bindService绑定服务,传入一个自定义的ServiceConnection用来接收IBinder
Ÿ 定义一个业务接口,其中定义需要的使用的方法
Ÿ 服务中自定义一个IBinder继承Binder并实现业务接口,在onBind方法中返回
Ÿ 调用端将IBinder转为接口类型,调用接口中的方法即可调用到服务中的方法
4.4绑定远程服务
Ÿ 远程绑定服务时无法通过同一个接口来调用方法,这时就需要使用AIDL技术
Ÿ 将接口扩展名改为“.aidl”
Ÿ 去掉权限修饰符
Ÿ gen文件夹下会生成同名接口
Ÿ 将服务中自定义的IBinder类改为继承接口中的Stub
Ÿ ServiceConnection中返回的IBinder是代理对象,不能使用强转,改用Stub.asInterface()
4.5AIDL使用自定义类型
Ÿ AIDL默认只能使用Java中基本数据类型和String、List、Map,List和Map中的元素类型也只能是这些类型。
Ÿ 如果需要使用其他类型数据,使用的类必须实现Parcelable接口以完成序列化和反序列化工作
重写 public void writeToParcel(Parcel dest,int flags)
定义 public static finalParcelable.Creator<Person> CREATOR
Ÿ 定义该类对应的AIDL
package 包名
parcelable 类名
Ÿ 在接口AIDL中导入该类,注意:即使是同一个包也需要导入
注意:
service没有用户界面,但它会在后台一直运行。例如,service可能在用户处理其它事情的时候播放背景音乐,或者从网络上获取数据,或者执行一些运算,并把运算结果提供给activity展示给用户。每个service都扩展自类Serivce。
多媒体播放器播放音乐是应用service的一个非常好的例子。多媒体播放器程序可能含有一个或多个activity,用户通过这些activity选择并播放音乐。然而,音乐回放并不需要一个activity来处理,因为用户可能会希望音乐一直播放下去,即使退出了播放器去执行其它程序。为了让音乐一直播放,多媒体播放器activity可能会启动一个service在后台播放音乐。Android系统会使音乐回放service一直运行,即使在启动这个service的activity退出之后。
应用程序可以连接到一个正在运行中的service。当连接到一个service后,可以使用这个service向外暴露的接口与这个service进行通信。对于上面提到的播放音乐的service,这个接口可能允许用户暂停,停止或重新播放音乐。
与activity以及其它组件一样,service同样运行在应用程序进程的主线程中。所以它们不能阻塞其它组件或用户界面,通常需要为这些service派生一个线程执行耗时的任务。
• WINDOW_SERVICE WindowManager 管理打开的窗口程序
• LAYOUT_INFLATER_SERVICE LayoutInflater 取得xml里定义的view
• ACTIVITY_SERVICE ActivityManager 管理应用程序的系统状态
• POWER_SERVICE PowerManger 电源的服务
• ALARM_SERVICE AlarmManager 闹钟的服务
• NOTIFICATION_SERVICE NotificationManager 状态栏的服务
• KEYGUARD_SERVICE KeyguardManager 键盘锁的服务
• LOCATION_SERVICE LocationManager 位置的服务,如GPS
• SEARCH_SERVICE SearchManager 搜索的服务
• VEBRATOR_SERVICE Vebrator 手机震动的服务
• CONNECTIVITY_SERVICE Connectivity 网络连接的服务
• WIFI_SERVICE WifiManager Wi-Fi服务
• TELEPHONY_SERVICE TeleponyManager 电话服务
二、四大组件之间的联系
l Activity:页面清新简洁。良好的即时交互
l Service:负责的数据处理、耗时长
l broadcase receiver:下发通知、响应通知
l Content Provider:实现应用间的数据共享