首页 > 代码库 > Intent学习

Intent学习

1.Intent是什么


Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对 
应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则 
根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组 
件,并完成组件的调用。 
Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service 
之间的交互。因此,Intent在这里起着一个中介的作用,专门提供组 
件互相调用的相关信息,实现调用者与被调用者之间的解耦。

2.Intent定义的内容


在Android参考文档中,对Intent的定义是执行某操作的一个抽象描述。

(1)Action,也就是要执行的动作 
(2)Data,也就是执行动作要操作的数据 
(3)type(数据类型) 
(4)category(类别) 
(5) component(组件) 
(6) extras(附加信息)

2.1)执行的动作(action)


动作(action)的一个简要描述,如VIEW_ACTION(查看)、EDIT_ACTION 
(修改)等,Android为我们定义了一套标准动作。

系统定义的动作(action) 
ACTION_CALL    activity    Initiate a phone call. 
ACTION_EDIT    activity    Display data for the user to edit. 
ACTION_MAIN    activity    Start up as the initial activity of a task, with no data input and no returned output. 
ACTION_SYNC    activity    Synchronize data on a server with data on the mobile device. 
ACTION_BATTERY_LOW    broadcast receiver    A warning that the battery is low. 
ACTION_HEADSET_PLUG    broadcast receiver    A headset has been plugged into the device, or unplugged from it. 
ACTION_SCREEN_ON    broadcast receiver    The screen has been turned on. 
ACTION_TIMEZONE_CHANGED    broadcast receiver    The setting for the time zone has changed.

2.2)执行动作要操作的数据(data)


Android中采用指向数据的一个URI来表示, 
如在联系人应用中,一个指向某联系人的URI可能为:content://contacts/1。

这种URI表示,通过 ContentURI这个类来描述,具体可以参考android.net.ContentURI类的文档。

以联系人应用为例,以下是一些action / data对,及其它们要表达的意图

VIEW_ACTION content://contacts/1-- 显示标识符为"1"的联系人的详细信息 
EDIT_ACTION content://contacts/1-- 编辑标识符为"1"的联系人的详细信息 
VIEW_ACTION content://contacts/-- 显示所有联系人的列表 
PICK_ACTION content://contacts/-- 显示所有联系人的列表,并且允许用户在列表中选择一个联系人,然后把这个联系人返回给父activity。

--------------------code----------------- 
action为Intent.ACTION_VIEW,data为ContactsContract.Contacts.CONTENT_URI 
查看联系人列表

Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("content://com.android.contacts/contacts"));//Intent intent = new Intent(Intent.ACTION_VIEW,ContactsContract.Contacts.CONTENT_URI);


startActivity(intent); 
查看某一个联系人

Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("content://com.android.contacts/contacts/190"));//Intent intent = new Intent(Intent.ACTION_VIEW,ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, 190));

startActivity(intent); 
编辑某一个联系人

Intent intent = new Intent(Intent.ACTION_EDIT,Uri.parse("content://com.android.contacts/contacts/190"));//Intent intent = new Intent(Intent.ACTION_EDIT,ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, 190));


startActivity(intent); 
注意:不能编辑一个联系人列表。

Intent intent = new Intent(Intent.ACTION_EDIT,Uri.parse("content://com.android.contacts/contacts"));//错


显示联系人列表,并选择一个,然后获取该联系人信息;

Intent intent = new Intent(Intent.ACTION_PICK,ContactsContract.Contacts.CONTENT_URI);startActivityForResult(intent, 100);@Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        if(requestCode == 100){            if(resultCode == RESULT_OK){                Uri uri = data.getData();                Cursor cursor = getContentResolver().query(uri, null, null, null, null);                if(cursor.moveToFirst()){                    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));                    System.out.println(name);                }                cursor.close();            }        }    }


-----------------------code-------------------------------

Uri uri = data.getData();Cursor cursor = getContentResolver().query(uri, null, null, null, null);if(cursor.moveToFirst()){    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));    nameet.setText(name);    String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));        Cursor c2 = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+id, null, null);    c2.moveToFirst();    String phone = c2.getString(c2.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));    phoneet.setText(phone);        c2.close();    cursor.close();}

 

2.3)category 类别


category(类别)是被执行动作的附加信息。

 

2.4)type(数据类型)


type(数据类型),显式指定Intent的数据类型(MIME)。一般Intent 
的数据类型能够根据数据本身进行判定, 
但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。

Intent intent = new Intent(Intent.ACTION_VIEW);intent.setDataAndType(Uri.parse("file:///mnt/sdcard/a.pdf"),"application/pdf");startActivity(intent);

 

2.5)component(组件)


