Android开发实践:实战演练隐式Intent的用法

简介:

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


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


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


1. 什么是隐式Intent?


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


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


1
2
3
4
5
6
7
8
9
10
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,让系统来筛选出合适的目标。


例如拨打电话: 


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


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


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


2. 为PlayerActivity添加<intent-filter>


<intent-filter>的标签有很多,这里只介绍和添加最基本且最常用的三个标签,分别是<action>,<category>和<data>。


2.1 添加<action>


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


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


添加了<action>后的<activity>如下所示:


1
2
3
4
5
<activity android:name= "com.jhuster.videoplayer.PlayerActivity" >
     <intent-filter>
         <action android:name= "android.intent.action.VIEW"  />        
     </intent-filter>            
</activity>


2.2 添加<category>


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


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


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


添加了category后的<activity>如下所示:


1
2
3
4
5
6
<activityandroid:name= "com.jhuster.videoplayer.PlayerActivity" >
     <intent-filter>
         <actionandroid:name= "android.intent.action.VIEW"  />        
         <categoryandroid:name= "android.intent.category.DEFAULT"  />
     </intent-filter>            
</activity>


2.3 添加<data>


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


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

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


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


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


(1) <data android:scheme="xxx"/>


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


本应用中我们给PlayerActivity的<Intent-filter>中添加:


1
2
3
4
< data  android:scheme = "file" />
< data  android:scheme = "content" />
< data  android:scheme = "http" />
< data  android:scheme = "rtsp" />


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


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


1
2
3
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对象,例如:


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


(2) <data android:mimeType="xxx"/>


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


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


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


1
2
<data android:mimeType= "video/3gpp" />
<data android:mimeType= "video/mp4"  />


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


1
2
3
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) 小结


添加了<data>标签后的<intent-filter>如下所示:


1
2
3
4
5
6
7
8
9
10
11
12
13
< activity  android:name = "com.jhuster.videoplayer.PlayerActivity" >
     < intent-filter >
         < action  android:name = "android.intent.action.VIEW"  />
         < category  android:name = "android.intent.category.DEFAULT"  />
         < data  android:scheme = "file" />
         < data  android:scheme = "content" />
         < data  android:scheme = "http" />
         < data  android:scheme = "rtsp" />
         < data  android:scheme = "rtmp" />                
         < data  android:mimeType = "video/3gpp"  />
         < data  android:mimeType = "video/mp4"  />
     </ intent-filter >            
</ activity >


3.  在PlayerActivity中获取参数


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


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


1
2
3
4
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对象,一般是从系统的媒体数据库中检索出来的结果,因此需要反向查找得到实际的文件地址,这里提供一个函数进行转换。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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();
}


本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1621957,如需转载请自行联系原作者

相关文章
|
24天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
48 19
|
24天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
52 14
|
27天前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
|
25天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
在数字时代,掌握安卓应用开发技能是进入IT行业的关键。本文将引导读者从零基础开始,逐步深入安卓开发的世界,通过实际案例和代码示例,展示如何构建自己的第一个安卓应用。我们将探讨基本概念、开发工具设置、用户界面设计、数据处理以及发布应用的全过程。无论你是编程新手还是有一定基础的开发者,这篇文章都将为你提供宝贵的知识和技能,帮助你在安卓开发的道路上迈出坚实的步伐。
32 5
|
24天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
25天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
25天前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
25天前
|
搜索推荐 Android开发 开发者
安卓应用开发中的自定义控件实践
在安卓应用开发的广阔天地中,自定义控件如同璀璨的星辰,点亮了用户界面设计的夜空。它们不仅丰富了交互体验,更赋予了应用独特的个性。本文将带你领略自定义控件的魅力,从基础概念到实际应用,一步步揭示其背后的原理与技术细节。我们将通过一个简单的例子——打造一个具有独特动画效果的按钮,来展现自定义控件的强大功能和灵活性。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇通往更高阶UI设计的大门。
|
28天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
25天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
33 0