隐式调用
在前文 activity四种启动模式及Flag 中我们知道启动一个activity是可以通过activity.startActivity ( intent )来显式调用 启动的。相对于显式调用,android还提供了一种implicit intents(隐式Intent)来启动activity,这就需要用到 < intent-filter >了。
准确的来讲,Intent的隐式调用只是启动符合某一特定< Intent - Filter> 的 activity,而不是指定activity。
Uri number = Uri.parse("tel:10086");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
在执行类似的隐式调用时,系统会去匹配过滤那些与Intent携带的action,category,data等属性,这些属性是特定的字符串。只有这些声明属性相同的activity,才会被启动,当多个符合规则的activity同时存在时,系统会弹出一个选择框让用户选择。
如上图,系统存在多个提供壁纸选择的activity供用户选择,用户可以默认使用其中一项,下次还有相同的隐式调用就默认打开,同时,activity这种隐式调用的规则也实现了不同APP间的跳转。
注: 不仅仅只有activity才能通过implicit intents(隐式Intent)来调起,包括service、broadcast receiver也是可以接受的。本文为节省篇幅不做过多说明,详情请移步android 官网api引导intent-filter-element
Intent - Filter
当Intent 隐式调用时,为了尽可能准确的筛选你的activity,Manifests 中每一个activity声明的intent filter都应该写清楚。
<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"/>
<data android:mimeType="image/*"/>
</intent-filter>
</activity>
Action:一个执行特定action的字符串。 通常是系统已经定义好的值(可以是自己定义的),例如 ACTION_SEND 或者 ACTION_VIEW ,系统全部的action类型都在Intent对象里面以静态final属性标识。Manifests 中声明Intent - Filter用 指定它的值。
Category:提供一个附加的属性 字符串来标识这个activity。 通常与用户的手势或者是启动位置有关。 系统有支持几种不同的categories。像MainActivity允许在启动器去点击它的图标启动。
< category android:name= “android.intent.category.LAUNCHER”/>
但是大多数都不怎么用的到,我们可以自己声明这个字符串,使系统更容易筛选出这个activity。所有的隐式调用都默认是 CATEGORY_DEFAULT,可在intent - filter中用 < category > 指定它的值。Data: Intent附带数据的描述(对URI不熟悉先前看下一标题URI)。在intent filter中用< data > 指定它的值, 可以使用一个或者多个属性, 你可以只定义MIME type或者是只指定URI前缀, 也可以只定义一个URI scheme, 或者是他们配合使用。
<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string" />
注: 如果你不想写明Uri 类型的数据,但又想指明数据类型, 那么你应该指定 android:mimeType 属性。 例如 text/plain 、image/jpeg
URI(统一资源标识符)
在熟悉intent-filter的data项前我们需要多URI有一定的认识。
统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。
URI由包括确定语法和相关协议的方案所定义。
Web上可用的每种资源:HTML文档、图像、视频片段、程序等 - 由一个通用资源标识符(URI)进行定位。
引用至:百度百科的URI
可能Uri这个名词比较陌生,但url大伙应该听过,其实还有个urn,他们的关系:
URI = Universal Resource Identifier 统一资源标志符
URL = Universal Resource Locator 统一资源定位符
URN = Universal Resource Name 统一资源名称
URI分为三种,URL or URN or (URL and URI)
URL代表资源的路径地址,而URI代表资源的名称。
URN 也是URI的一个子集,目前没有大规模运用。
这是Uri的结构
< scheme >://< host >:< port >[< path >|< pathPrefix >|< pathPattern >]
引用于 android官网api指南
这是具体使用
1. http://image.baidu.com:80/search/detail?gsm=348&rpstart=0&rpnum=0
2. file:///sdcard/music/我的滑板鞋.mp3
- scheme 可以理解为协议头
- host 就是主机地址,如image.baidu.com
- port 端口号,http协议默认80端口
- path、pathPattern 、pathPrefix表示路径
- path 完整路径
- pathPattern 可以携带通配符的路径,如*,0等通配符
- pathPrefix 路径的前缀
Intent 的URI功能示例总汇
打开一个网页,类别是Intent.ACTION_VIEW
Uri uri = Uri.parse(“http://blog.youkuaiyun.com/cch1024/“);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);打开地图并定位到一个点
Uri uri = Uri.parse(“geo:52.76,-79.0342”);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);打开拨号界面,类型是Intent.ACTION_DIAL
Uri uri = Uri.parse(“tel:10086”);
Intent intent = new Intent(Intent.ACTION_DIAL, uri);直接拨打电话,与三不同的是,这个直接拨打电话,而不是打开拨号界面
Uri uri = Uri.parse(“tel:10086”);
Intent intent = new Intent(Intent.ACTION_CALL, uri);卸载一个应用,Intent的类别是Intent.ACTION_DELETE
Uri uri = Uri.fromParts(“package”, “xxx”, null);
Intent intent = new Intent(Intent.ACTION_DELETE, uri);安装应用程序,Intent的类别是Intent.ACTION_PACKAGE_ADDED
Uri uri = Uri.fromParts(“package”, “xxx”, null);
Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, uri);播放音频文件
Uri uri = Uri.parse(“file:///sdcard/download/everything.mp3”);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setType(“audio/mp3”);打开发邮件界面
Uri uri= Uri.parse(“mailto:admin@android-study.com”);
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);发邮件,与八不同这里是将邮件发送出去
Intent intent = new Intent(Intent.ACTION_SEND);
String[] tos = { “admin@android-study.com” };
String[] ccs = { “webmaster@android-study.com” };
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT, “I come from http://blog.youkuaiyun.com/cch1024“);
intent.putExtra(Intent.EXTRA_SUBJECT, “http://blog.youkuaiyun.com/cch1024“);intent.setType(“message/rfc882”);
Intent.createChooser(intent, “Choose Email Client”);
//发送带附件的邮件
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_SUBJECT, “The email subject text”);
intent.putExtra(Intent.EXTRA_STREAM, “file:///sdcard/mysong.mp3”);
intent.setType(“audio/mp3”);
startActivity(Intent.createChooser(intent, “Choose Email Client”));发短信
Uri uri= Uri.parse(“tel:10086”);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(“sms_body”, “I come from http://blog.youkuaiyun.com/cch1024“);
intent.setType(“vnd.Android-dir/mms-sms”);直接发短信
Uri uri= Uri.parse(“smsto://10086”);
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent.putExtra(“sms_body”,”3gandroid http://blog.youkuaiyun.com/cch1024“);发彩信
Uri uri= Uri.parse(“content://media/external/images/media/23”);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(“sms_body”,”3g android http://blog.youkuaiyun.com/cch1024“);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType(“image/png”);路径规划
Uri uri= Uri.parse (“http://maps.google.com/maps?f=d“);
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
//where startLat, startLng, endLat, endLng are a long with 6 decimals like: 50.123456安装指定apk
public void setupAPK(String apkname){
String fileName = Environment.getExternalStorageDirectory() + “/” + apkname;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(fileName)), “application/vnd.android.package-archive”);
mService.startActivity(intent);
}进入联系人页面
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(People.CONTENT_URI);
startActivity(intent);查看指定联系人
Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);// info.id联系人ID
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(personUri);
startActivity(intent);调用相册
public static final String MIME_TYPE_IMAGE_JPEG = “image/*”;
public static final int ACTIVITY_GET_IMAGE = 0;
Intent getImage = new Intent(Intent.ACTION_GET_CONTENT);
getImage.addCategory(Intent.CATEGORY_OPENABLE);
getImage.setType(MIME_TYPE_IMAGE_JPEG);
startActivityForResult(getImage, ACTIVITY_GET_IMAGE);调用系统相机应用程序,并存储拍下来的照片
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
time = Calendar.getInstance().getTimeInMillis();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment
.getExternalStorageDirectory().getAbsolutePath()+”/tucue”, time + “.jpg”)));
startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);