component(组件),指定Intent的的目标组件的类名称。 
通常 Android会根据Intent 中包含的其它属性的信息 
,比如action、data/type、category进行查找,最终找到一个 
与之匹配的目标组件。 
但是,如果 component这个属性有指定的话,将直接 
使用它指定的组件,而不再执行上述查找过程。 
指定了这个属性以后,Intent的其它所有属性都是可选的。

Intent intent = new Intent();ComponentName component =         new ComponentName(getApplicationContext(), SecondActivity.class);intent.setComponent(component);startActivity(intent);

 

2.6)extras(附加信息)


extras(附加信息),是其它所有附加信息的集合。使用extras可以为 
组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以 
将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

 

3.Android如何解析Intent


在应用中,我们可以以两种形式来使用Intent:

直接Intent:

指定了component属性的Intent(调用setComponent 
(ComponentName)或者setClass(Context, Class)来指定)。 
通过指定具体的组件类,通知应用启动对应的组件。 
间接Intent:没有指定comonent属性的Intent。这些Intent需要 
包含足够的信息,这样系统才能根据这些信息,在所有的可用组件 
中,确定满足此Intent的组件。

间接Intent


Intent解析机制主要是通过查找已注册在AndroidManifest.xml中 
的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。

IntentFilter意图筛选器 
IntentFilter用来描述Activity能够做些什么事情。 
应用程序的组件为了告诉Android自己能响应、处理哪些隐式Intent 
请求,可以声明一个甚至多个Intent Filter。每个Intent Filter描 
述该组件所能响应Intent请求的能力——组件希望接收什么类型的请求 
行为,什么类型的请求数据。

间接Intent匹配


隐式Intent(Explicit Intents)和Intent Filter(Implicit Intents) 
进行比较时的三要素是Intent的动作、数据以及类别。(隐式Intent:指的是在 
Intent intent = new Intent()时的java代码,而Intent filter是在androidmanifest.xml 
文件中定义的。) 
实际上,一个隐式Intent请求要能够传递给目标组件,必要通过这三个方 
面的 检查。如果任何一方面不匹配,Android都不会将该隐式Intent传递 
给目标组件。接下来我们讲解这三方面检查的具体规则。

隐式启动:

Intent intent = new Intent();intent.setAction("com.anjoyo.myfirsttest");startActivity(intent);

intent-filter配置:

<activity android:name=".intentfilter.TestActivity">    <intent-filter >        <action android:name="com.anjoyo.myfirsttest"/>        <category android:name="android.intent.category.DEFAULT"/>    </intent-filter></activity>

补充

1.作为一个程序为桌面程序

 

<activity    android:name=".intent.MainActivity"    android:label="@string/app_name" >    <intent-filter>        <action android:name="android.intent.action.MAIN" />        <category android:name="android.intent.category.HOME"/>        <category android:name="android.intent.category.DEFAULT"/>    </intent-filter></activity>
<category android:name="android.intent.category.HOME"/>回到桌面<category android:name="android.intent.category.LAUNCHER"/>作为应用的入口

2.隐式Intent(Explicit Intents)和Intent Filter(Implicit Intents)


进行比较时的三要素是Intent的动作、数据以及类别。 
实际上,一个隐式Intent请求要能够传递给目标组件,必要通过这三个方面 
的 检查。如果任何一方面不匹配,Android都不会将该隐式Intent传递给目 
标组件。接下来我们讲解这三方面检查的具体规则。 
1).动作测试 
<intent-filter>元素中可以包括子元素<action>,比如:

<intent-filter>    <action android:name=”com.example.project.SHOW_CURRENT” />    <action android:name=”com.example.project.SHOW_RECENT” />    <action android:name=”com.example.project.SHOW_PENDING” /></intent-filter>

一条<intent-filter>元素至少应该包含一个<action>,否则任何Intent 
请求都不能和 该<intent-filter>匹配。 
如果隐式启动一个Activity,那么还需要在<intent-filter>中加入 
 

<category android:name="android.intent.category.DEFAULT"/>

例子:

<activity android:name="xxx">     <intent-filter >        <action android:name="com.anjoyo.mysecond"/>        <category android:name="android.intent.category.DEFAULT"/>    </intent-filter>    <intent-filter >        <action android:name="com.anjoyo.mysecond2"/>        <action android:name="com.anjoyo.mysecond3"/>        <category android:name="android.intent.category.DEFAULT"/>    </intent-filter></activity>

action匹配规则:找到一个与隐式Intent的Action定义相同的Intent filter.

2).类别测试 
<intent-filter>元素可以包含<category>子元素,比如:

<intent-filter>    <category android:name=”android.Intent.Category.DEFAULT” />    <category android:name=”android.Intent.Category.BROWSABLE” /></intent-filter>

