Android笔记一.深入理解Intent和IntentFilters(一)

时间:2022-03-28 07:00:20
深入理解Intent和IntentFiler(一)

转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空)

    为了比較深刻的理解并灵活使用Intent,我计划将这部分的学习分为两步:一是深入理解Intent基本概念以及其类。二是。通过实例来阐述怎样灵活使用Intent来启动一个组件以及实现组件之间的传递数据。
一、什么是Intent,有什么作用?
    Android的应用程序包含四大组件:Activity、contentProvider、Service、BroadcastReceiver,为了方便不同组件之间的交流通信,应用程序就採用了一种统一的方式启动组件及传递数据,即使用Intent。
           
    Intent封装了Android应用程序须要启动某个组件的"意图"。Intent类的对象是组件间的通信载体。一个Intent对象就是一组信息,其包括接收Intent组件所关心的信息(如action
和 Data)和Android 系统关心的信息(如Category等)。

也就是说,发送"意图"的组件通过Intent对象所包括的内容。来启动指定的(即Component属性)或通过筛选(即Action&Category属性)的某(些)组件,然后实施对应的动作(即Action属性)并传递对应的数据(即Data属性)以便完毕对应的动作。

二、Intent是怎样实现组件间相互调用?

1.Intent实现
     Android笔记一.深入理解Intent和IntentFilters(一)
    上图请求一个Activity组件的简单的实现流程图,算是用的最多的Intent解析实例。
   首先,发出"意图"的组件,通过调用Context.startActivity(intent)開始启动组件:发出"意图"的组件传入已经构好的Intent对象(为一组信息,它决定了是否可以成功的启动还有一个组件);
   然后,调用"动作"实际的执行着Instrumentation对象。它是整个应用激活的Activity管理者。集中负责应用内全部Activity的执行。它有一个隐藏的方法execStartActivity方法。就是负责依据Intent启动Activity。该方法去掉一些细节。它做得最重要的事情,就是将此调用,通过RPC的方式。传递到ActivityManagerService。
   最后,ActivityManagerService会将这些关键信息递交给还有一个服务PackageManagerService,此服务掌握整个软件包及其各组件的信息。它会将传递过来的Intent。与已知的全部Intent
Filters进行匹配(假设带有Component信息,就不用比了)。假设找到了,就把相关Component的信息通知回AcitivityManagerService,在这里。会完毕启动Activity这个非常多细节的事情。

2.Intent匹配

    究竟发出"意图"的组件是怎样找到所需的组件呢?在这里,Intent Filters就開始起作用了。Intent Filters定义在AndroidMainFest.xml文件里。每个Activity都会有一个<Intent
Filters/>元素,它包括了<action/>、<data/>等子元素。当我们的intent对象没有包括Component信息时,这样的"意图"被称之为隐形"意图"。也就是说,"意图"没有指明详细要启动哪个组件以及完毕什么样的动作。

这时我们就须要通过Intent
Filters中的子元素进行信息匹配。从而确定当前包括Intent Filters属性的Activity是不是我们要启动的那个(些)组件。即发送"意图"组件配置好intent对象,被启动组件实现Intent Filters属性,最后。发送组件会依据被启动组件AndroidMainFest.xml中的<Intent
Filters/>信息来确定它是不是目标组件。

Android笔记一.深入理解Intent和IntentFilters(一)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjYzNzUwMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="446" height="215" alt="" style="background-color:inherit; display:inline-block; margin-top:8px; width:446.12500000000006px; height:215px">

三、Intent对象具体解释

  Intent类的对象是组件间的通信载体。利用Intent对象我们能够非常方便的实现不同组件之间的通信。一个Intent对象就是一组信息,这些信息都是通过其Component、Action、Category、Data、Extra和Flag这7种属性体现的。

Intent代表了Android应用的启动"意图"。Android应用将会依据Intent来启动指定组件,至于究竟启动哪个组件,则取决于Intent的属性。

1.Action属性

    Action属性为一个普通的字符串,它代表了该Intent对象要完毕一个什么样的"动作"。当我们为Intent对象指明了一个action时,被启动的组件就会按照这个动作的指示表现出对应的行为。比方查看、拨打、编辑等,须要注意的是一个组件(如Activity)仅仅能有一个action。我们能够方便自己的应用程序组件之间的通信,自己定义action的(字符串)创建新的动作。也能够直接使用Intent类中的静态成员变量。比方ACTION_VIEW,ACTION_PICK,它们是Android中为action属性提前定义的一批action变量。
在设置Intent对象Action属性时,有两种:
(1)自己定义字符串
public final String CUSTOME_ACTION="intent.action.CUSTOME_JIANG";//字符串能够随意
Intent intent=new Intent();
intent.setAction(ActionAttr.CUSTOME_ACTION); //注意:ActionAttr为我们创建的类,也能够使用this.CUSTOME_ACTION
(2)使用系统预定action常量
Intent intent=new Intent();
intent.setAction(Intent.ACTION_CALL); //当中ACTION_CALL为Intent类的静态成员变量,能够类直接调用
//相应字符串"android.intent.action.CALL"

2.Data属性

   Action属性为Intent对象描写叙述了一个"动作",那么Data属性就为Intent对象的Action属性提供了操作的数据。

这里须要注意的是,Data属性仅仅接受一个Uri对象,一个Uri对象通常通过例如以下形式的字符串来表示:

Uri字符串格式:scheme://host:port/path 举例: content://com.android.contacts/contacts/1或tel://18819463209
在设置Intent对象Data属性时能够这样:
Intent intent=new Intent();
String data="content://com.android.contacts/contacts/1";
Uri uri=Uri.parse(data);//将字符串转换为Uri
intent.setData(uri);
或者
Intent intent=new Intent();
intent.setData(Uri.parse("content://com.android.contacts/contacts/1"));

 博主笔记1:action属性和data属性为Intent所传递信息的主要部分,action/data属性举例:
ACTION_VIEW content://contacts/people/1 -- 传递的信息: 显示 号码为1的人相关信息
ACTION_DIAL content://contacts/people/1 -- 传递的信息:给编号为1的人 打 电话
ACTION_VIEW tel:123 -- 传递的信息:将号码123 显示
ACTION_DIAL tel:123 --传递的信息:  拨打 号码123
ACTION_EDIT content://contacts/people/1 -- 传递的信息: 编辑编号为1的联系人
ACTION_VIEW content://contacts/people/ -- 传递的信息:列出显示全部联系人.假设希望在查看某个联系人,须要定义一个新的intent而且属性设置为{
ACTION_VIEW content://contacts/N } 传递到一个新的Activity。
总结:action属性、data属性是intent的主要属性。

3.Catagory属性

    通过Action。配合Data或Type属性能够准确的表达出一个完整的意图了。但为了使的"意图"更加精确,我们也给意图加入一些约束,这个约束由"意图"的Catagory属性实现。一个意图仅仅能指定一个action属性,可是能够加入一个或多个Catagory属性。

Category属性能够自己定义字符串实现。但为了方便不同应用之间的通信还能够设置系统提前定义的Category常量。

调用方法addCategory
用来为Intent 加入一个Category。方法removeCategory 用来移除一个Category;getCategories方法返回已定义的Category。

在设置Intent对象Categoty属性时能够这样:
(1)自己定义字符串
public final String CUSTOME_CATEGORY="intent.action.CUSTOME_CATEGORY";//字符串能够随意
Intent intent=new Intent();
intent.addCategory(ActionAttr.CUSTOME_CATEGORY);
(2)使用系统预定action、category常量
下面代码实现当点击某个button时,通过Intent对象实现返回HOME桌面。 Intent intent=new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);//返回Home桌面

博主笔记2:一般来说Action属性和Category属性都是同一时候使用的。

在Android中,全部应用主Activity(就是单独启动时候。第一个执行的那个Activity...)。都须要能够接受一个Category为 CATEGORY_LAUNCHER,Action为ACTION_Main的意图。

对于发出"意图"的组件。我们能够通过setAction()、addCategory()方法为"意图"加入action属性或者同一时候加入Action、Category属性;对于接收"意图"的组件,在AndroidManifest.xm文件里,我们能够这样设置:

<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".ActionCateAttr"
            android:label="第一个Activity界面" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"
/>            //默认Action
                <category android:name="android.intent.category.LAUNCHER"
/>    //默认Category
            </intent-filter>
        </activity>
     
        <activity
            android:name=".SecondaryActivity"
            android:label="第二个Activity界面" >
            <intent-filter>
                <action android:name="intent.action.JIANG_ACTION" />
                <category android:name="intent.action.JIANG_CATEGORY" />
                <category android:name="android.intent.category.DEFAULT"
/>    //默认Category
            </intent-filter>
        </activity>
