三、Intent 和 Intent过滤器(IntentFilter)

article/2025/10/30 10:40:21

Intent(意图):

    Intent 是一个消息传递对象,是我们要执行操作的一个抽象描述。我们可以使用它在相应的组件中传递消息和请求。下面是它的主要使用场景:

    1. 启动Activity

    通过 startActivity() 或者 startActivityForResult() 。参数 intent 描述了要启动的 activity 以及可以携带希望传递给新 activity 相关的数据。

public void startActivity(Intent intent) {...
}public void startActivityForResult(Intent intent, int requestCode) {startActivityForResult(intent, requestCode, null);
}

    2. 启动服务

    通过 startService() bindService() 分别启动和绑定 Service。同理,参数 Intent 描述了要启动的服务并可以携带我们想要传递的数据。

public ComponentName startService(Intent service) {...
}public boolean bindService(Intent service, ServiceConnection conn, int flags) {...
}

    3. 传递广播

    通过 sendBroadcast() 等发送广播。

 

Intent 类型:

    Intent 分为两种类型:

    a. 显式 Intent:

    通过明确指定被启动对象的组件信息(包括包名和类名)显式的指定要启动的组件。通常,我们会在自己的应用中使用显式 Intent 来启动组件,这是因为我们知道要启动的 Activity 或 Service 的详细包名和类名。例如,我们使用显式 Intent 启动新的Activity 以及启动 Service 在后台下载文件。

    b. 隐式 Intent:

    不明确指定要启动的组件,而是声明要执行的常规操作,通过系统来选择并允许其它应用中的组件处理它。例如,如果我们需要在地图上向用户显示位置,则可以使用隐式 Intent,请求手机中具有此功能的应用在地图上显示指定的位置。

    当我们使用显式 Intent 启动 Activity 或 Service 时,系统将立即启动 Intent 对象中指定的应用组件;当我们使用隐式 Intent 时,Android 系统会通过将隐式 Intent 中的内容与在设备上其它应用的清单文件(AndroidManifest.xml)中声明的 Intent 过滤器(IntentFilter)进行比较,从而找到要启动的相应组件。如果只有一个 IntentFilter 与之相匹配,则系统直接启动该组件,如果有多个 IntentFilter 与之相匹配,则系统会显示一个对话框,然后由用户来选择要启动的组件。

    IntentFilter 是应用清单文件中的一个表达式,它可以指定该组件要接收的 Intent 类型。如下所示:

<activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter>
</activity>

    我们可以通过为 Activity 声明 IntentFilter,让其它应用能够直接通过特定类型的 Intent 来启动该 Activity;如果我们没有为 Activity 声明任何的 IntentFilter 过滤器,则该 Activity 只能通过显式 Intent 来启动。

    上面这幅图为隐式 Intent 如何通过 Android System 传递以启动其它 Activity 的图。分为以下三步:

  1. 1. Activity A 创建包含操作描述的 Intent,并将其传递给 startActivity()。

  2. 2. Android System 搜索所有应用中与该 Intent 匹配的 IntentFilter。

  3. 3. 找到匹配项之后,Android System 通过调用匹配的 Activity(Activity B)的 onCreate() 方法,并将 Intent 作为其参数传递进去,从而启动了该 Activity。

    注意:为了确保应用的安全性,我们在启动 Service 时要使用显式 Intent,并且不要为 Service 声明 IntentFilter。因为我们使用隐式 Intent 来启动 Service 时,无法确定设备上的哪些 Service 将匹配该 Intent,并且我们无法看到哪些 Service 已启动,所以会存在安全隐患。从 Android 5.0(API 级别 21)开始,如果使用隐式 Intent 调用 bindService(),系统会引发异常。

 