只有当Intent请求中所有的Category与组件中某一个IntentFilter的 
<category>完全匹配时,才会让该Intent请求通过测试,IntentFilter 
中多余的<category>声明并不会导致匹配失败。

3).数据在<intent-filter>中的描述如下:

<intent-filter>    <data android:type=”video/mpeg” android:scheme=”http” . . . />    <data android:type=”audio/mpeg” android:scheme=”http” . . . /></intent-filter>

<data>元素指定了希望接受的Intent请求的数据URI和数据类型, 
URI被分成三部分来进行匹配:scheme、authority和path。 
其中,用setData()设定的Intent请求的URI数据类型和scheme必须 
与IntentFilter中所指定的一致。若IntentFilter中还指定了 
authority或path,它们也需要相匹配才会通过测试。

如:http://www.baidu.com  http就是schema 
tel:1390023232  tel就是schema 
file:///mnt/sdcard/Picture/xx.jpg file就是schema

例子:

Intent intent = new Intent();intent.setAction(Intent.ACTION_CALL);intent.setData(Uri.parse("tel:123343"));startActivity(intent);
<activity     android:name=".intent.ForthActivity">    <intent-filter>        <action android:name="android.intent.action.CALL"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:scheme="tel"/>    </intent-filter></activity>


3. 
1).向下一个Activity传递数据(使用Bundle和Intent.putExtras)

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");

2).向上一个Activity返回结果 
(使用setResult,针对startActivityForResult(it,REQUEST_CODE)启动的Activity) 
   

Intent intent=getIntent();     Bundle bundle2=new Bundle();     bundle2.putString("name", "This is from ShowMsg!");     intent.putExtras(bundle2);     setResult(RESULT_OK, intent);

     
回调上一个Activity的结果处理函数(onActivityResult)

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {if(requestCode==REQUEST_CODE){ if(resultCode==RESULT_CANCELED)     setTitle("cancle"); else if (resultCode==RESULT_OK) {     String temp=null;     Bundle ();     if(bundle!=null)         bundle=data.getExtras    temp=bundle.getString("name");     setTitle(temp); } } }

简单例子: 
1,调用web浏览器

Uri myBlogUri = Uri.parse(http://www.cmd100.com);  intent = new Intent(Intent.ACTION_VIEW, myBlogUri);

  2,地图

Uri mapUri = Uri.parse("geo:38.899533,-77.036476");  intent = new Intent(Intent.ACTION_VIEW, mapUri);

  3,调拨打电话界面

Uri telUri = Uri.parse("tel:10086");  intent = new Intent(Intent.ACTION_DIAL, telUri);


4,直接拨打电话

Uri callUri = Uri.parse("tel:10086");  intent = new Intent(Intent.ACTION_CALL, callUri);

  5,卸载

Uri uninstallUri = Uri.fromParts("package", "xxx", null);  intent = new Intent(Intent.ACTION_DELETE, uninstallUri);


6,安装

Uri installUri = Uri.fromParts("package", "xxx", null);  intent = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);


7,播放

Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");  intent = new Intent(Intent.ACTION_VIEW, playUri);


8,发邮件

Uri emailUri = Uri.parse("mailto:xx@xxx.com");  intent = new Intent(Intent.ACTION_SENDTO, emailUri);

  9,发邮件

intent = new Intent(Intent.ACTION_SEND);  String[] tos = { "xx@xxx.com" };  String[] ccs = { "xx@xxx.com" };  intent.putExtra(Intent.EXTRA_EMAIL, tos);  intent.putExtra(Intent.EXTRA_CC, ccs); intent.putExtra(Intent.EXTRA_TEXT, "body");  intent.putExtra(Intent.EXTRA_SUBJECT, "subject");  intent.setType("message/rfc882");  Intent.createChooser(intent, "Choose Email Client");


10,发短信

Uri smsUri = Uri.parse("tel:10086");  intent = new Intent(Intent.ACTION_VIEW, smsUri);  intent.putExtra("sms_body", "hello~");  intent.setType("vnd.android-dir/mms-sms");


11,直接发邮件

Uri smsToUri = Uri.parse("smsto://10086");  intent = new Intent(Intent.ACTION_SENDTO, smsToUri);  intent.putExtra("sms_body", "hello");


12,发彩信

Uri mmsUri = Uri.parse("content://media/external/images/media/23"); intent = new Intent(Intent.ACTION_SEND);  intent.putExtra("sms_body", "hello");  intent.putExtra(Intent.EXTRA_STREAM, mmsUri);  intent.setType("image/png");


用获取到的Intent直接调用startActivity(intent)就可以了。