凝视:发出"意图"的Activity将Category为 CATEGORY_LAUNCHER,Action为ACTION_Main,接收"意图"的Activity须设置一个默认的Category属性CATEGORY_DEFAULT,这里不能将其设置为CATEGORY_LAUNCHER否者会报错。

另外,假设我们使用了系统提前定义的action常量,则须要在AndroidManifest.xm文件里加入对应的权限,这方面的内容我们将在第二部分讲到。


4.Type属性
   Type属性用于指定该Data所指定Uri相应的MIME类型,这种类型能够是不论什么自己定义的MIME类型。仅仅要符合abc/xyz格式的字符串就可以。这里需要注意的是。Type属性和Data属性通常会出现相互覆盖的情况,假设希望Intent既有Data属性也有Type属性,必须通过setDataAndType()方法来实现。对于Type属性的理解。我记得有篇博文是这样作比方的:说了Data,就必需要提Type,非常多时候,会有人误解,觉着Data和Type的区别,就宛如泡妞和泡马子之间的区别一样,微乎其微。

但事实上不然,Type信息。是用MIME来表示的,比方text/plain。这种东西。

讲到这里。两者区别就非常清晰了,Data就是门牌号,指明了详细的位置。详细问题详细分析。而type,则是强调物以类聚,解决一批量的问题。实际的样例是这种。比方,从某个应用拨打一个电话,会发起的是action为ACTION_DIAL且data为tel:xxx这种Intent。相应的人类语言就是拨打xxx的电话。非常具象。而假设使用type,就宽泛了很多,比方浏览器收到一个未知的MIME类型的数据(比方一个视频...),就会放出这种Intent。求系统的其它应用来帮助,表达成自然语言应该就是:查看pdf类文档,这种。


博主笔记3:MIME类型?

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被訪问的时候,浏览器会自己主动使用指定应用程序来打开。多用于指定一些client自己定义的文件名称。以及一些媒体文件打开方式。

最早的HTTP协议中,并没有附加的数据类型信息,全部传送的数据都被客户程序解释为超文本标记语言HTML
文档,而为了支持多媒体数据类型,HTTP协议中就使用了附加在文档之前的MIME数据类型信息来标识数据类型。

MIME意为多功能Internet邮件扩展,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能依据其类型进行处理。

然而当它被HTTP协议支持之后。它的意义就更为显著了。

它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。每一个MIME类型由两部分组成,前面是数据的大类别,比如声音audio、图象image等,后面定义详细的种类。

常见的MIME类型(通用型):
超文本标记语言文本 .html text/html
xml文档 .xml text/xml
XHTML文档 .xhtml application/xhtml+xml
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
PDF文档 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG图像 .png image/png
GIF图形 .gif image/gif
JPEG图形 .jpeg,.jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG文件 .mpg,.mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar
随意的二进制数据 application/octet-stream

5.Ertras属性

  通过上面的这些项。识别问题,基本完美攻克了,剩下一个重要的问题。就是传參。Extras是用来做这个事情的,它是一个Bundle
类的对象,有一组可序列化的key/value对组成。

每个Action都会有与之相应的key和value类型约定。发起Intent的时候,须要依照要求把Data不能表示的额外參数放入Extras中。

6.Flags属性

   能识别,有输入。整个Intent基本就完整了。但另一些附件的指令,须要放在Flags中带过去。顾名思义,Flags是一个整形数,有一些列的标志
位构成,这些标志,是用来指明执行模式的。

比方,你期望这个意图的执行者,和你执行在两个全然不同的任务中(或说进程也无妨吧...),就须要设置FLAG_ACTIVITY_NEW_TASK 的标志位。

7.Component属性
    通常来说,"意图"可分为显示intent和隐式intent。

Intent Filters它是用来描写叙述一个Activity或 Serveice等组件,我们通过在组件AndroidManifest.xml中<intent-ilters/>元素中加入<action/>等属性。以满足期望可以响应怎么样的Intent,这样的没有指明要启动组件名方式就称之为隐式intent。

当然,我们也可以使"意图"实现启动指定的组件,即称之为显示intent,主要通过Component属性来实现。Intent的Component属性须要接受一个ComponentName对象,这个对实现将要启动指定组件的类名、类所在的包名绑定在intent上。

ComponentName comp=new ComponentName(ComponentAttr.this,SecondaryActivity.class);
Intent intent=new Intent();
intent.setComponent( comp);//设置intent的Component属性,指定"意图"要启动组件的包和类名
凝视:第一句用于创建一个ComponentName对象,来指定包名和类型-这就能够唯一地确定一个组件类。

四、Intent相关类

