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)就可以了。