经过Intent传递类对象

1、Intent是什么

一、定义

Intent被译做意图,其实仍是很能传神的,Intent指望作到的,就是把实现者和调用者彻底解耦,调用者专心将以意图描述清晰,发送出去,就能够梦想成真,达到目的。html

这 个解释仍是有点不太好理解,下面还有一个:Intent是一种运行时绑定(run-time binding)机制,它能在程序运行过程当中链接两个不一样的组件。经过Intent,你的程序能够向Android表达某种请求或者意愿,Android 会根据意愿的内容选择适当的组件来完成请求。好比,有一个Activity但愿打开网页浏览器查看某一网页的内容,那么这个Activity只须要发出 WEB_SEARCH_ACTION给Android,Android就会根据Intent的请求内容,查询各组件注册时声明的 IntentFilter,找到网页浏览器的Activity来浏览网页。 这个解释好像理解起来就容易好多,咱们经过intent传入某种意图,而android就会根据这种意图,自动寻找合适的activity来启动,若是有 多个条件符合的activity,就以列表的方式让用户手动选择一个。
java

二、显示Intent与隐式Intent

这两个概念刚开始不太好理解,先看两个经过intent启动activity的代码:android

例一:web

Intent intent = new Intent();
intent.setClass(Context packageContext, OtherActivity.class);
startActivity(intent);

例二:浏览器

Intent intent = new Intent();
intent.setAction(Intent.ACTION_NEW);
startActivity(intent);

从这两段代码中能够明显看出,一样是startActivity,但第一个明确指出是启动OtherActivity,而在第二个例子中,并无明确指出要启动哪一个activity!服务器

这两种书写方式就分别是显示Intent(例一)、隐式Intent(例二);app

  • 显式intent是指明确指出此intent是启动哪一个activity.函数

  • 隐式intent是指并无指出要启动哪一个activity,而要系统自动去判断并启动匹配的activity.测试

三、显式Intent小结

有两种方式来显示的指示要启动的Activity:google

方式一:(经过setClassName)

Intent intent = new Intent();
//表示但愿启动com.example.test_permission包中的com.example.test_permission.MainActivity
intent.setClassName("com.example.test_permission", "com.example.test_permission.MainActivity");
startActivity(intent);

方式二:(经过SetClass)

Intent intent = new Intent();
intent.setClass(Context packageContext, OtherActivity.class);
startActivity(intent);

一样,setClass(Context packageContext, OtherActivity.class);是指启动packageContext包里的OtherActivity.class类;

2、针对隐式intent,Activity的匹配原则

上面咱们讲了隐式intent是要靠系统自动去匹配并启动某个activity的。那系统是怎样匹配activity的呢,系统是怎样知道这个actitiy就是某个intent想要的呢。

某个activity能不能被某个intent激活,要看这个activity是否是符合这个intent的要求,而某个activity能被哪一个intent激活是有定义的,定义就在AndroidManifest.xml

打开AndroidManifest.xml,找到任意一个activity,通常都能看到一段代码,举个例子,我随便复制一个,以下:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

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

看这里有一对标签<intent-filter>……</intent-filter>
在这个标签里定义的全部东东都是用来定义该activity能够被哪些intent激活的,若是匹配,就会被激活!!!!!

在<intent-filter>里有如下几个属性可让intent来匹配:Action、CategoryData;下面逐一介绍:

一、Action:该activity能够执行的动做

该 标识用来讲明这个activity能够执行哪些动做,因此当隐式intent传递过来action时,若是跟这里<intent- filter>所列出的任意一个匹配的话,就说明这个activity是能够完成这个intent的意图的,能够将它激活!!!!

经常使用的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 改变时区警告.

两条原则:

  • 一条<intent-filter>元素至少应该包含一个<action>,不然任何Intent请求都不能和该<intent-filter>匹配。

  • 若是Intent请求的Action和<intent-filter>中个任意一条<action>匹配,那么该Intent就能够激活该activity(前提是除了action的其它项也要经过)

两条注意:

若是Intent请求或<intent-filter>中没有说明具体的Action类型,那么会出现下面两种状况。

  •  若是<intent-filter>中没有包含任何Action类型,那么不管什么Intent请求都没法和这条<intent-filter>匹配。

  •  反之,若是Intent请求中没有设定Action类型,那么只要<intent-filter>中包含有Action类型,这个Intent请求就将顺利地经过<intent-filter>的行为测试。

