本文通过完成一个实战任务,来掌握Android开发中隐式Intent的用法。


任务假设我们已经实现了一个视频播放器(PlayerActivity),我们希望能把它注册到系统中,当用户点击本地视频或者在线视频时,能启动这个视频播放器。


假设该类的全路径为:com.jhuster.videoplayer.PlayerActivity)


[注]:本文完整的示例代码请到我的Github下载,地址:VideoPlayer


1. 什么是隐式Intent?


Intent是Android中比较重要的组件,常用来启动一个新的Activity或者Service、广播某个事件,以及在Android组件之间传递数据。通过Intent来启动新的Activity或者Service通常有两种方法,一种是显示启动,另一种是隐式启动。


显示启动就是在明确指出要启动的Activity或者Service的类或者包名。例如:


Intent intent = newIntent(this, PlayerActivity.class);  startActivity(intent); Intent intent = new Intent();intent.setClass(this,PlayerActivity.class);  startActivity(intent);   Intent intent = new Intent();intent.setClassName(“com.jhuster.videoplayer”,“com.jhuster.videoplayer.PlayerActivity”); startActivity(intent);


隐式启动则是不明确指定启动哪个Activity或者Service,而是通过设置Action、Data、Category,让系统来筛选出合适的目标。


例如拨打电话: 


Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse(“tel:021-80961111”));startActivity(intent);


系统接收到隐式启动请求后,会根据系统中各个Activity在AndroidManifest.xml文件中声明的来比较和判断是否匹配当前的Intent请求的。


因此,如果我们希望PlayerActivity能够被系统隐式启动,则首先需要在AndroidManifest.xml文件中为该Activity添加.


2. 为PlayerActivity添加


的标签有很多,这里只介绍和添加最基本且最常用的三个标签,分别是,


2.1 添加


这个标签是必须添加的,可以自己定义,也可以使用系统预定义的变量,Android系统默认定义了很多action,具体可以查看SDK文档,或者Google一下“android.intent.action.”。


这里,因为我们的类是用来“播放视频”的,因此可以使用系统预定义的:android.intent.action.VIEW,它表示需要启动某个Activity显示指定的数据(包括图片、视频、文档等)。


添加了后的如下所示:


                                    


2.2 添加


category代表类别,定义了Activity的类别,Activity可以设置一个或者多个category标签。常用的一般有3个:DEFAULT,HOME,LAUNCHER


DEFAULT  默认动作HOME     设置为本地桌面应用LAUNCHER 本APP的启动Activity


本应用中我们使用DEFAULT类别即可,DEFAULT也是category最常用的选项。


添加了category后的如下所示:


                                            


2.3 添加


data 代表数据源,是中最复杂的标签,因为不同的Activity支持的数据来源和类型多种多样,所以需要通过详细的data标签信息来指明。


data 标签有很多属性,包括:

android:host: 指定主机名,例如:google.comandroid:port:  制定主机端口,例如: 80android:path:  指定URL的有效路径值,例如: /index/examplesandroid:mimeType: 指定组件可以执行的数据类型,例如:p_w_picpath/jpeg,video/*android:scheme: 指定特定的模式,例如:content,http


这里,假设我们的视频播放器支持多种数据来源,包括:本地视频文件,本地媒体URL,网络视频流(HTTP、RTMP、RTSP协议),另外,假设我们的视频播放器只支持mp4和3gpp两种文件格式。


那么,下面我们来添加两种最常用的标签,scheme和mimeType,并且解释每条标签对应的是怎样的一种数据来源或者数据格式。


(1)


这里的xxx可以是:file,content,网络协议(HTTP,RTMP、RTSP等)


本应用中我们给PlayerActivity的中添加:



添加了这样几条data标签项之后,如果隐式Intent中的数据来源URL是以“file://”、“content://”、“http://”、“rtsp://”开头的URL资源,都会隐式地启动我们的PlayerActivity。


例如,其他的Activity可以通过下面的方法来隐式启动我们的PlayerActivity.


Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setData(Uri.fromFile(new File("/sdcard/test.3gp")));startActivity(intent);


Uri.fromFile这条语句会把指定的文件位置转换为以“file://”开头的Uri对象,如上述例子最终得到的URL为:“file:///sdcard/test.3gp”


同理,可以通过Uri.parse来转换我们常见的网络地址字符串为Uri对象,例如:


Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setData(Uri.parse("http://ticktick.blog.51cto.com/test.mp4"));startActivity(intent);


(2)


mimeType用来设置数据类型,例如图像数据(p_w_picpath/png或者p_w_picpath/*),视频数据(video/mp4或者video/*),如果使用*代表匹配所有的子类型。


MIME TYPE是互联网的一种标记数据类型的标准,现在已经支持非常多的类型了,这里我不一一列举,大家可以在Google上搜索一下。


本应用中我们假设需要支持的是mp4和3gpp两种类型,那么,我们可以添加这样两条 mimeType :



那么,其他的Activity就可以通过下面的方法来隐式启动我们的PlayerActivity. 注意,当已经添加了mimeType之后,隐式Intent必须设置Type参数才能匹配到该Activity,所以建议使用setDataAndType方法,而不是单一的setData方法。


Intent intent = new Intent(Intent.ACTION_VIEW);        intent.setDataAndType(Uri.fromFile(new File("/sdcard/test.3gp")),"video/3gpp");startActivity(intent);


当然,这里的"video/3gpp"也可以写成:"video/*",但这样可能会匹配到一些不支持3gpp的播放器。


(3) 小结


添加了标签后的如下所示:


                                                                                                            


3.  在PlayerActivity中获取参数


通过上面的介绍,我们已经知道了怎样添加以及怎样通过隐式Intent来调用我们的PlayerActivity,那么,下面我们还要了解如何在PlayerActivity中解析来自隐式Intent的参数


其实,Intent提供了很多方法可以Get相关的参数信息,例如:


public String getAction();public Uri    getData();public String getScheme();public String getType();


上述方法分别可以获取Intent的Action,Data Uri,Scheme和MimeType值。


对于“file://”开头的Uri对象,我们可以通过Uri.getPath方法得到去除了“file://”前缀的具体文件地址。例如: “file:///sdcard/test.mp4”则可以转换为实际的“/sdcard/test.mp4”。


对于网络码流,例如:“http://”、“rtsp://”等开头的Uri,则可以直接通过toString()方法转换为实际地址的字符串。


而对于“content://”开头的URI对象,一般是从系统的媒体数据库中检索出来的结果,因此需要反向查找得到实际的文件地址,这里提供一个函数进行转换。


public static String getVideoPath(Context context, Uri uri) {            Uri videopathURI = uri;    if (uri.getScheme().toString().compareTo("content") == 0 ) {              Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);        if (cursor.moveToFirst()) {            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);            videopathURI = Uri.parse(cursor.getString(column_index));            return videopathURI.getPath();        }    }    else if (uri.getScheme().compareTo("file") == 0 ) {        return videopathURI.getPath();    }        return videopathURI.toString();}


4.  总结


到这里算是把隐式Intent的重要知识点都讲清楚了,本文的示例代码请到我的Github下载(地址在本文开头)有不清楚或者错误的地方,欢迎大家留言讨论或者来信lujun.hust@gmail.com交流,或者关注我的新浪微博 @卢_俊 获取最新的文章和资讯。另外转载请著名本文作者和出处(ticktick),谢谢。


更多相关文章

  1. 如何快速学习一门新技术
  2. Android(安卓)Volley完全解析(一),初识Volley的基本用法
  3. Android(安卓)使用Settings 数据库demo(源码)以及adb 读写settings
  4. Android(安卓)基础知识+app测试权限问题
  5. 【Android(安卓)界面效果25】android中include标签的使用
  6. 写给初学者Android(安卓)AIDL必看内容
  7. Android性能优化-布局优化
  8. Android(安卓)FileProvider详细解析和踩坑指南
  9. 2017.03.12 Android卡顿分析

随机推荐

  1. 安卓布局详解
  2. Android(安卓)蓝牙操作--读取远程已配对的
  3. Android初级教程 - DatePicker的使用(日历
  4. Android中定义接口的方法
  5. android 显示通知栏
  6. android用户界面教程实例汇总
  7. Android(安卓)Studio Error:Unable to re
  8. Android中的Typeface
  9. Android获取CPU信息(主频,使用率)
  10. weex android 选择文件 拍照 获得uri 并