构建 Intent:

    Intent 对象携带了 Android 系统用来确定要启动哪个组件的信息(例如组件的名称等)以及可能想要传递给组件的相关数据。

    组件名称(Component):

    要启动的组件名称。这是可选项,但也是构建显式 Intent 的一项重要信息,表示要启动特定的组件。如果没有为 Intent 明确指定组件名称,则 Intent 是隐式的,Android 系统会根据 Intent 相关的其它信息(比如操作(action)、数据(data)、类别(category))决定哪个组件应该接收 Intent。因此,如果我们需要在应用中启动特定的组件(也就是使用显式 Intent),则应指定该组件的名称。

    注意:启动 Service 时,您应始终使用显式 Intent 方式指定好要启动的 Service 名称。否则,我们无法确定哪项服务会响应 Intent,且用户也无法看到哪项 Service 已经启动。

    Intent 的 Component 属性接受一个 ComponentName 对象。使用如下:

    先看一下 ComponentName 对象的构造方法:

// 创建 pkg 所在包下的 cls 类所对应的组件
ComponentName(String pkg, String cls)
// 创建上下文 pkg 所对应的包下所对应的组件
ComponentName(Context pkg, String cls)
// 创建上下文 pkg 所对应的包下的 cls 所对应的组件
ComponentName(Context pkg, Class<?> cls)
// 显式 Intent 的用法
Intent intent = new Intent();//  方法 1
intent.setComponent(new ComponentName("com.cfm.intenttest", "com.cfm.intenttest.SecondActivity"));// 方法 2
intent.setComponent(new ComponentName(FirstActivity.this, "com.cfm.intenttest.SecondActivity"));// 方法 3
intent.setComponent(new ComponentName(FirstActivity.this, SecondActivity.class));Log.d("cfm", intent.getComponent().getPackageName()); // output: cfm: com.cfm.intenttest
Log.d("cfm", intent.getComponent().getClassName());   // output: com.cfm.intenttest.SecondActivity
Log.d("cfm", intent.getComponent().getShortClassName()); // output: .SecondActivity// 方法 4
intent.setClass(FirstActivity.this, SecondActivity.class);// 方法 5
intent.setClassName("com.cfm.intenttest", "com.cfm.intenttest.SecondActivity");// 方法 6
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);

    操作(Action):

    指定要执行的通用操作的字符串。它在很大程度上决定了其余 Intent 的构成,特别是数据和 extra 中包含的内容。

    通常我们都使用 Intent 类或者其它框架定义的操作常量,当然,我们也可以自定义指定自己的操作,以满足相应的 Intent 要求。下面是常见的用于启动 Activity 的操作:

    ACTION_VIEW:

    用于可向用户显示信息的 Activity。

    ACTION_SEND:

    用于可共享数据的 Activity。

    在使用中,我们可以通过 setAction() 或 Intent 构造函数为 Intent 指定操作。

eg:
Intent intent1 = new Intent(Intent.ACTION_SEND);Intent intent2 = new Intent();
intent2.setAction(Intent.ACTION_VIEW);

    注意:一般当我们自定义操作时,通常使用该应用的包名作为前缀:

static final String ACTION_TEST = "com.cfm.intenttest.TEST";

    数据(Data):

    data 的语法如下所示:

<dataandroid:scheme="string"android:host="string"android:port="string"android:path="string"android:pathPattern="string"android:pathPrefix="string"android:mimeType="string"/>

    data 由两部分组成,mimeType URI。mimeType 指媒体类型,比如 image/jpeg、audio/mpeg4-generic 和 video/* 等,可以表示图片、文本、视频等不同的媒体格式,而 URI 中包含的数据就比较多了,下面是 URI 的结构:

<scheme>://<host>:<port>/[<path>]|<pathPrefix>|[<pathPattern>]

eg:

content://com.cfm.test:200/folder/subfolder/etc
http://www.baidu.com:80/search/info

    具体参数分析:

    schemeURI 的模式,比如 http、file、content 等,如果 URI 中没有指定 scheme,那么整个 URI 的其它参数无效,这也意味着 URI 是无效的。

    hostURI 的主机名,比如 www.baidu.com,如果 host 未指定,那么整个 URI 的其它参数也是无效的,这也意味着 URI 是无效的。

    port URI 中的端口号。比如 80,仅当 URI 中指定了 scheme 和 host 参数的时候 port 参数才是有意义的。

    path 表示完整的路径信息。

    pathPattern 也表示完整的路径信息,但是它里面可以包含通配符“*”,“*”表示 0 个或多个任意字符,需要注意的是,由于正则表达式的规范,如果想表示真实的字符串,那么“*”要写成“\\*”,“\”要写成“\\\\”。

    pathPrefix 表示路径的前缀信息。

    一般情况下,提供的数据类型通常是由 Intent 的操作决定。比如:如果操作时 ACTION_EDIT,则数据应包含待编辑文档的 URI。

    在指定数据类型的时候,除了指定 URI 之外,指定 mimeType 往往也很重要。比如,能够显示图像的 Activity 可能无法播放音频格式的文件。因此在我们指定了媒体类型之后,有助于 Android System 找到匹配 Intent 的最佳组件。但有时,mimeType 可以通过 URI 推断出来,比如当 URI 为 content 时,表明数据位于设备中,且由 ContentProvider 控制。

    如果我们仅设置数据 URI 时,可以调用 setData()。如果仅设置 mimeType,则调用 setType()。如果同时设置 URI 和 mimeType,则调用 setDataAndType(),而不能同时调用前面两个方法,具体原因可以看下面源码,因为 setData() 和 setType() 可以相互抵消彼此的值。

public Intent setData(Uri data) {mData = data;mType = null; // 将 mimeType 置为 nullreturn this;
}public Intent setType(String type) {mData = null; // 将 URI 置为 nullmType = type; return this;
}

    类别(Category):

    一个包含应处理的 Intent 组件类型的附加信息的字符串。我们可以将任意数量的类别描述放入一个 Intent 中,但大多数 Intent 均不需要类别。以下是一些常见类别:

    CATEGORY_BROWSABLE:

    目标 Activity 允许通过网络浏览器启动,以显示链接引用的数据,如图像或电子邮件。

    CATEGORY_LAUCHER:

    该 Activity 是任务的初始 Activity,在系统的应用启动器中列出。

    我们可以使用 addCategory() 指定类别。

    上面列出的这些属性(Component、Action、Data、Category)表示 Intent 的既定特征。通过读取这些属性,Android System 能够解析应当启动哪个应用组件。但是,Intent 还可以携带不影响其如何解析为应用组件的信息,如下所示:

    Extra:

    通过键值对的方式,携带相应的数据信息。

    标志:

    在 Intent 类中定义的、充当 Intent 元数据的标志。标志可以指示 Android System 如何启动 Activity(比如 Activity 应属于哪个任务栈等),以及启动之后如何处理。(具体请结合 Activity 启动模式那篇最后的分析)

 

隐式 Intent 的使用:

    通过隐式 Intent 我们可以调用设备上其它能够响应该 Intent 的 Activity。如果我们的应用无法执行该操作而其它应用可以,且您希望用户选取要使用的引用,则使用隐式 Intent 非常有用。

    注意,当设备上没有任何应用能处理我们发送到 startActivity() 的隐式 Intent 时,应用将会崩溃,所以我们在使用隐式 Intent 之前通常会先判断设备上有没有能够响应该 Intent 的 Activity。

eg:

// 创建一个隐式 Intent
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, textMessage);
intent.setType("text/plain");// 先检查有没有能够响应该 intent 的 Activity,然后再调用 startActivity()
if( intent.resolveActivity(getPackageManger()) != null ){startActivity(intent);
}

    这时,如果只有一个应用能够处理该 Intent,则应用将直接被打开;但是如果多个 Activity 能接受 Intent,则系统将显示一个对话框,使用户能够自己选取要使用的应用。

    我们也可以强制调用应用选择器:

    使用 createChooser() 创建 Intent,并将其传递给 startActivity()。

Intent intent = new Intent(Intent.ACTION_SEND);// 应用选择器的标题
String title = getResources().getString(R.string.chooser_title);// 创建一个应用选择器
Intent chooser = Intent.createChooser(intent, title);if( intent.resolveActivity(getPackageManager()) != null ){startActivity(chooser);
}

 

接收隐式 Intent:

    我们可以在 AndroidManifest.xml 文件中使用 <intent-filter> 元素为每个应用组件声明一个或多个 Intent 过滤器。每个 Intent 过滤器均根据 Intent 的操作、数据和类别指定自身接收的 Intent 类型。仅当隐式 Intent 可以匹配 Intent 过滤器的其中一个时,系统才会将该 Intent 传递给应用组件。

    注意:只要明确指定了 Component,按照显式 Intent 启动应用组件,则不需要匹配该应用组件声明的 Intent 过滤器。

eg:
<activity android:name="TestActivity"><intent-filter><action android:name="android.intent.action.SEND"/><category android:name="android.intent.category.DEFAULT"/><data android:mimeType="text/plain"/></intent-filter>
</activity>

    注意:为了接收隐式 Intent,必须将 CATEGORY_DEFAULT 类别包括在 Intent 过滤器中。因为 startActivity() 和 startActivityForResult() 会自动为其 Intent 参数增加 CATEGORY_DEFAULT 类别。如果未在 Intent 过滤器中声明此类别,则隐式 Intent 不会匹配我们的应用组件。

 

限制对组件的访问:

    当我们使用 Intent 过滤器时,无法安全的防止其它应用启动组件。虽然 Intent 过滤器可以将组件限制为仅响应特定类型的隐式 Intent,但是如果开发者知道该组件的具体名称,则依然有可能通过显式 Intent 启动它。所以,为了确保该组件只能该应用可以启动,我们可以将该组件的 exported 属性设置为 false。

    注:对于 Activity,我们只能在清单文件中声明 Intent 过滤器。但是 BroadcastReceiver 的过滤器可以通过调用 registerReceievr() 动态注册,然后通过 unregisterReceiver() 注销该接收器。这样一来,应用便可以仅在应用运行时的某一指定时间段内侦听特定的广播。

 

Intent 过滤器匹配规则:

    1. action 的匹配规则

    action 是一个字符串,系统预定义了一些 action,同时我们也可以在应用中自定义 action。action 的匹配规则是 Intent 中的 action 必须能和过滤器规则中的 action 之一完全匹配(action 区分大小写,所以要一模一样才能匹配成功)。一个 IntentFilter 中可以有多个 action,只要 Intent 中的 action 能够和过滤器规则中的任何一个 action 相同即可匹配成功。需要注意的是,Intent 中如果没有指定 action,那么匹配失败。综上,action 的匹配规则要求 Intent 中的 action 存在且必须和过滤规则中的其中一个 action 完全相同,才算是匹配成功。

    2. category 的匹配规则

    category 也是一个字符串,系统预定义了一些 category,同时我们也可以在应用中自定义 category。category 的匹配规则是如果 Intent 中含有 category,那么必须和过滤器规则中的 category 完全匹配才可以;如果 Intent 中不含有 category,那么过滤器规则中必须包含“android.intent.category.DEFAULT”才能匹配成功,因为当我们使用 startActivity() 或者 startActivityForResult() 时会默认为 Intent 加上 “android.intent.category.DEFAULT”这个 category。(这里要注意区分和 action 的匹配规则不一样)

    3. data 的匹配规则

    data 的匹配规则和 action 的类似,它也要求 Intent 中必须含有 data 数据,并且 data 数据能够完全匹配过滤规则中的某一个 data(同时匹配 URI 和 mimeType)。如果过滤规则中没有指定 URI,默认值为 content 或者 file,所以即使 IntentFilter 中没有指定 data 数据,我们也必须为隐式 Intent 调用 setData( Uri.parse("file://abc") ) 或者 setData( Uri.parse("content://abc") ) 才能匹配。

 

最后补充两个知识点:

    1. 判断设备中是否有 Activity 能够匹配我们的隐式 Intent。有两种方法,一种是前面使用过的通过 Intent 的 resolveActivity() 方法;另一种是通过 PackageManager 的 resolveActivity() 方法。另外 PackageManager 中还提供了 queryIntentActivitys(),它和 resolveActivity() 的区别是后者返回的是最佳匹配的 Activity 信息,而前者返回的是所有成功匹配的 Activity 信息。

// 原型
public abstract ResolveInfo resolveActivity(Intent intent, int flags);
public abstract List<ResolveInfo> queryIntentActivities(Intent intent, int flags);
// 第一个参数是传入的隐式 Intent。// 第二个参数是附加的标志信息。我们常常使用 MATCH_DEFAULT_ONLY。这个标志信息的含义是仅仅匹配那些在 intent-filter 中声明了 <category android:name="android.intent.category.DEFAULT"/> 这个类别的 activity。因为在我们使用 startActivity() 或者 startActivityForResult() 是会默认为 intent 添加这个类别,所以一定程度上就可以减少由于缺少这个类别而导致的启动 activity 异常。

     2. 

<action android:name="android .intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>

    ACTION_MAIN:操作指示这是主要入口点,且不要求输入任何 intent 数据。

    CATEGORY_LAUNCHER:类别指示此 Activity 的图标应放入系统的应用启动器。如果 <activity> 元素中未使用 icon 指定图标,则系统将使用 <application> 元素中的图标。

    这二者匹配使用用来表示这是一个入口 Activity 并且会出现在系统的应用列表中。少了任何一个都没有实际意义,也无法出现在系统的应用列表中,也就是二者缺一不可。


http://chatgpt.dhexx.cn/article/C7g55ZYc.shtml

相关文章

【Android】Intent 和 Intent Filter

一. Intent 简介 Intent 是一个消息传递对象&#xff0c;您可以用来从其他应用组件请求操作。可以用于&#xff1a;启动 Activity、启动服务、传递广播。 https://developer.android.com/guide/components/intents-filtershttps://developer.android.com/guide/components/i…

Android开发——IntentFilter的匹配规则

1. IntentFilter中的过滤信息 启动Activity分为显式调用和隐式调用&#xff0c;前者没什么好讲的&#xff0c;后者需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息。包括action、category、data。 一个Activity中可以有多个IntentFilter&#xff0c;一个Intent…

Android中的Intent和Intent-filter总结

一&#xff0e;相关概念 &#xff08;一&#xff09;基本概念 Intent中文意思指”意图”,按照Android的设计理念,Android使用Intent来封装程序的”调用意图”,不管启动Activity、Service、BroadcastReceiver,Android都使用统一的Intent对象来封装这一”启动意图”。此外,Inten…

【intent-filter】AndroidManifest中<intent-filter>标签的 部分作用

这里写自定义目录标题 AndroidManifest.xmlIntent-filter 标签Intent-filter 标签中的常用元素Intent-filter 标签的作用Intent对象Intent显式启动活动窗口Intent隐式启动&#xff08;重要&#xff09; AndroidManifest.xml AndroidManifest.xml是安卓开发中主配置文件&#x…

IntentFilter功能简介

1.什么是IntentFilter &#xff1f; IntentFilter翻译成中文就是“意图过滤器”&#xff0c;主要用来过滤隐式意图。当用户进行一项操作的时候&#xff0c;Android系统会根据配置的 “意图过滤器” 来寻找可以响应该操作的组件&#xff0c;服务。 例如&#xff1a;当用户点击…

简述 IntentFilter(意图过滤器)

转载自&#xff1a;http://www.cnblogs.com/ywtk/p/4158103.html 侵删 1.什么是IntentFilter &#xff1f; IntentFilter翻译成中文就是“意图过滤器”&#xff0c;主要用来过滤隐式意图。当用户进行一项操作的时候&#xff0c;Android系统会根据配置的 “意图过滤器” 来寻找可…

IntentFilter详解

IntentFilter的意思就是意图过滤器&#xff0c;当我们隐式的启动系统组件的时候&#xff0c;就会根据IntentFilter来筛选出合适的进行启动。 如果组件的 IntentFilter 与 Intent 中的 IntentFilter 正好匹配&#xff0c;系统就会启动该组件&#xff0c;并把 Intent 传递给它。如…

WPF MessageBox简单用法

1、弹出小框 用法&#xff1a; if (MessageBox.Show("内容", "标题", MessageBoxButton.YesNo, MessageBoxImage.Information) MessageBoxResult.Yes){label1.Content "yes";}else{label1.Content "no";} 2、例子 if (MessageBo…

C# winform 中MessageBox用法大全(附效果图)

我们在程序中经常会用到MessageBox。 MessageBox.Show()共有21中重载方法。现将其常见用法总结如下&#xff1a; 1.MessageBox.Show(“Hello~~~~”); 最简单的&#xff0c;只显示提示信息。 2.MessageBox.Show(“There are something wrong!”,“ERROR”); 可以给消息框加上…

MessageBox使用详解

Messagebox是我们编写程序时都会用到的东西&#xff0c;我每次使用的时候都能让它显示出来&#xff0c;但是我并不了解它的结构&#xff0c;或者说语法&#xff0c;下面简单总结一下。 语法 Messagebox(<字符串>text,<字符串>title&#xff0c;messageboxbuttons&a…

C#中Messagebox的简单使用

MessageBox的使用方法比较多&#xff0c;下面对常用的几种做了简单的说明&#xff0c;详细的资料可参考微软官方文档。 Messagebox.Show(String) 显示具有指定文本的消息框。 private void button1_Click(object sender, EventArgs e){//Show(String).显示具有指定文本的消息…

MessageBoxA 和MessageBoxW

文章目录 第一个参数&#xff1a;第二个参数&#xff1a;第三个参数&#xff1a;第四个参数&#xff1a;补充代码实现 MessageBoxA(NULL, text, title, MB_OK) 第一个参数&#xff1a; HWND hWnd 传入一个句柄&#xff0c;这个窗口句柄代表的窗口就是这个消息窗口的所有者&…

C#中MessageBox()用法详解

简介&#xff1a; MessageBox&#xff08;&#xff09;功能是显示一个消息对话框&#xff0c;其中包含一个系统图标、 一组按钮和一个简短的特定于应用程序消息&#xff0c;如状态或错误的信息。 格式&#xff1a; MessageBox.Show&#xff08;string Text, string Caption,…

C/C++ MessageBox() 弹窗的用法

C/C MessageBox 的用法 目录 一、语法 二、头文件 三、常量 图标常量&#xff0c;按钮常量&#xff0c;返回值 四、示范 五、成品 六、通过返回值判断点击的按钮是什么 七、通过输入的文字来改变弹窗上的文字 一、语法 MessageBox(NULL,("对话框内容"),("对话…

MessageBox()函数用法及参数详解

MessageBox函数 显示模式对话框&#xff0c;其中包含系统图标&#xff0c;一组按钮和简要的特定于应用程序的消息&#xff0c;例如状态或错误信息。消息框返回一个整数值&#xff0c;指示用户单击的按钮。 语法 int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCapti…

MessageBox.Show 用法介绍

简介摘要&#xff1a;MessageBox.Show (String) 显示具有指定文本的消息框。 由 .NET Compact Framework 支持。 MessageBox.Show (IWin32Window, String) 在指定对象的前面显示具有指定文本的消息框。 MessageBox.Show (String) 显示具有指定文本的消息框。 由 .NET Compac…

C# MessageBox用法大全

C#中MessageBox用法大全&#xff08;附效果图&#xff09; 我们在程序中经常会用到MessageBox。 MessageBox.Show()共有21中重载方法。现将其常见用法总结如下&#xff1a; 1.MessageBox.Show("Hello~~~~"); 最简单的&#xff0c;只显示提示信息。 2.MessageBox.S…

MessageBox 用法详解与实例

摘自&#xff1a;教育网-自学之路&#xff1a;http://www.selfroad.com.cn/content.asp?id83 MessageBox这个函数可以在VC里面显示一个标准对话框&#xff0c;是比较常用的一个信息对话框&#xff0c;其不仅能够定义显示的信息内容、信息提示图标&#xff0c;而且可以定义按钮…

MessageBox()用法简介

MessageBox () 功能显示一个消息对话框。 语法 MessageBox (text,title{,icon{,button{,default}}}) 参数title&#xff1a;string类型&#xff0c;指定消息对话框的标题text&#xff1a;指定消息对话框中显示的消息&#xff0c;该参数可以是数值数据类型、字符串或boolean值…

C#中MessageBox用法大全(附效果图)

C#中MessageBox用法大全&#xff08;附效果图&#xff09; 我们在程序中经常会用到MessageBox。 MessageBox.Show()共有21中重载方法。现将其常见用法总结如下&#xff1a; 1.MessageBox.Show("Hello~~~~"); 最简单的&#xff0c;只显示提示信息。 2.MessageBox.S…