二、Category:于指定当前动做(Action)被执行的环境

即这个activity在哪一个环境中才能被激活。不属于这个环境的,不能被激活。

经常使用的Category属性以下所示:

     CATEGORY_DEFAULT:Android系统中默认的执行方式,按照普通Activity的执行方式执行。表示全部intent均可以激活它 

    CATEGORY_HOME:设置该组件为Home Activity。

    CATEGORY_PREFERENCE:设置该组件为Preference。 

    CATEGORY_LAUNCHER:设置该组件为在当前应用程序启动器中优先级最高的Activity,一般为入口ACTION_MAIN配合使用。 

    CATEGORY_BROWSABLE:设置该组件可使用浏览器启动。表示该activity只能用来浏览网页。 

    CATEGORY_GADGET:设置该组件能够内嵌到另外的Activity中。

注意:

若是该activity想要经过隐式intent方式激活,那么不能没有任何category设置,至少包含一个android.intent.category.DEFAULT

三、Data  执行时要操做的数据

在目标<data/>标签中包含了如下几种子元素,他们定义了url的匹配规则:

  • android:scheme 匹配url中的前缀,除了“http”、“https”、“tel”...以外,咱们能够定义本身的前缀

  • android:host 匹配url中的主机名部分,如“google.com”,若是定义为“*”则表示任意主机名

  • android:port 匹配url中的端口

  • android:path 匹配url中的路径

在XML中声明能够操做的data域应该是这样的:

<activity android:name=".TargetActivity">
<intent-filter>
    <action android:name="com.scott.intent.action.TARGET"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:scheme="scott" android:host="com.scott.intent.data" android:port="7788" android:path="/target"/>
</intent-filter>
</activity>

注意:

这个标识比较特殊,它定义了执行此Activity时所须要的数据,也就是说,这些数据是必须的!!!!!全部若是其它条件都足以激活该Activity,但intent却没有传进来指定类型的Data时,就不能激活该activity!!!!

3、Intent隐式传递方法

上面咱们讲了一个Activity能被某隐式Intent唤醒的原则,只有这些所有匹配的intent才能唤醒这个Activity,下面咱们就讲讲怎么向隐式intent传递这些参数,以便与activity匹配将向唤醒。

一、Action

使用Intent的一个构造方法便可实现传递Action参数:

public Intent(String action) {
    mAction = action;
}

对于有以下声明的Activity:

<activity android:name=".TargetActivity">
    <intent-filter>
        <action android:name="com.scott.intent.action.TARGET"/> 
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

要激活这个Activity,就须要以下这样构造Intent:(直接向intent中传递action的name值)

    public void gotoTargetActivity(View view) {
        Intent intent = new Intent("com.scott.intent.action.TARGET");
        startActivity(intent);
    }

这样就能够启动咱们上面的这个activity了。

注意这里再次提醒,一个activity能够有多个action,只要有一个匹配就能够被启动。一样,若是仅指定某个action,而多个activity都具备这个action的话,系统会列出列表供用户选择执行哪个activity.

二、Category

一个intent对象能够有任意个category。intent类定义了许多category常数.

  • addCategory()方法为一个intent对象增长一个category,

  • removeCategory删除一个category,

  • getCategories()获取intent全部的category.

三、Data

有两种传递data的方式:

第一种:利用构造函数:

public Intent(String action, Uri uri) {
    mAction = action;
    mData = uri;
}

第二种:利用Intent::SetData(URI uri)

Intent intent = new Intent("com.scott.intent.action.name");
intent.setData(Uri.parse("scheme://host:port/parth"));
startActivity(intent);

举个例子:(改动下上面的action的例子)

<activity android:name=".TargetActivity">
    <intent-filter>
        <action android:name="com.scott.intent.action.TARGET"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="scott" android:host="com.scott.intent.data" android:port="7788" android:path="/target"/>
    </intent-filter>
</activity>

这个时候若是要启动这个TargetActivity只指定action就不够了,咱们须要为其设置data值,以下:

Intent intent = new Intent("com.scott.intent.action.TARGET");
intent.setData(Uri.parse("scott://com.scott.intent.data:7788/target"));
startActivity(intent);

