什么是Intent
java
Intent是一种运行时绑定(run-time binding)机制,它能在程序运行过程当中链接两个不一样的组件。经过Intent,你的程序能够向Android表达某种请求或者意愿,Android会根据意愿的内容选择适当的组件来完成请求。好比,有一个Activity但愿打开网页浏览器查看某一网页的内容,那么这个Activity只须要发出WEB_SEARCH_ACTION给Android,Android就会根据Intent的请求内容,查询各组件注册时声明的IntentFilter,找到网页浏览器的Activity来浏览网页。android
Android的三个基本组件——Activity,Service和Broadcast Receiver——都是经过Intent机制激活的,不一样类型的组件有不一样的传递Intent方式:数据库
要激活一个新的Activity,或者让一个现有的Activity作新的操做,能够经过调用Context.startActivity()或者Activity.startActivityForResult()方法。浏览器
要启动一个新的Service,或者向一个已有的Service传递新的指令,调用Context.startService()方法或者调用Context.bindService()方法将调用此方法的上下文对象与Service绑定。服务器
Context.sendBroadcast()、Context.sendOrderBroadcast()、Context.sendStickBroadcast()这三个方法能够发送Broadcast Intent。发送以后,全部已注册的而且拥有与之相匹配IntentFilter的BroadcastReceiver就会被激活。app
Intent一旦发出,Android都会准确找到相匹配的一个或多个Activity,Service或者BroadcastReceiver做响应。因此,不一样类型的Intent消息不会出现重叠,即Broadcast的Intent消息只会发送给BroadcastReceiver,而决不会发送给Activity或者Service。由startActivity()传递的消息也只会发给Activity,由startService()传递的Intent只会发送给Service。
ide
Intent的构成
函数
要在不一样的activity之间传递数据,就要在intent中包含相应的内容,通常来讲数据中最基本的应该包括:
工具
Action:用来指明要实施的动做是什么,好比说ACTION_VIEW, ACTION_EDIT等。具体的能够查阅android SDK-> reference中的Android.content.intent类,里面的constants中定义了全部的action。
一些经常使用的Action:
ACTION_CALL activity 启动一个电话.
ACTION_EDIT activity 显示用户编辑的数据.
ACTION_MAIN activity 做为Task中第一个Activity启动
ACTION_SYNC activity 同步手机与数据服务器上的数据.
ACTION_BATTERY_LOW broadcast receiver 电池电量太低警告.
ACTION_HEADSET_PLUG broadcast receiver 插拔耳机警告
ACTION_SCREEN_ON broadcast receiver 屏幕变亮警告.
ACTION_TIMEZONE_CHANGED broadcast receiver 改变时区警告.
ui
Data: 要事实的具体的数据,通常由一个Uri变量来表示
简单的Action,Data的例子:
[java] view plaincopy
Uri uri = Uri.parse("http://www.google.com");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
Category:一个字符串,包含了关于处理该intent的组件的种类的信息。一个intent对象能够有任意个category。intent类定义了许多category常数:
CATEGORY_BROWSABLE 目标activity可使用浏览器来显示-例如图片或电子邮件消息
CATEGORY_GADGET 该activity能够被包含在另一个装载小工具的activity中
CATEGORY_HOME 该activity显示主屏幕,也就是用户按下Home键看到的界面
CATEGORY_LAUNCHER 该activity能够做为一个Task的第一个activity,而且列在应用程序启动器中
CATEGORY_PREFERENCE 该activity是一个选项面板
addCategory()方法为一个intent对象增长一个category,
removeCategory删除一个category,
getCategories()获取intent全部的category.
Type:显式指定Intent的数据类型(MIME)(多用途互联网邮件扩展,Multipurpose Internet Mail Extensions)。好比,一个组件是能够显示图片数据的而不能播放声音文件。不少状况下,data类型可在URI中找到,好比content:开头的URI,代表数据由设备上的content provider提供。可是经过设置这个属性,能够强制采用显式指定的类型而再也不进行推导。
component:指定Intent的目标组件的类名称。一般 Android会根据Intent 中包含的其它属性的信息,好比action、data/type、category进行查找,最终找到一个与之匹配的目标组件。可是,若是 component这个属性有指定的话,将直接使用它指定的组件,而再也不执行上述查找过程。指定了这个属性之后,Intent的其它全部属性都是可选的。例如:
[java] view plaincopy
Intent it = new Intent(Activity.Main.this, Activity2.class);
startActivity(it);
extras:附加信息,例如ACTION_TIMEZONE_CHANGED的intent有一个"time-zone"附加信息来指明新的时区,而ACTION_HEADSET_PLUG有一个“state”附加信息来指示耳机是被插入仍是被拔出。intent对象有一系列put...()和set...()方法来设定和获取附加信息。 这些方法和Bundle对象很像。事实上附加信息可使用putExtras()和getExtras()做为Bundle来读和写。例如:
[java] view plaincopy
//用Bundle传递数据
Intent it = new Intent(Activity.Main.this, Activity2.class);
Bundle bundle=new Bundle();
bundle.putString("name", "This is from MainActivity!"); it.putExtras(bundle);
startActivity(it);
//得到数据
Bundle bundle=getIntent().getExtras();
String name=bundle.getString("name");
intent的解析
在应用中,咱们能够以两种形式来使用Intent:
直接Intent(或名显示intent):指定了component属性的Intent(调用setComponent(ComponentName)或者setClass(Context, Class)来指定)。经过指定具体的组件类,通知应用启动对应的组件。
间接Intent(或名隐式intent):没有指定comonent属性的Intent。这些Intent须要包含足够的信息,这样系统才能根据这些信息,在在全部的可用组件中,肯定知足此Intent的组件。
对于直接Intent,Android不须要去作解析,由于目标组件已经很明确,Android须要解析的是那些间接Intent,经过解析将 Intent映射给能够处理此Intent的Activity、Service或Broadcast Receiver。
Intent解析机制主要是经过查找已注册在AndroidManifest.xml中的全部<intent-filter>及其中定义的Intent,经过PackageManager(注:PackageManager可以获得当前设备上所安装的
application package的信息)来查找能处理这个Intent的component。在这个解析过程当中,Android是经过Intent的action、type、category这三个属性来进行判断的,判断方法以下:
若是Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,不然不能匹配;
若是Intent没有提供type,系统将从data中获得数据类型。和action同样,目标组件的数据类型列表中必须包含Intent的数据类型,不然不能匹配。
若是Intent中的数据不是content:类型的URI,并且Intent也没有明确指定type,将根据Intent中数据的scheme(好比 http:或者mailto:)进行匹配。同上,Intent 的scheme必须出如今目标组件的scheme列表中。
若是Intent指定了一个或多个category,这些类别必须所有出如今组建的类别列表中。好比Intent中包含了两个类别:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析获得的目标组件必须至少包含这两个类别。
相信作android应用开发的朋友对intent组件都已是至关熟悉了,这里鄙人总结一下intent的妙用,但愿对你们有帮助。
intent妙用之编写本身的android主界面
众所周知,android的主界面名为laucher2,功能强大,会在android启动以后运行,也是全部其余应用程序的入口程序。那么,如何让本身的应用程序取代laucher2的位置,成为android系统的主界面呢?其实说出来很简单,接下来,我就来为你们揭开这其中的神秘面纱。
首先,咱们来看看一个普通的应用程序的intent声明:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
是否是看着很眼熟呢?没错了,这段代码是在AndroidManifest.xml中相应activity的intent声明,相信你们目前缩写的应用程序的intent声明无一例外都是这样的吧。可能不少人都会对着两行代码有下面的理解:
第二行<action android:name="android.intent.action.MAIN" />表示这个activity是当前应用程序的主activity,而第二行表示当前activity在lancher中加载。
这么理解的倒是没错,但事实上,有更加简单的理解方式。这里请允许我先卖个关子。咱们继续往下看。
既然是想让咱们本身的应用程序取代laucher的位置,那么咱们就来看一下lancher的intent声明是怎么样的吧:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
</intent-filter>
固然,想要看到这段代码,你必需要有laucher的源代码。(关于android源代码的问题,前面的文章已经提到过不少次了,有源代码真的是件很好的事情,无论是对应用程序开发者来讲仍是对底层开发者来讲亦或是对android爱好者来讲,都会受益不浅的,因此这里再次建议你们不要仅仅局限于android sdk和avd的使用来进行应用程序的开发,无论你有没有时间,下份源代码老是没有坏处的。)
你们看出这两个intent声明之间的差异了吗?没错,当出现 <category android:name="android.intent.category.HOME"/> 的时候,咱们的应用程序就会变成跟lancher具备相同功能的(固然,我指的仅仅是主界面,laucher的功能是在是太强大了),成为android系统的主界面,而且,当咱们按下Home键的时候,会出现一个选择界面,是否是发现你的应用程序和laucher同时出如今了选择框中呢?若是是,那么恭喜你,从功能上来讲,你已经实现了。若是没有看到,请email我louiswangbing@gmail.com。
可是,所谓一山不容二虎,同时有两个主界面存在固然不是咱们想要的。
若是你有android源代码的话,你甚至能够把laucher删掉,直接将你本身的应用程序编译到android系统中,这样,系统启动的时候就会直接运行你的应用程序,而你的应用程序就会冠冕堂皇地鸠占鹊巢,瓜熟蒂落的成为系统的主界面,而且当你按下Home键的时候,就会跳到你的应用程序的主activity了!!
若是你只是一个功能上的追求者,那么看到这里你就能够关掉这个页面去试试上面的功能了。
若是你是一个好奇心比较强的人,那么请跟着我继续往下看。
刚才我说过,intent声明的理解问题。事实上,你能够有更好的理解方式,固然,这要创建在你对android系统的启动进程有必定的了解的基础上。
简单来讲,intent其实就是一个条件过滤器,activity的intent声明的每一条均可以做为一个过滤条件,条目越多,过滤条件也就越强,定位起来也就越容易。相信这个原理学过数据库的朋友理解起来更加容易。你能够将整个android系统中全部的activity都集中起来当成是一个数据库,而intent自己就是一条select语句,其中每一项声明都是一项过滤条件,而过滤以后剩下的,就是将要被调用的activity。当过滤条件足够强大或者过滤条件比较特殊的时候,最后剩下的只有一个activity,那么系统会绝不犹豫地启动它;当过滤条件不足致使过滤以后还剩下比较多的activity的时候,系统会将知足这些条件的全部的activity用一个listview列出来让你选择。
相信原理你们都已经很清楚了,那么上面所述的这个功能就很好理解了。没错,android在启动的时候会有一个PackageManager选择系统中知足过滤条件:
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
的activity做为系统启动的第一个activity,也就是主界面,任何一个知足这个过滤条件的activity都将进入候选名单,若是候选名单中仅有一人,那么很荣幸,不战而胜,你就是系统的主界面了;若是候选名单中有多我的(好比刚才说的有laucher和你本身的应用程序),那么就进入残酷的”民意选举“,也就是用户本身的选择,你选谁系统就会启动谁。但和民意选举不一样的是,选举出来的结果一般会有必定的任期,而这个主界面的选举任期很是的短,每当你按下一次Home键或者重启一下系统,系统就会从新安排一次”民意选举“。若是想要永远的成为主界面,那么惟一的办法就是--没错,虽然很残酷,但不得不说--就是,干掉它......或者和谐一点,你可让它活着,可是也必须将它贬为庶民或者是将其发配边疆,具体的实施手段就是--改掉它的intent声明,使其不知足主界面的这个过滤条件。
在整个intent妙用章节中,这一章算是比较特殊的,由于虽然全部的章节运用的原理基本相通,也就是我上面说到的原理,可是后续章节的intent过滤条件都是能够由用户本身定义、手动修改的,而惟独只有这个是不能改的,你只能决定去适应或者不适应这个过滤条件,而不能去改变这个过滤条件,就像你只能去适应这个社会,却很难改变它--或许不是不能,而是暂时还能找到途径......
有时候真的,生活跟计算机,竟然有如此之多的类似之处......
intent妙用之列出全部已安装的应用程序列表
装载:http://blog.csdn.net/android_tutor/article/details/5724634
这篇文章写的很好,既说明了方法,也给出了实例,可是很惋惜的是,并无说明其中的原理。
这里,看过我上一篇文章的朋友相信已经可以本身分析得出答案了!
没错,其实全部的这些应用程序列表也就是一个过滤以后知足过滤条件的activity!而这个过滤条件一般是:
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
即对应着上面转载文章当中的函数:
public void bindAllApps(){
//这里是关键哦,咱们平时写的应用总有一个activity申明成这两个属性
//也就是应用的入口
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
//符合上面条件的所有查出来,而且排序
mAllApps = mPackageManager.queryIntentActivities(mainIntent, 0);
Collections.sort(mAllApps, new ResolveInfo.DisplayNameComparator(mPackageManager));
}
很容易看明白,四、5两行就是定义的这个过滤条件,其中Intent.ACTION_MAIN对应着<action android:name="android.intent.action.MAIN" />,Intent.CATEGORY_LAUNCHER对应着<category android:name="android.intent.category.LAUNCHER" /> ,这个对应关系是系统定义的。固然,这个对应关系其实也能够本身自定义,后续章节会介绍,这里略过。而今跟着的后面两句就是查询和列出符合条件的activity了。这里须要注意到是,并非全部的应用程序intent声明都能知足这个过滤条件的,好比说你们喜闻乐见的Adobe 的Flashplayer浏览器插件就不是这样的,这也是为何你们将这个插件安装到手机上却不能显示在主界面应用程序列表里面的缘由。
带着我上一篇文章里面讲到的原理,这部分的理解就显得异常简单了。
固然啊,到这里也只是完成了列出全部知足过滤条件的应用列表而已,想要点击这个列表就能进入相应的应用程序,还有接下来的工做要作。
参照我转载的这篇文章来讲,函数功能是这样实现的:
//gridview点击事件,点击进入相关应用
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
ResolveInfo res = mAllApps.get(position);
//该应用的包名和主Activity
String pkg = res.activityInfo.packageName;
String cls = res.activityInfo.name;
ComponentName componet = new ComponentName(pkg, cls);
Intent i = new Intent();
i.setComponent(componet);
startActivity(i);
}
在具体说明原理以前,有一个前提条件你们必需要记住,那就是在android系统中,是不容许有两个包名彻底相同的应用程序存在的,若是两个程序的包名和包里面的内容彻底同样,后来的将会覆盖原有的,这也是为何android应用开发不须要卸载以前的应用程序而直接修改源代码再运行就能够覆盖的缘由。
有了这个前提条件以后,接下来,咱们看看这段代码。其实,这里也是intent的一个妙用。前面的那些过滤条件,咱们称之为隐式intent,由于将会过滤出哪些或者多少知足条件的activity,咱们都是不知道的。而这里的intent使用,咱们称之为显示intent,由于它的过滤条件十分强大,近似一个指针,直接指向一个独一无二的应用,而且在指定的时候就已经知道它是谁,并且知道它确定是独一无二的。
其实很简单,刚才已经说过 了,由于android中不容许有相同的包名出现,也就是说全部的包名都是独一无二的,那么只要指定intent过滤条件为相应的包名和activity名,一切也就迎刃而解了。从数据库原理的角度来理解,列出全部知足条件的列表以后,第N条的数据是什么已经能够看见了,这时候只须要将过滤条件设置主键值为第N条的那个主键值就能够惟必定位到那条数据了。
上面的代码到第13行的时候,intent i所包含的activity就只剩下一个了,剩下的工做只须要启动它就好了,startActivity(i),一切瓜熟蒂落。