1.Activity类
   这里我们仅仅需学习使用Intent启动Activity组件将要用的的方法
void
startActivity(Intent intent)
作用:启动Activity,详细启动哪个Activity和怎么样启动由intent属性决定
void
startActivityForResult(Intent
intent, int requestCode)
作用:启动Activity,并返回一个结果。当被启动的Activity退出时。会调用 onActivityResult() 方法并向其传入一个 requestCode參数,这个 requestCode參数为非负数(>0)。作用是标志是哪个Activity组件发出的"意图",须要注意的是假设 requestCode小于0时,这种方法的仅仅能用于启动一个Activity而不能返回值了。

另外,Intent的action属性设为可以返回一个结果,假设设置为 Intent.ACTION_MAIN or Intent.ACTION_VIEW。也是不能获取结果的。

待写:另外还有怎样启动Service、BroadcastReceiver组件的方法,这以后学到了再说吧。
2.Intent类
(1)构造函数

Intent():创建一个空的构造函数
     Intent(Intent o)
    :拷贝构造函数

Intent(String action)
 :创建一个具有acion属性的意图对象

Intent(String action, Uri uri):创建一个带action属性的意图。接受一个Uri对象

Intent(Context packageContext, Class<?

>
cls):创建一个已经指定组件的意图


Intent(String action, Uri uri, Context packageContext, Class<?>
cls)
为一个指定的组件创建一个带action和data属性的意图

(2)经常用法

addCategory(String category)
Add a new category to the intent.
addFlags(int
flags)
Add additional flags to the intent (or with existing flags value).
Retrieve the general action to be performed, such as ACTION_VIEW.
Return the set of all categories in the intent.
Retrieve the concrete component associated with the intent.
Retrieve data this intent is operating on.
Retrieves a map of extended data from the intent.
int
Retrieve any special flags associated with this intent.
static Intent
This method was deprecated in API level 4. Use parseUri(String,
int)
 instead.
Retrieve the application package name this Intent is limited to.
Return the scheme portion of the intent's data.
Return the specific selector associated with this Intent.
Get the bounds of the sender of this intent, in screen coordinates.
Retrieve any explicit MIME type included in the intent.
boolean
hasCategory(String category)
Check if a category exists in the intent.
boolean
Returns true if an extra value is associated with the given name.
static Intent
Create an intent to launch the main (root) activity of a task.
static Intent
makeMainSelectorActivity(String selectorAction, String selectorCategory)
Make an Intent for the main activity of an application, without specifying a specific activity to run but giving a selector to find the
activity.
static Intent
parseIntent(Resources resources, XmlPullParser parser, AttributeSet attrs)
Parses(解析) the "intent" element (and its children) from XML and instantiates an Intent object.
static Intent
parseUri(String uri,
int flags)
Create an intent from a URI.
putExtra(String name,
int value)
Add extended data to the intent.
putExtra(String name, CharSequence value)
Add extended data to the intent.
setAction(String action)
Set the general action to be performed.
Convenience for calling setComponent(ComponentName) with
the name returned by a Class object.
setClassName(Context packageContext, String className)
Convenience for calling setComponent(ComponentName) with
an explicit class name.
setClassName(String packageName, String className)
Convenience for calling setComponent(ComponentName) with
an explicit application package name and class name.
(Usually optional) Explicitly set the component to handle the intent.
setData(Uri data)
Set the data this intent is operating on.
setFlags(int
flags)
Set special flags controlling how this intent is handled.
setPackage(String packageName)
(Usually optional) Set an explicit application package name that limits the components this Intent will resolve to.
void
Set the bounds of the sender of this intent, in screen coordinates.
setType(String type)
Set an explicit MIME data type.
Returns a string containing a concise(简洁), human-readable (可读)description of this object.
toUri(int
flags)
Convert this Intent into a String holding a URI representation of it.

(3)类静态成员变量

    即ACTION、CAYEGORY常量等,由Intent或其对象调用设置intent属性
a.标准Activity Actions
    下面actions常量,用于Intent定义用来操作各种Activity。通常使用 startActivity(Intent)方法实现。

b.标准Broadcast Actions

    下面"意图"的action属性常量,用于接收广播。通常使用 registerReceiver(BroadcastReceiver, IntentFilter)方法或者在AndroidManifest.xml
文件里定义了<receiver>属性的Activity。

c.标准Categories常量

d.标准Extra Data常量

e.Flags

    通过 setFlags(int) 和addFlags(int)设置intent的flags属性。