此处将为大家介绍关于Intent使用的详细内容,并且为您解答有关intent用途的相关问题,此外,我们还将为您介绍关于AndroidgetIntent()返回第一个intent、AndroidInte
此处将为大家介绍关于Intent 使用的详细内容,并且为您解答有关intent用途的相关问题,此外,我们还将为您介绍关于Android getIntent()返回第一个intent、Android Intent 和 IntentFilter、Android Intents和Intent过滤器(一)、Android Intent与IntentFilter案例详解的有用信息。
本文目录一览:- Intent 使用(intent用途)
- Android getIntent()返回第一个intent
- Android Intent 和 IntentFilter
- Android Intents和Intent过滤器(一)
- Android Intent与IntentFilter案例详解
Intent 使用(intent用途)
Intent用法
1.显示Intent
2.隐式Intent
- 启动活动
<activity>
android:name=".SecondActivity"
android:exported="true">
<intent-filter>
<!-- 自动添加到隐式intent-->
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.example.activitytest.MY_CATEGORY"/>
<action android:name="com.example.activitytest.ACTION_START"/>
</intent-filter>
</activity>
Android getIntent()返回第一个intent
我的类叫DownloadTask.java扩展了AsyncTask.所以在这里我使用onProgressUpdate()方法更新进度,我在其中使用notificationmanager.一切都像魅力一样,除了下载完成后我想点击通知打开特定的视频文件.所以这就是我所做的:
mnotificationmanager = (notificationmanager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); int icon = android.R.drawable.stat_sys_download_done; long when = System.currentTimeMillis(); mNotification = new Notification(icon,"",when); mContentTitle_complete = mContext.getString(R.string.download_complete); notificationIntent = new Intent(mContext,OpenDownloadedVideo.class); notificationIntent.putExtra("fileName",file); mContentIntent = PendingIntent.getActivity(mContext,notificationIntent,0); mNotification.setLatestEventInfo(mContext,file,mContentTitle_complete,mContentIntent); mNotification.flags = Notification.FLAG_AUTO_CANCEL; mnotificationmanager.notify(NOTIFICATION_ID,mNotification);
请注意,在我的情况下,fileName和NOTIFICATION_ID是唯一的.
Activity OpenDownloadedVideo.java通过以下方式打开文件:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { fileName = getIntent().getExtras().getString("fileName"); Intent i = new Intent(Intent.ACTION_VIEW); File videoFiletoPlay = new File(Environment.getExternalStorageDirectory()+"/MyFolder"+"/"+fileName); i.setDataAndType(Uri.fromFile(videoFiletoPlay),"video/*"); startActivity(i); finish(); } catch(Exception e) { // } }
因此,当我第一次下载视频并单击通知时,将打开相应的视频文件.但是,下次当我下载另一个视频,然后单击该通知时,将再次打开下载的第一个文件.
这是因为OpenDownloadedVideo中的getIntent返回创建的第一个Intent而不是最新的Intent.我怎么能纠正这个?
此外,请注意,当我下载多个视频时存在问题场景,例如:如果我下载五个不同的视频文件,状态栏中有五个通知.每次单击通知时都会打开相同的文件.
解决方法
mContentIntent = PendingIntent.getActivity(mContext,PendingIntent.FLAG_UPDATE_CURRENT);
Android Intent 和 IntentFilter

Intent:
Intent 是 Android 不同组件间通信的载体。
显示 Intent:主要根据组件类名来的
显示 IntentFilter:主要根据某些条件来作为触发的条件,通过 IntentFilter 来声明条件
Android Intents和Intent过滤器(一)
Android应用程序有三个核心组件---Activity、Service、Broadcast Receiver,Broadcast receiver是通过叫做Intent的消息来激活的。Intent消息是同一个应用程序或不同应用程序运行后,组件间进行绑定的一种能力。Intent对象本身是一个持有要执行操作的抽象描述的无源数据结构,或者在广播的情况下,经常用它来描述一些已经发生或正在发生的事情。给每种类型组件发送Intent对象都有其独立的机制:1. 为了做某些新的操作,把一个Intent对象传递给Context.startActivity()或Activity.startActivityForResult()方法来启动一个新的Activity或者获取一个既存的Activity。调用startActivityForResult()方法启动的那个Activity也能够把Intent对象传递给Activity.setResult()方法来返回响应的信息。
2. 把一个Intent对象传递给Context.startService()方法来初始化一个服务或给一个正在运行的服务发送新的指令。类似地,也能把Intent对象传递给Context.bindService()方法,在调用组件和目标服务之间建立一个连接,如果服务还没有运行可以选择启动。
3. 传递给广播方法(如,Context.sendBroadcast()、Context.sendOrderedBroadcast()、或Context.sendStickyBroadcast()方法)的任何Intent对象都被发送给所有的感兴趣的广播接收器。广播的许多类型源于系统代码。
在每种情况下,Android系统都会查找对应的Activity、Service或Broadcast Receiver的设置来响应这个Intent对象,如果需要也会实例化这些组件。在这些消息系统内部没有消息重叠:广播的Intent对象仅发送给Broadcast Receiver组件,不会发送给Activity或Service组件。传递给startActivity()方法的Intent对象仅发送给一个Activity,不会发送给一个Service或Broadcast Receiver组件,等等。
本文档开始介绍Intent对象,然后介绍Android使用的把Intent对象映射给组件的规则---Android系统是如何解析那个组件应该接收对应的Intent消息。对于没有明确命名目标组件的Intent对象,这个过程涉及用与潜在的目标关联Intent过滤器来检测Intent对象。
Intent 对象
一个Intent对象就是一个信息包。它包含了接收这个Intent对象的组件感兴趣的信息(如要执行的动作和动作相关的数据)和Android系统感兴趣的信息(如处理这个Intent对象的组件的分类和有关如何启动目标Activity的指令),主要包含以下信息:
组件名
指的是能够处理Intent对象的组件的名字。这个字段是一个ComponentName对象---它是目标组件的完全类名(如:com.example.project.app.FreneticActivity)和组件所在的应用程序的清单文件中设置的包名(如:com.example.project)的组合。组件名的包部分和清单文件中设置的包名不一定一致。
组件名是可选的,如果设置了组件名,Intent对象就会被发送给这个指定类的实例。如果没有设置,Android系统使用Intent对象中的其他信息来定位合适的目标。
组件名是通过setComponent()、setClass()或setClassName()方法来设置,并且通过getComponent()方法来读取。
动作(Action)
指的是一个要执行的动作的命名字符串,在广播Intent对象的情况下,指的是已经发生和正在报告的动作。Intent类定义很多动作常量,详见下表:
常量 |
目标组件 |
动作 |
ACTION_CALL |
Activity |
发起电话呼叫 |
ACTION_EDIT |
Activity |
为用户显示要编辑的数据 |
ACTION_MAIN |
Activity |
作为一个任务的初始Activity启动,没有数据输入和返回输出。 |
ACTION_SYNC |
Activity |
用移动设备上的数据同步服务上的数据。 |
ACTION_BATTERY_LOW |
Broadcast Receiver |
低电量的一个警告 |
ACTION_HEADSET_PLUG |
Broadcast Receiver |
耳麦已经被插入设备,或者从设备上拔出。 |
ACTION_SCREEN_ON |
Broadcast Receiver |
显示屏已经被打开 |
ACTION_TIMEZONE_CHANED |
Broadcast Receiver |
时区相关的设置已经被改变 |
对于一般性动作的预定义常量列表,请看Intent类说明。在Android API的其他地方还定义了一些其他的动作。你也可以在自己的应用程序中给Activity组件定义自己的动作字符串。你创建这些动作应该包含应用程序的包名作为动作前缀---例如:com.example.project.SHOW_COLOR.
动作在很大程度上决定了Intent类的结构---特别是data和extras字段---如一个方法名决定了一组参数和一个返回值。由于这个原因,尽可能的指定使用动作的名字是个好主意,并且要把它们与Intent的其他字段紧密的捆绑在一起。换句话说,就是要给你的组件能够处理的Intent对象定义一个完整的协议,而不是定义一个独立的动作。
Intent对象中的动作是由setAction()方法设定的,并且有getAction()方法读取的。
数据(Data)
指的是动作相关的数据的资源标识和数据的MIME类型。不同的动作要跟不同的数据规范类型配合使用。如果动作字段是ACTION_EDIT,那么数据字段应该包含为编辑而显示的数据的资源标识(URI)。如果动作时ACTION_CALL,那么数据字段就应该是tel:带有呼叫号码的URI。类似地,如果动作时ACTION_VIEW,并且数据字段是http:URI。那么接收Activity就应该下载并显示URI所指向的数据。
在把一个Intent对象分配给一个有处理数据能力的组件时,了解附件在URI中的数据类型是至关重要。例如,能够显示图片的组件不应该被调用来播放音频文件。
很多情况下,从URI中能够推断出数据类型---特别是content:URIs,它指明了设备上数据的位置和控制数据的内容提供器。但是数据类型也能够在Intent对象中明确的设定。setData()方法只能给URI指定数据,setType()方法只能给数据指定MIME类型,setDataAndType()方法同时指定URI的数据和数据的MIME类型。通过getData()方法读取数据,getType()方法获取数据类型。
分类(Category)
指的是包含能够处理这个Intent对象的组件类型的相关信息的字符串。任何类别的分类描述都能够被放在Intent对象中。跟action的动作一样,Intent类也定义几个分类常量,如下表:
常量 |
含义 |
CATEGORY_BROWSABLE |
目标Activity能够安全的调用浏览器来显示链接所指向的数据---如,一张图片或一封电子邮件消息。 |
CATEGORY_GADGET |
Activity能够被嵌入到持有小部件的另一个Activity中 |
CATEGORY_HOME |
Activity显示在主屏幕上,在设备打开时用户看到的第一个屏幕或Home按钮被按下时,用户看到的屏幕。 |
CATEGORY_LAUNCHER |
Activity能够作为任务的初始Activity,并且被列在应用程序启动器的顶层。 |
CATEGORY_PREFERENCER |
目标Activity是一个首选面板。 |
完整的分类列表请看Intent类的说明。
addCategory()方法把一个分类放到一个Intent对象中,removeCategory()方法删除先前添加的分类,getCategories()方法获取当前Intent对象中的所有分类设置。
附加信息(Extras)
它是以Key-value对的形式发送给处理这个Intent对象的组件的附加信息。就像某些数据URIs要跟动作配对一样,某些特殊的附加信息也需要配对。如,一个ACTION_TIMEZONE_CHANGED类型的Intent对象有一个指定新时区的time-zone附加信息,ACTION_HEADSET_PLUG类型的Intent对象有一个指示耳麦当前是插入还拔出状态的附加信息,对于耳麦类型还有一个name的附加信息。如果你创建了一个SHOW_COLOR动作,颜色值应该被设置在一个key-value对的附加信息中。
Intent对象为插入各种类型的附加数据会有一系列的put…()方法,并为读取数据也会有一组类似的get…()方法。这些方法并行于Bundle对象一些方法。实际上,附加信息能够作为一个Bundle对象使用putExtras()和getExtras()方法来安装和读取。
标记(Flags)
Intent对象有各种标记,很多都是用于指示Android系统如何启动Activity(如,Activity应该属于哪个任务),以及启动后如何处理(如,它是否属于最近的Activity列表)。所有这些标记都在Intent类中定义。
Android系统和平台相关的应用都采用Intent对象来发出面向系统的广播和激活系统定义的组件。
原文链接: http://blog.csdn.net/fireofstar/article/details/7330095
Android Intent与IntentFilter案例详解
1. 前言
在Android中有四大组件,这些组件中有三个组件与Intent相关,可见Intent在Android整个生态中的地位高度。Intent是信息的载体,用它可以去请求组件做相应的操作,但是相对于这个功能,Intent本身的结构更值得我们去研究。
2. Intent与组件
Intent促进了组件之间的交互,这对于开发者非常重要,而且它还能做为消息的载体,去指导组件做出相应的行为,也就是说Intent可以携带数据,传递给Activity/Service/BroadcastReceiver。
- 启动Activity。Activity可以简单的理解为手机屏幕中的一个页面,你可以通过将Intent传入startActivity方法来启动一个Activity的实例,也就是一个页面,同时,Intent也可以携带数据,传递给新的Activity。如果想要获取新建的Activity执行结果,可以通过onActivityResult()方法去启动Activity。
- 启动Service。Service是一个不呈现交互画面的后台执行操作组件,可以通过将Intent穿入startService()方法来启动一个Service来启动服务。
- 传递广播BroadCast。广播是任何应用都可以接收到的消息,通过将Intent传递给 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast()方法,可以将广播传递接收方。
3. Intent类型
在Android中,Intent分为两种类型,显式和隐式。
- 显式Intent,可以通过类名来找到相应的组件,在应用中用显式Intent去启动一个组件,通常是因为我们知道这个组件(Activity或者Service)的名字。如下代码,我们知道具体的Activity的名字,要启动一个新的Activity,下面就是用的显示Intent。
Intent intent = new Intent(context,XXActivity.class); startActivity(intent);
- 隐式Intent,不指定具体的组件,但是它会声明将要执行的操作,从而匹配到相应的组件。最简单的Android中调用系统拨号页面准备打电话的操作,就是隐式Intent。
Intent intent = new Intent(Intent.ACTION_DIAL); Uri data = Uri.parse("tel:" + "135xxxxxxxx"); intent.setData(data); startActivity(intent);
使用显示Intent去启动Activity或者Service的时候,系统将会立即启动Intent对象中指定的组件。
使用隐式Intent的时候,系统通过将Intent对象中的IntentFilter与组件在AndroidManifest.xml或者代码中动态声明的IntentFilter进行比较,从而找到要启动的相应组件。如果组件的IntentFilter与Intent中的IntentFilter正好匹配,系统就会启动该组件,并把Intent传递给它。如果有多个组件同时匹配到了,系统则会弹出一个选择框,让用户选择使用哪个应用去处理这个Intent,比如有时候点击一个网页链接,会弹出多个应用,让用户选择用哪个浏览器去打开该链接,就是这种情况。
IntentFilter通常是定义在AndroidManifest.xml文件中,也可以动态设置,通常是用来声明组件想要接受哪种Intent。例如,你如果为一个Activity设置了IntentFilter,你就可以在应用内或者其他应用中,用特定的隐式Intent来启动这个Activity,如果没有为Activity设置IntentFilter,那么你就只能通过显示Intent来启动这个Activity。
注意,为了确保系统的稳定性,官方建议使用显示Intent来启动Service,同时也不要为Service设置IntentFilter,因为如果使用隐式Intent去启动Service,我们并不知道那些服务会响应Intent,而且由于服务大多是不可见的,我们也不知道那些服务被启动了,这是非常危险的。在Android 5.0(API 21)以后,如果使用隐式的Intent去调用bindService()方法,系统会抛出异常。
4. Intent的属性
Intent作为消息的载体,系统根据它去决定启动哪个具体的组件同时将组件执行中需要的信息传递过去。Intent能够包含的属性有Component、Action、Data、Category、Extras、Flags,关于这些属性的更详细信息可查看这里。
- Component,要启动的组件名称。这个属性是可选的,但它是显式Intent的一个重要属性,设置了这个属性后,该Intent只能被传递给由Component定义的组件。隐式Intent是没有该属性的,系统是根据其他的信息(例如,Action、Data等)来判断该Intent应该传递给哪个组件。这个属性是目标的组件的具体名称(完全限定类名),例如,com.example.DemoActivity。该属性可以通过setComonentName()、setClass()、setClassName()或者Intent的构造函数来设置。
- Action,表明执行操作的字符串。它会影响Intent的其余信息,比如Data、Extras。该属性可以通过setAction()方法或者Intent的构造函数来设置。用户可以自定义这个属性,也可以使用系统中已经有的Action值。下面列出启动Activity时候的一些通用Action属性。
- ACTION_VIEW,当有一些信息需要展示出来,可以设置Intent的Action为这个值,并调用startActivity()方法
- ACTION_SEND,当用户有一些信息需要分享到其他应用,可以设置Intent的Action为这个值,并调用startActivity()方法
- ACTION_DIAL,拨打电话,可以设置Intent的Action为这个值,并调用startActivity()方法
- ACTION_EDIT,编辑某些文件,可以设置Intent的Action为这个值,并调用startActivity()方法
- Data,它是待操作数据的引用URI或者数据MIME类型的URI,它的值通常与Intent的Action有关联。比如,如果设置Action的值为ACTION_EDIT,那么Data的值就必须包含被编辑文档的URI。当我们创建Intent的时候,设置MIME类型非常重要。例如,一个可以显示图片的Activity可能不能播放音频,图片和音频的URI非常类似,如果我们设置了MIME类型,可以帮助系统找到最合适的组件接受Intent。有时候,MIME类型也可以从URI判断出来,例如当Data是一个包含content:字符串的URI时候,可以明确的知道,待处理的数据存在设备中,而且由ContentProvider控制。
- 使用setData()方法设置数据引用的URI,使用setType()方法设置数据的MIME类型,使用setDataAndType()方法同时设置这两个属性。
- 注意:如果想要设置两个的属性,直接用setDataAndType()方法,不要同时调用setData()和setType()方法,因为这两个方法设置的值会相互覆盖
public Intent setData(Uri data) { mData = data; mType = null; return this; } public Intent setType(String type) { mData = null; mType = type; return this; }
- Category,这个属性是对处理该Intent组件信息的补充。它是一个ArraySet类型的容器,所以可以向里面添加任意数量的补充信息,同时,Intent没有设置这个属性不会影响解析组件信息。可以通过addCategory()方法来设置该属性。下面列出一些常用的Category的值。
- CATEGORY_BROWSABLE,设置Category为该值后,在网页上点击图片或链接时,系统会考虑将此目标Activity列入可选列表,供用户选择以打开图片或链接。
- CATEGORY_LAUNCHER,应用启动的初始Activity,这个Activity会被添加到系统启动launcher当中。
以上列出的这些关于Intent的属性(Component、Action、Data、Category)可以帮助系统来确定具体的组件,但是有一些Intent的属性,不会影响到组件的确定。
- Extras,以key-value键值对的形式来存储组件执行操作过程中需要的额外信息,可以调用putExtra()方法来设置该属性,这个方法接受两个参数,一个是key,一个是value。也可以通过实例化一个储存额外信息的Bundle对象,然后调用putExtras()方法将我们实例化的Bundle添加到Intent中。
- Flags,这个属性可以指示系统如何启动一个Activity,以及启动之后如何处理。例如Activity属于哪一个task(参考Activity的四种启动方式)。
5. 显式Intent示例
上文说到,显式Intent是用于启动某个特定的组件(Activity或者Service)的Intent,穿创建显式的Intent的时候需要设置组件名称(Component)属性,其他的属性都是可选属性。
// fileUrl是一个URL字符串,例如 "http://www.example.com/image.png" Intent downloadIntent = new Intent(context, DownloadService.class); downloadIntent.setData(Uri.parse(fileUrl)); startService(downloadIntent);
这里的Intent的构造函数传入了两个参数,context和组件名(Component),调用了startService()方法后,会在当前的应用中启动DownloadService这个服务。
显示Intent中设置的组件名(Component)需要在AndroidManifest.xml进行注册,所以它一般用来启动当前应用内的组件。
6. 隐式Intent示例
隐式Intent比显示的Intent会复杂一些,它既可以启动当前应用内的组件,也可以启动当前应用外的组件。如果当前应用无法处理隐式Intent,但是其他应用中的组件可以处理,那么系统会弹框让用户选择启动哪个应用中的组件。
例如,如果用户有内容想分享给其他应用,就创建一个Intent,将它的Action属性设置为ACTION_SEND,然后将要分享的内容设置到Extras属性中,然后调用startActivity()方法,用户就可以选择将内容分享到哪一个应用。
注意,如果没有任何应用能处理用户发送的隐形Intent,调用组件失败,应用可能会崩溃。调用resolveActivity()方法可以确认是否有Activity能够处理这个Intent,如果返回为非空,那么至少有一个组件能够处理这个Intent,调用startActivity()就很安全了;如果返回的是空(null),那么说明没有组件能够处理这个Intent,这个时候就不应该使用这个隐式的Intent了。
// 要将textMessage信息分享出去 Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage); sendIntent.setType("text/plain"); // 确认是否有组件能够处理这个隐式Intent if (sendIntent.resolveActivity(getPackageManager()) != null) { startActivity(sendIntent); }
调用startActivity()传入一个隐式Intent时候,系统会检查设备中所有的应用,确定哪些应用可以处理这个隐式的Intent(含有startActivity()操作并携带text/plain类型的Intent),如果只有一个应用可以处理这个Intent,那么直接唤起这个应用,并将Intent传给它;如果有多个应用可以处理这个Intent,那么系统会弹出一个选择框,让用户选择唤起哪个应用。
7. 强制唤起选择框
上文说了,如果多个应用可以处理同一个隐式Intent,系统会弹出选择框,让用户选择唤起哪个应用,并设置该应用为默认的打开方式,以后就不会弹出选择框了。如果用户希望以后一直使用该用户处理这个隐式Intent(比如打开网页,用户通常会倾向于使用同一个web浏览器),那么十分方便。
但是如果用户想每一次都用不同的应用去处理这个隐式的Intent的,就应该每次弹出选择框,用户可以在选择框中选择唤起的应用,但是无法设置默认的打开方式。例如,当用户想根据当前的位置将内容分享到不同的应用,所以每次都需要弹出选择框。
用户需要通过Intent.createChooser()创建一个Intent,然后调用startActivity()。
Intent sendIntent = new Intent(Intent.ACTION_SEND); ... // 分享的标题 String title = getResources().getString(R.string.chooser_title); // 创建一个调用选择框的Intent Intent chooser = Intent.createChooser(sendIntent, title); // 确认是否有应用可以处理这个Intent if (sendIntent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); }
8. 接受隐式Intent
想配置你的应用可以处理哪些隐式的Intent,需要在AndroidManifest.xml文件中使用<intent-filter>标签为组件设置一个或者多个过滤器。每一个过滤器基于Action、Data、Category来指定自身可以处理的Intent类型。如果隐式Intent的能够匹配到用户设置的其中一个过滤器,系统才能唤起这个应用相应的组件并将Intent传递给这个组件。
组件应该为为一个它可以处理的操作单独设置一个处理器。例如,相册中的Activity可能有两个过滤器,一个过滤器对应浏览照片的操作,另一个过滤器对应编辑照片的操作。当这个Activity被启动的时候,根据Intent中携带的信息来决定执行哪种操作。
每一个过滤器是在AndroidManifest.xml使用<intent-filter>标签来定义的,嵌套在组件标签中,例如<activity>、<service>标签。在<intent-filter>标签中,用户可以使用一下三个属性中的一个或者多个来指定可以接受的Intent。
- <action>,在这个属性中,声明该组件可以执行的操作。该值必须是关于操作的一个字符串,并不是类常量
- <data>,使用一个或者多个数据URI(scheme、host、port、path等等)和数据的MIME类型来指定接受的数据类型
- <category>,声明接受的Intent类型
Activity组件要接受隐式Intent,它必须有一个<category>属性为CATEGORY_DEFAULT的过滤器,因为startActivity()和startActivityForResult()方法处理Intent时候,默认的认为接受组件有一个<category>属性为CATEGORY_DEFAULT的过滤器。如果一个Activity组件不声明这样一个过滤器,它就接收不到隐式Intent。
例如,以下代码声明了一个Activity组件,这个组件可以处理action属性为ACTION_SEND,数据类型是文本(text/plain)的隐式Intent。
<activity android:name="ShareActivity"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>
用户也可以创建一个包含多个<action>、<data>、<category>标签的过滤器,创建时候仅需要确定该组件能够处理过滤器定义的操作即可。
如果是根据<action>、<data>、<category>标签的组合来处理多个Intent,那么需要为这个组件声明多个过滤器。
系统会以这三个属性将隐式Intent与所有组件声明的过滤器进行对比,如果这三个属性全部能够匹配上,系统才有可能将这个隐式Intent传递给这个组件,因为如果多个应用的组件都能匹配上会弹出选择框,让用户选择一个应用去处理这个隐式Intent。
为了避免无意中启动了其他的Service,所以在应用内,建议一直使用显示的Intent去启动服务,这样就不必再AndroidManifest.xml文件中为Service声明过滤器了。
对于Activity的过滤器,必须在AndroidManifest.xml文件中声明,也可以不声明,直接使用显示Intent唤起Activity组件。
广播接收器的过滤器声明可以在AndroidManifest.xml文件中声明,也可以使用registerReceiver()方法动态注册,使用完毕后,使用unregisterReceiver()方法动态注销。
9. 过滤器声明示例
下面一些过滤器的声明能够帮助你更好的理解。
<activity android:name="MainActivity"> <!-- 该Activity是该应用的启动入口页面,它会被储存在系统的launcher列表中 --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="ShareActivity"> <!-- 该Activity能够处理ACTION_SEND行为且数据类型为text/plain的隐式Intent --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> <!-- 该Activity能够处理ACTION_SEND行为且数据类型是媒体内容的隐式Intent --> <intent-filter> <action android:name="android.intent.action.SEND"/> <action android:name="android.intent.action.SEND_MULTIPLE"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="image/*"/> <data android:mimeType="video/*"/> </intent-filter> </activity>
第一个名为MainActivity的组件,是应用的启动入口页面,当用户点击应用图标,该Activity会被启动。
- android.intent.action.MAIN,表示该Activity是应用的启动入口,且不需要任何Intent携带的数据。
- android.intent.category.LAUNCHER,表示将该Activity的图标设为手机主屏幕上的应用图标,如果它没有图标,就用Application的图标。
第二个名为ShareActivity的组件,能够处理两种隐式Intent,可以接受文本和媒体内容的分享操作,也就是说如果一个隐式Intent能够匹配到任意一个过滤器都可以唤起该Activity。当然,也可以直接通过显示Intent指定启动它。
9. PendingIntent
PendingIntent是对Intent的一种封装。它主要作用在于,让外部的应用执行内部的Intent时候,就好像是在你的应用中还行一样。
通常在以下场景中会使用PendingIntent。
- 当用户点击通知栏时候,才执行的Intent(系统的NotificationManager执行的Intent),详情参考这里
- 当用户操作悬浮在主屏幕中的小工具,才执行的Intent(主屏幕应用执行的Intent),详情参考这里
- 在未来某一个特定时间执行的Intent(系统的AlarmManager执行的Intent)
因为每一个Intent对象都是针对具体的组件类别(Activity/Service/BroadcastReceiver)进行实例化,因此在创建PendingIntent的时候,也要基于相同的因素去实例化,使用以下方法实例化PendingIntent。
- PendingIntent.getActivity(),返回一个适用于Activity组件的PendingIntent
- PendingIntent.getService(),返回一个适用于Service组件的PendingIntent
- PendingIntent.getBroadcast(),返回一个适用于BroadcastReceiver的PendingIntent
当然官方还有一些其他获取PendingIntent对象的方法,不过内部也是使用上面三个方法来获取实例化对象的。
这三个方法都需要当前应用的context,需要封装的Intent,以及一个或者多个该如何使用该Intent的标志(例如,是否可以多次使用该Intent)。
关于Pending的具体使用也不再这里展开,需要了解具体使用的可以查看Notification中PendingIntent的使用和悬浮工具栏中PendingIntent的使用
10. Intent匹配规则
上文中提到了,当发送一个隐式Intent后,系统会将它与设备中的每一个组件的过滤器进行匹配,匹配属性有Action、Category、Data三个,需要这三个属性都匹配成功才能唤起相应的组件。
10.1 Action匹配规则
一个过滤器可以一个Action属性也可以声明多个Action属性。如下:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
隐式Intent中的Action属性,与组件中的某一个过滤器的Action能够匹配(如果一个过滤器声明了多个Action属性,只需要匹配其中一个就行),那么就算是匹配成功。
如果过滤器没有声明Action属性,那么只有没有设置Action属性的隐式Intent才能匹配成功。
10.2 Category匹配规则
一个过滤器可以不声明Category属性也可以声明多个Category属性,如下:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
隐式Intent中声明的Category必须全部能够与某一个过滤器中的Category匹配才算匹配成功。比如说一个Category属性设为CATEGORY_BROWSABLE的隐式Intent也可以通过上面的过滤器,也就是说,过滤器的Category属性内容必须是大于或者等于隐式Intent的Category属性时候,隐式Intent才能匹配成功。
如果一个隐式Intent没有设置Category属性,那么它可以通过任何一个过滤器的Category匹配。
10.3 Data匹配规则
一个过滤器可以不声明Data属性也可以声明多个Data属性,如下:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
每个Data属性都可以指定数据的URI结构和数据MIME类型。URI包括scheme、host、port 和path四个部分,host和port合起来也成authority(host:port)部分。
<scheme>://<host>:<port>/<path>
例如:
content://192.168.0.1:8080/folder/subfolder/etc
在这个URI中,scheme是content,host是192.168.0.1,port是8080,path是folder/subfolder/etc。我们平时使用的网络url就是这种格式。
在URI中,每个组成部分都是可选的,但是有线性的依赖关系
- 如果没有scheme部分,那么host部分会被忽略
- 如果没有host部分,那么port部分会被忽略
- 如果host部分和port部分都没有,那么path部分会被忽略
当进行URI匹配时候,并不是比较全部,而是局部对比,以下是URI匹配规则。
- 如果一个URI仅声明了scheme部分,那么所有拥有与其相同的scheme的URI都会通过匹配,其他部分不做匹配
- 如果一个URI声明了scheme部分和authority部分,那么拥有与其相同scheme和authority的URI才能匹配成功,path部分不做匹配
- 如果一个URI所有的部分都声明了,那么只有所有部分都相同的URI才能匹配成功
注意:path部分可以使用通配符(*),也就是path其中的一部分进行匹配。
Data匹配时候,MIME类型和URI两者都会进行匹配,匹配规则如下:
- 如果过滤器未声明URI和MIME类型,则只有不含URI和MIME类型的隐形Intent才能匹配成功
- 如果过滤器中声明URI但是未声明MIME类型(也不能从URI中分析出MIME类型),则只有URI与过滤器URI相同且不包含IME类型的隐式Intent才能匹配成功
- 如果过滤器声明MIME类型但是未声明URI,只有包含相同MIME类型但是不包含URI的隐式Intent才能匹配成功
- 如果过滤器声明了URI和MIME类型(既可以是直接设置,也可以是从URI分析出来),只有包含相同的URI和MIME类型的隐式Intent才能匹配成功
注意:进行匹配时候必须以过滤器为单位进行匹配,不能跨过滤器匹配。如果一个过滤器声明了多个Action、Category、Data,隐式Intent包含的Action、Category、Data都能在过滤器中匹配到相应的属性即可,也就是说过滤器中声明的属性是大于或者等于Intent中包含的属性,Intent才能匹配成功
11. 其他
系统通过过滤器去匹配Intent,启动相应组件,在PackageManager类中提供了一系列的查询(queryIntentActivities()/queryIntentServices()/queryBroadcastReceivers())方法去查询可以处理某个Intent的组件,也提供了一系列的解析(resolveActivity()/resolveService())方法来确定最佳启动组件。这些方法在某些场景下是非常有用的,也可以帮助我们降低程序crash风险。
12. 思考
上文中对Intent以及IntentFilter进行了详细的讲解,大多都是系统级别的处理过程。但是Intent作为一个官方已经封装好的信息携带者,我们可以用它来做很多事情。比如可以写自己的一套匹配规则,Intent仅仅作为数据携带者,通过它去传递一些信息,实现Fragment/Activity的页面跳转逻辑。关于Intent的使用,我相信还有更多的用处,需要用户一步一步的去探索。
到此这篇关于Android Intent与IntentFilter案例详解的文章就介绍到这了,更多相关Android Intent与IntentFilter内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
- Android 中IntentFilter的匹配规则实例详解
- Android组件间通信--深入理解Intent与IntentFilter
- Android Intent-Filter匹配规则解析
- Android中的Intent Filter匹配规则简介
- Android IntentFilter的匹配规则示例详解
今天关于Intent 使用和intent用途的分享就到这里,希望大家有所收获,若想了解更多关于Android getIntent()返回第一个intent、Android Intent 和 IntentFilter、Android Intents和Intent过滤器(一)、Android Intent与IntentFilter案例详解等相关知识,可以在本站进行查询。
本文标签: