赵工的个人空间


专业技术部分转网页计算转业余爱好部分


 手持终端

首页 > 专业技术 > 手持终端 > Android系统的组件通信
Android系统的组件通信

交互,是手机扩展功能所必须的,通过相互之间的交互机制,手机能够支持复杂的应用。Android系统提供了终端用户应用程序之间交互功能的组件,包括广播接收器Broadcast Receiver、意图Intent、适配器Adapters、内容提供器Content Provider。其中Intent是Android的核心组件,它利用消息实现应用程序之间的交互,这种消息描述了应用中一次操作的动作、数据以及附加数据,系统通过该Intent的描述负责找到对应的组件,并将Intent传递给调用的组件,完成组件调用。

1. Intent组成属性:

Intent由动作、数据、分类、类型、组件和扩展信息等内容组成,每个组成都由相应的属性来表示,并提供设置和获取相应属性的方法:

组成

属性

设置属性方法

获取属性方法

动作

Action

setAction()

getAction()

数据

Data

setData()

getData()

分类

Category

addCategory()

 

类型

Type

setType()

getType()

组件

Component

setComponent()
setClass()
setClassName()

getComponent()

扩展信息

Extra

putExtra()

getXxxExtra()获取不同数据类型的数据
getExtras()获取Bundle包

1)Action属性:
Action属性用于描述Intent要完成的动作,是一个描述一类动作的普通字符串,用户可以在应用程序中通过Intent自定义动作字符串来隐式启动某个Activity,或者由其他应用程序定义的动作字符串来启动本应用程序的组件。因为系统是根据此字符串来决定哪个Activity,因此此字符串必须是唯一的。
一个Intent对象最多只能设置一个Action属性,Action要完成的动作可以自定义,也可以指定系统提供的Action。示例:
String COM_SUDA="com.mialab.demo.SUDA_ACTION";
Intent intent=new Intent();
intent.setAction(COM_SUDA);
上述代码设置了Action属性,但该Intent具体启动哪个Activity取决于对应的<intent-filter>元素配置。
Android系统提供了很多Action常量,用来标识系统标准动作,这些系统Action属性常量,分为Activity动作和Broadcast动作两类。

Action常量

对应字符串

描述

ACTION_MAIN

android.intent.action.MAIN

应用程序入口

ACTION_VIEW

android.intent.action.VIEW

显示指定数据

ACTION_EDIT

android.intent.action.EDIT

编辑指定数据

ACTION_GET_CONTENT

android.intent.action.GET_CONTENT

让用户选择数据并返回所选数据

ACTION_DIAL

android.intent.action.DIAL

显示拨号面板

ACTION_CALL

android.intent.action.CALL

直接向指定用户打电话

ACTION_SEND

android.intent.action.SEND

向其他人发送数据

ACTION_SENDTO

android.intent.action.SENDTO

向其他人发送消息

ACTION_ANSWER

android.intent.action.ANSWER

应答电话

ACTION_INSERT

android.intent.action.INSERT

插入数据

ACTION_DELETE

android.intent.action.DELETE

删除数据

ACTION_RUN

android.intent.action.RUN

运行数据

上面是Activity动作,Broadcast动作有:

ACTION_BATTERY_LOW

android.intent.action.BATTERY_LOW

警告设备电量低

ACTION_HEADSET_PLUG

android.intent.action.HEADSET_PLUG

插入或者拔出耳机

ACTION_SCREEN_ON

android.intent.action.SCREEN_ON

打开移动设备屏幕

ACTION_TIMEZONE_CHANGED

android.intent.action.TIMEZONE_CHANGED

时区发生变化

2)Data属性:
Data是用于向Action提供操作的数据,主要描述Intent的动作所操作的数据的URI及MIME类型,setData()接受一个URI对象,而setType()是Data所指定URI对应的MIME类型。不同类型的Action会有不同的Data型数据。
如果为Intent先设置Data属性,后设置Type属性,则Type属性会覆盖Data属性,反之亦然。如果希望同时拥有这两个属性,则可以调用Intent的setDataAndType()方法。示例:
Intent intent=new Intent();
intent.setDataAndType(Uri.parse("content://com.mialab.demo/data"),"abc/xyx");
常用的Data属性常量有:

Data常量

说明

示例

tel://

号码数据格式,后跟电话号码

tel://114

mailto://