此时,url中的每一个部分和TargetActivity配置信息中所有一致才能跳转成功,不然就被系统拒绝。

注意:

不过有时候对path限定死了也不太好,好比咱们有这样的url:(scott://com.scott.intent.data:7788/target/hello)(scott://com.scott.intent.data:7788/target/hi)

这个时候该怎么办呢?咱们须要使用另一个元素:android:pathPrefix,表示路径前缀。
咱们把android:path="/target"修改成android:pathPrefix="/target",而后就能够知足以上的要求了。

四、Extras

这 个参数不参与匹配activity,而仅做为额外数据传送到另外一个activity中,接收的activity能够将其取出来。这些信息并非激活这个 activity所必须的。也就是说激活某个activity与否只上action、data、catagory有关,与extras无关。而 extras用来传递附加信息,诸如用户名,用户密码什么的。

可经过putXX()和getXX()方法存取信息;也能够经过建立Bundle对象,再经过putExtras()和getExtras()方法来存取。

经过bundle对象传递

发送方

Intent intent = new Intent("com.scott.intent.action.TARGET");  
Bundle bundle = new Bundle();  
bundle.putInt("id", 0);  
bundle.putString("name", "scott");  
intent.putExtras(bundle);  
startActivity(intent);

接收方:

Bundle bundle = intent.getExtras();
int id = bundle.getInt("id");
String name = bundle.getString("name");

更多参数传递方法见《经过Intent传递类对象》


五、附《Intent调用常见系统组件方法》

// 调用浏览器
Uri webViewUri = Uri.parse("http://blog.csdn.net/zuolongsnail");
Intent intent = new Intent(Intent.ACTION_VIEW, webViewUri);

// 调用地图
Uri mapUri = Uri.parse("geo:100,100");
Intent intent = new Intent(Intent.ACTION_VIEW, mapUri);

// 播放mp3
Uri playUri = Uri.parse("file:///sdcard/test.mp3");
Intent intent = new Intent(Intent.ACTION_VIEW, playUri);
intent.setDataAndType(playUri, "audio/mp3");

// 调用拨打电话
Uri dialUri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent.ACTION_DIAL, dialUri);
// 直接拨打电话,须要加上权限<uses-permission id="android.permission.CALL_PHONE" />
Uri callUri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent.ACTION_CALL, callUri);

// 调用发邮件(这里要事先配置好的系统Email,不然是调不出发邮件界面的)
Uri emailUri = Uri.parse("mailto:zuolongsnail@163.com");
Intent intent = new Intent(Intent.ACTION_SENDTO, emailUri);
// 直接发邮件
Intent intent = new Intent(Intent.ACTION_SEND);
String[] tos = { "zuolongsnail@gmail.com" };
String[] ccs = { "zuolongsnail@163.com" };
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT, "the email text");
intent.putExtra(Intent.EXTRA_SUBJECT, "subject");
intent.setType("text/plain");
Intent.createChooser(intent, "Choose Email Client");

// 发短信
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra("sms_body", "the sms text");
intent.setType("vnd.android-dir/mms-sms");
// 直接发短信
Uri smsToUri = Uri.parse("smsto:10086");
Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);
intent.putExtra("sms_body", "the sms text");
// 发彩信
Uri mmsUri = Uri.parse("content://media/external/images/media/23");
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "the sms text");
intent.putExtra(Intent.EXTRA_STREAM, mmsUri);
intent.setType("image/png");

// 卸载应用
Uri uninstallUri = Uri.fromParts("package", "com.app.test", null);
Intent intent = new Intent(Intent.ACTION_DELETE, uninstallUri);
// 安装应用
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File("/sdcard/test.apk"), "application/vnd.android.package-archive");

// 在Android Market中查找应用
Uri uri = Uri.parse("market://search?q=愤怒的小鸟");         
Intent intent = new Intent(Intent.ACTION_VIEW, uri);

至此本文就结束了。

下一篇用简单的几个实例,来具体讲解隐式intent的匹配与调用原理。

参考文章 :

《Android中Intent组件详解》

《android Intent机制详解》

《基础总结篇之九:Intent应用详解》

《Intent详解》

《Intent总结》

《Intent中的四个重要属性——Action、Data、Category、Extras》

相关文章
相关标签/搜索