邮件数据格式,后跟收件人邮箱地址

mailto://dwen@163.com

smsto://

短信数据格式,后跟短信接收号码

smsto://15915888888

content://

内容数据格式,后跟需要读取的内容

content://contact/person/1

file://

文件数据格式,后跟文件路径

file://sdcard/music.mp3

geo://latitude,longitude

经纬度数据格式,地图上显示所指定的位置

gro://180,65

Action属性和Data属性一般匹配使用,不同的Action由不同的Data数据指定,如:

ACTION属性

DATA属性

描述

ACTION_VIEW

content://contacts/person/1

显示_id为1的联系人信息

ACTION_EDIT

content://contacts/person/1

编辑_id为1的联系人信息

ACTION_VIEW

tel:114

显示电话为114的联系人信息

ACTION_VIEW

http://www.google.com

在浏览器中浏览该网页

ACTION_VIEW

file://sdcard/music.mp3

播放MP3

一些Data属性的含义:

android:host

指定一个有效的主机名

android:mimetype

指定组件能处理的数据类型

android:path

URI路径名

android:scheme

有需要的特定协议

3)Category属性:
Category属性指明一个执行Action的分类。一个Intent对象可以设置多个Category属性,通过调用addCategory()方法来添加属性。常用的Category属性有:

Category属性

描述

CATEGORY_DEFAULT

默认的执行方式,按照普通Activity的执行方式执行

CATEGORY_HOME

该组件为Home Activity

CATEGORY_LAUNCHER

优先级最高的Activity,通常与入口ACTION_MAIN配合使用

CATEGORY_BROWSABLE

可以使用浏览器启动

CATEGORY_GADGET

可以内嵌到另外Activity中

CATEGORY_INFO

提供包信息

4)Component属性:
Component属性用于指明Intent的目标组件名称。通常Android会根据Intent中包含的其他属性的信息(如Action、Data/Type、Category)进行查找,最终找到一个与之匹配的目标组件。但如果指明了Component属性,Intent会根据组件名直接查找到相应的组件,而不再执行上述查找过程。指定Component属性后,Intent的其他属性都是可选的。
根据Intent寻找目标组件时采用的方式不同,可以将Intent分为显式和隐式两类,显式Intent通过指定组件名称Component来实现,隐式Intent通过Intent Filter过滤来实现。
显式Intent通过setComponent()、setClassName()或setClass()设置组件名,如:
Intent intent=new Intent();
intent.setClass(Activity1.this,Activity2.class);
代码中首先产生一个Intent对象,然后利用setClass()方法设置目标组件是Activity2。
5)Extra属性:
Extra属性用于添加一些附加信息,如发送一个邮件,就可以提供Extra属性来添加主题Subject和内容Body。通过使用Intent对象的putExtra()方法来添加附加信息,如:
Intent intent=new Intent();
intent.putExtra("name","dwenzhao");
通过使用Intent对象的getXxxExtra()方法可以获取附加信息,如:
String name=intent.getXxxExtra("name");

2. Intent的启动:

Intent是一种轻量级消息传递机制,描述了应用中某一次操作的动作、动作涉及数据、附加数据,Android则根据此描述找到对应的组件,将Intent传递给待启动的组件并完成该组件的启动。这种消息的传递可以在同一应用程序中不同组件之间,也可以在不同应用程序的组件之间,这类组件主要是Activity、Broadcast、Service。
Android应用程序的三个核心组件Activity、BroadcastReceiver、Service都可通过Intent来启动或激活,Intent提供了不同的启动方法:

核心组件

调用方法

作用

Activity

Context.startActivity()
Activity.startActivityForResult()

启动一个Activity或使一个已存在的Activity去做新的工作

Service

Context.startService()
Context.bindService()

初始化一个Service或传递一个新的操作给当前正在运行的Service;绑定一个已经存在的Service

BroadcastReceiver

Context.sendBroadcast()
Context.sendOrderedBroadcast()
Context.sendStickyBroadcast()

对所有想接收消息的BroadcastReceiver传递消息

包含多个Activity的Android应用程序,可通过startActivity()方法指定相应的Intent对象来启动另外一个Activity。Intent启动Activity分为显示启动和隐式启动两种。
1)显示启动:
显示启动是指一个Activity通过类名明确指明要启动哪个Activity。显示启动Activity需要两个步骤:
⑴创建Intent对象,并初始化指明要启动的Activity,有两种创建方法。
·第一种:
Intent intent=new Intent(A.this,B.class);
·第二种:
ComponentName component=new ComponentName(A.this,B.class);
Intent intent=new Intent();
intent.setComponent(component);
其中,A.this表示当前程序的上下文,B.class表示新启动的Activity所在的类。
⑵启动新的Activity,使用startActivity()或startActivityForResult()方法完成启动。
2)隐式启动:
隐式启动表示不需要指明要启动哪一个Activity,只需要声明一个行为,系统会根据Activity配置,启动能够匹配这个行为的Activity。隐式启动Activity时,系统会自动启动与Intent上的动作Action、附加数据Category以及数据Data相匹配的Activity。
Action用于描述要完成的动作,Category为被执行动作Action增加的附加信息,通常Action与Category结合使用,Data则用于向Action提供操作的数据。Intent隐式启动的步骤:
⑴创建Intent对象:
Intent intent=new Intent();
⑵设置用于匹配的Intent属性,包括动作Action、附加数据Category以及数据Data,分别需要调用不同的方法来设置。
intent.setAction(); //设置动作属性
intent.addCategory(); //设置类别属性
intent.setData(); //设置Data属性
intent.setType(); //设置该Data所指定Uri对应的mimeType属性
⑶调用启动Activity方法启动新的Activity,如startActivity(intent)

3. Intent消息传递:

Intent的Extra属性用于添加一些附加信息,利用该属性可以进行消息传递。将消息存放到Extra属性中有两种方式。
1)直接调用putExtra()方式。该方式是将消息添加到Extra属性中,然后通过调用getXxxExtra()方法进行获取,在数据量比较少的情况下使用。
2)另一种是将数据封装到Bundle包中。Bundle被看作Kay-Value映射的哈希表,当数据量比较多时可以使用Bundle存放数据,然后通过putExtras()方法将Bundle对象添加到Extra属性中,再通过使用getExtras()方法获取存放的Bundle对象,最后读取Bundle包中的数据。
Bundle类常用的方法有:

Bundle方法

功能描述

Object get(String key)

获取关键字key对应的数据

boolean getBoolean(String key)

获取关键字key对应的布尔值,若找不到返回false

boolean getBoolean(String key,boolean defaultValue)

获取关键字key对应的布尔值,若找不到返回defaultValue

Bundle getBundle(String key)

获取关键字key对应的Bundle对象,若找不到返回null

char getChar(String key)

获取关键字key对应的char值,若找不到返回0

char get(String key,char defaultValue)

获取关键字key对应的char值,若找不到返回defaultValue

boolean hasFileDescriptors()

Bundle对象是否包含文件描述符,包含时返回true

void putAll(Bundle map)

插入map到该Bundle对象中

void putBoolean(String key,boolean value)

插入布尔值value到该Bundle对象中,若key存在则替代

void putBundle(String key,Bundle value)

插入Bundle对象value到该Bundle对象中

void putByte(String key,byte value)

插入字节值value到该Bundle对象中

void remove(String key)

移除关键字为key的记录

int size()

获取Bundle对象的关键字个数

当需要传递的数据比较多时,可以通过Bundle传递数据,通过循环遍历将其中的数据取出。

4. Intent Filter:

Intent可以通过显式或隐式方式找到目标组件,隐式方式是通过Intent Filter过滤来实现的。
对于隐式Intent,Android系统需先对其进行解析,通过解析将Intent映射给可以处理该Intent的Activity、Broadcast Receiver或Service。Android应用程序的核心组件都是通过Intent Filter来通告其所具备的能力,即可以处理和响应哪些Intent。
Android提供了两种生成Intent Filter的方式,一种是通过IntentFilter类生成,另一种是通过配置文件AndroidManifest.xml中定义<intent-filter>元素生成的。
1)<intent-filter>元素:
AndroidManifest.xml配置文件中,一个组件可以有多个<intent-filter>元素,每个元素描述不同的能力。示例:
<activity android:name=".Activity1" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
代码中对Activity1进行配置,通过设置<intent-filter>元素的<action>子元素值为android. intent.action.MAIN指明该Activity是应用程序入口,通过设置<category>子元素的值为android.intent.category.LAUNCHER指明该Activity优先级最高。<intent-filter>元素常用<action>、<data>、<category>子元素,分别对应Intent中的Action、Data、Category属性。
一个<intent-filter>中可以添加多个<action>和<category>子元素,且至少需要包含一个<action>子元素和一个<category>子元素,这样系统才能处理Intent消息。
一个<intent-filter>中可以添加多个<data>子元素,用于指定组件可以执行的数据。<data>子元素具有host、scheme、path、port、mimeType等属性,这些属性都是可选的,前4个属性构成一个典型的URI格式scheme://host:port/path;mimeType指定数据的MIME类型,Intent对象和过滤器可以用通配符“*”匹配子类型字段,例如text/*、audio/*。数据检测既要检测URI,也要检测数据类型。示例:
<data android:mimeType="image/*"/>
<data android:scheme="http" android:type="video/*"/>
前一条表示组件能够从内容提供者获取image数据并将其显示,后一种表示组件能够从网络获取视频数据并将其显示。
2)IntentFilter类:
IntentFilter类是另一种实现Intent Filter的方式,常用的方法有:

IntentFilter方法

功能描述

addAction(String action)

为IntentFilter添加匹配行为

addCategory(String category)

为IntentFilter添加匹配类别

addDataAuthority(String host,String port)

获取IntentFilter的数据验证,host和port可使用通配符*

countActions()

计算IntentFilter包含的Action数量

countDataAuthority()

计算IntentFilter包含的DataAuthority数量

getDataAuthority(int index)

根据index获取IntentFilter的DataAuthority

getAction(int index)

根据index获取IntentFilter的Action

setPriority(int priority)

设置IntentFilter的优先级,默认优先级为0,值-1000~1000

getPriority()

获取IntentFilter的优先级

hasCategory(String category)

判断category是否在Intent中,若包含返回true

matchCategory(Set<String>category)

基于category匹配IntentFilter,若匹配所有类别返回null,否则返回第一个不匹配的类别名

5. 广播接收Intent:

可以通过使用sendBroadcast()方法在组件之间进行匿名的广播,而Android中可以通过实现广播接收器来监听和响应这些广播Intent。通过广播Intent向监听器通知系统事件或应用程序事件,使应用程序更加开放。Android系统中大量使用广播Intent来广播系统事件,如电池电量、网络连接等。
如果一个Intent需要多个Activity处理,就需要使用广播Intent。实现广播和接收Intent包括4个步骤,注册广播接收器、发送广播、满足条件的广播接收器执行接收方法onReceiver方法、销毁广播接收器。
1)注册接收器:
需要继承BroadcastReceiver,并重写onReceiver方法,然后根据IntentFilter注册广播Intent。Android提供了Java和XML两种注册方法。
⑴Java注册:
创建IntentFilter和Receiver对象,然后在需要的地方调用Context.registerReceiver()进行注册,也可以使用Context.unregisterReceiver()取消注册,代码为:
IntentFilter myfilter=new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
MyReceiver myreceiver=new MyReceiver();
Context.registerReceiver(myreceiver,myfilter);
⑵XML注册:
在AndroidManifest.xml配置文件中的<intent-filter>元素中添加行为,示例代码为:
<receiver android:".MyReceiver">
<intent-filter>
<action android:name="android.provider.Telephone.SMS_RECEIVED"/>
</intent-filter>
</receiver>
2)广播:
Activity的sendBroadcast()、sendOrderBroadcast()和sendStrikyBroadcast()方法广播Intent,满足条件的BroadcastReceiver都会执行onReceiver方法。三种方法的区别是,sendBroadcast()不保证执行顺序;sendOrderBroadcast()按注册时IntentFilter设置的优先级顺序来执行,高优先级的执行优先于低优先级的,且可以阻止继续执行;sendStrikyBroadcast()提供了带粘着功能的Intent。
3)接收:
广播接收器收到广播Intent,对Intent进行判断,如果该接收器满足条件,则执行onReceiver方法。
4)销毁:
广播接收器的onReceiver方法执行完后,其实例就会被销毁。执行onReceiver方法时,Android系统会启动一个程序计时器,如果一定时间内onReceiver方法没有完成,就会被认为没有响应。

6. Activity配置:

Android系统开放了许多底层应用供用户调用,并有自己特殊的调用底层应用的方式,在运行时检查该用户程序是否有权限调用底层应用,设置了Activity许可才能运行相应的应用。这种方式提供了程序使用系统应用的安全性保证。在AndroidManifest.xml中可以配置应用程序的权限。
Android要求所有的组件都必须显式地在AndroidManifest.xml中进行配置,即在配置文件<application>元素的子元素<activity>中进行Activity的配置,代码为:
<activity android:name="" android:icon="" android:label=""
android:exported="" android:launchMode="">
<intent-filter><intent-filter>
<meta-data/>
</activity>
配置Activity需指定以下属性:
·name:实现Activity的类名,必须明确指明类所在的包和类名,如果在<manifest>中明确定义了应用程序的包,即package="org.suda.app",这时name可以简写为“.myactivity”。
·icon:Activity对应的图标,通常和标签一起显示在窗口上,图标文件放置到drawable中
·label:Activity对应的标签,用于帮助用户了解Activity的可读文本标签
·exported:是否允许其他应用程序自动该Activity。如果设置为true,则允许启动;如果为false,则只运行本应用程序或相同用户ID的应用程序启动
·launchMode:指定该Activity的加载模式,该属性支持standard、singleTop、singleTask、singleInstance四种加载模式
同时,<activity>元素还包含两个子元素:
·<intent-filter>:intent过滤器,指定接收者响应Intent需要的类型
·<meta-data>:用于存储预定义数据,供父组件使用

7.启动和关闭Activity:

1)启动Activity:
Activity启动其他Activity有两种方法:
·startActivity(Intent intent)
·startActivityForResult(Intent intent,int requestCode)
前一种,参数intent描述了待启动的Activity的信息,示例:
Intent intent=new Intent(A.this,B.class);
startActivity(intent);
如果需要启动系统级的应用程序,如拨打电话,就需要启动手机中的电话程序:
Intent intent=new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:114"));
startActivity(intent);
后一种,指定请求码requestCode启动Activity,而且程序将会得到新启动Activity的结果,可以凭借重写onActivityResult()方法获取。
2)关闭Activity:
当完成任务,退出窗口时关闭Activity,也有两种方法:
·finish():表示结束当前Activity
·finishActivity(int requestCode):结束以startActivityForResult()方法启动的Activity。
3)使用Bundle在Activity之间交换数据:
通常情况下,Activity之间进行相互调用时需要传递一些数据。Android将数据封装成以键值对(key-value)形式表示的Bundle对象,靠Intent通信,只需要将Bundle数据放入Intent,通过调用Intent对象的方法即可实现数据传递。Intent提供了4种方法来设置传递的数据:
·putExtras(Bundle data):向Intent中放入需要传递的Bundle数据data
·putExtras(String name,Xxx val):向Intent中按key-value对的形式存入数据,Xxx指代各种数据类型的名称,key为name,value为val
·putXxx(String key,Xxx data):向Bundle中放入Int、Long等各种类型的数据,以key-value对的形式存入
·putSerializable(String key,Serializable data):向Bundle中放入一个可序列化的对象
Intent也提供了相应的取出传递过来的数据的方法:
·getExtras():取出Intent所携带的数据
·getXxxExtra(String name):取出Intent中key为name的数据
·getXxx(String key):从Bundle中取出Int、Long等各种数据类型的数据
·getSerializable(String Key,Serializable data):从Bundle中取出一个可序列化的对象
示例:Activity A启动Activity B,并携带name数据传递给Activity B
Intent intent=new Intent(A.this,B.class);
Bundle bundle=new Bundle();
bundle.putString("name","Tom");
intent.putExtras(bundle);
startActivity(intent);
Activity B获取传递过来的数据,相应代码为:
Intent intent=getIntent();
Bundle bundle=intent.getExtras();
String name=bundle.getString("name");
4)调用另一个Activity并返回结果:
如果启动另一个Activity,并希望返回结果给当前的Activity,可使用startActivityForResult()方法来启动Activity,返回的数据也是通过Bundle来进行交换的。
为了获取到被启动的Activity的返回结果,需要执行两个步骤:
⑴当前的Activity要重写onActivityResult(int requestCode,int resultCode,Intent intent)方法,其中requestCode为请求码,判断是哪个请求的结果所触发;resultCode为返回的结果码,判断是哪个Activity返回的结果。
⑵被启动的Activity需要调用setResult(int resultCode,Intent data)方法设置返回结果。


Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659