Intent 属性详解(上)

Android应用将会根据Intent来启动指定组件,至于到底启动哪个组件,则取决于Intent的各属性。本期将详细介绍Intent的各属性值,以及 Android如何根据不同属性值来启动相应的组件。

Intent 对象大致包含 Component、Action、Category、Data、Type、Extra 和 Flag 这 7 种属性,其中Component用于明确指定需要启动的目标组件,而Extra则用于携带需要交换的数据。

一、Component属性

Intent 的 Component 属性需要接受一个 ComponentName 对象,ComponentName 对象包含如下几个构造器。

  • ComponentName(String pkg, String cls):创建pkg所在包下的cls类所对应的组件。
  • ComponentName(Context pkg, String cls):创建pkg所对应的包下的cls类所对应的组件。
  • ComponentName(Context pkg, Class<?> cls):创建 pkg 所对应的包下的 cls 类所对应的组件。

上面几个构造器的本质是相同的,这说明创建一个ComponentName需要指定包名和类名。这样就可以唯一地确定一个组件类,这样应用程序即可根据给定的组件类去启动特定的组件。

除此之外,Intent还包含了如下三个方法。

  • setClass(Context packageContext, Class<?> cls):设置该 Intent 将要启动的组件对应的类。
  • setClassName(Context packageContext, String className):设置该 Intent 将要启动的组件对应的类名。
  • setClassName(String packageName, String className):设置该 Intent 将要启动的组件对应的类名。

指定Component属性的Intent已经明确了它将要启动哪个组件,因此这种Intent也被称为显式Intent,没有指定Component属性的Intent被称为隐式Intent。

下面的示例程序示范了如何通过显式Intent (指定了 Component属性)来启动另一个 Activity。该程序的界面布局很简单,界面中只有一个按钮,用户单击该按钮将会启动第二个Activity。此处不再给出该程序的界面布局文件。该程序的Java代码如下:

public class MainActivity extends AppCompatActivity {   
 @Override    protected void onCreate(Bundle savedInstanceState) {      
   super.onCreate(savedInstanceState);        
   setContentView(R.layout.activity_main);

        Button startBtn = (Button) findViewById(R.id.start_btn);        // 为bn按钮绑定事件监听器        
        startBtn.setOnClickListener(new View.OnClickListener() {          
          @Override            
          public void onClick(View arg0) {                // 创建一个ComponentName对象          
                ComponentName comp = new ComponentName(MainActivity.this, SecondActivity.class);  
                Intent intent = new Intent();                // 为Intent设置Component属性                
                intent.setComponent(comp);                
                startActivity(intent);            }      
             });  
 }}

上面程序中的onClick回调方法里面的代码用于创建ComponentName对象,并将该对象设置成Intent 对象的Component属性,这样应用程序即可根据该Intent的意图去启动指定组件。 实际上,这几行关键代码完全可以简化为如下形式:

// 根据指定组件类来创建
IntentIntent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);

从上面的代码可以看出,当需要为Intent设置Component属性时,实际上Intent己经提供了一个简化的构造器,这样方便程序直接指定启动其他组件。

当程序通过Intent的Component属性(明确指定了启动哪个组件)启动特定组件时,被启动组件几乎不需要使用<intent-filter.../>进行配置。

程序的SecondActivity也很简单,它的界面布局中只包含一个简单的文本框,用于显示该 Activity对应的Intent的Component属性的包名、类名。该Activity的Java代码如下:

public class SecondActivity extends AppCompatActivity {    
@Override    protected void onCreate(Bundle savedInstanceState) {     
   super.onCreate(savedInstanceState);        
   setContentView(R.layout.activity_second);

        TextView showTv = (TextView) findViewById(R.id.show_tv);        // 获取该Activity对应的Intent的Component属性        
        ComponentName comp = getIntent().getComponent();        // 显示该ComponentName对象的包名、类名        
        showTv.setText("组件包名为:" + comp.getPackageName() + "\n组件类名为:" + comp.getClassName()); 
}}

运行上面的程序,通过第一个Activity中的按钮进入第二个Activity中,将可以看到下图所示的界面。

二、Action属性

Intent的Action属性的值是一个普通的字符串,代表该Intent所要完成的一个抽象动作。

Action要完成的只是一个抽象动作,这个动作具体由哪个组件(或许是Activity,或许是 BroadcastReceiver)来完成,Action这个字符串本身并不管。比如Android提供的标准Action: Intent.ACTION_VIEW,它只表示一个抽象的查看操作,但具体查看什么、启动哪个Activity 来查看,Intent.ACTION_VIEW并不知道——这取决于Activity的<intent-filter.../>配置,只要某个Activity的<intent-filter.../>配置中包含了该ACTION_VIEW,该Actvitiy就有可能被启动。

下面通过一个简单的示例来示范Action属性(就是普通字符串)的作用。下面程序的第一个Activity非常简单,它只包括一个普通按钮,当用户单击该按钮时,程序会“跳转”到第二个Activity。但第一个Activity指定跳转的Intent时,并不指定要跳转的目标Activity,而是为Intent指定Action属性。此处不给出界面布局的代码,第一个Activity 的Java代码如下:

public class MainActivity extends AppCompatActivity { 
   private static final String TEST_ACTION = "com.jinyu.cqkxzsxy.android.intent.action.TEST_ACTION";    
   @Override    
   protected void onCreate(Bundle savedInstanceState) {       
    super.onCreate(savedInstanceState);        
    setContentView(R.layout.activity_main);        
    Button startBtn = (Button) findViewById(R.id.start_btn);        // 为bn按钮绑定事件监听器        
    startBtn.setOnClickListener(new View.OnClickListener() {            
     @Override            
     public void onClick(View arg0) {                // 创建Intent对象                
     Intent intent = new Intent();                // 为Intent设置Action属性(属性值就是一个普通字符串)  
     intent.setAction(MainActivity.TEST_ACTION);                
     startActivity(intent);    
     }       
   }); 

}}

上面程序中的onClick回调方法里面的代码指定了根据Intent来启动Activity。但该Intent并未指定要启动哪个Activity,从上面程序中的代码无法看出该程序将要启动哪个Activity。那么到底程序会启动哪个Activity呢?这取决于Activity配置中 <intent-fiIter.../>元素的配置。

<intent-filter.../>元素是 AndroidManifest.xml 文件中<activity.../>元素的子元素,前面已经学习过,<activity.../>元素用于为应用程序配置 Activity,<activity.../>的<intent-filter.../>子元素则用于配置该Activity所能“响应”的Intent。

<intent-filter.../>元素里通常可包含如下子元素。

  • 0〜N个<action.../>子元素。
  • 0〜N个<category…/>子元素。
  • 0〜1个<data.../>子元素。

<action.../>、<category.../>子元素的配置非常简单,它们都可指定android:name属性,该属性的值就是一个普通字符串。当<activity.../>元素的<intent-fiIter.../>子元素里包含多个<action.../>子元素(相当于指定了多个字符串)时,就表明该Activity能响应Action属性值为其中任意一个字符串的Intent。

由于上面的程序指定启动Action属性为MainActivity.TEST_ACTION常量的 Activity,也就要求被启动的 Activity 对应的配置元素的<intent-filter.../>元素里至少包括一个<action.../>子元素。另外上面程序中的代码并未指定目标Intent的Category属性,但该Intent 已有一个值为 android.intent.category.DEFAULT 的 Category 属性值,因此被启动 Activity 对应的配置元素的<intent-filter.../>元素里至少还包括一个如下的<category.../>子元素。被启动的Activity的完整配置如下:

        <activity android:name=".SecondActivity">           
         <intent-filter>             
           <!-- 指定该Activity能响应Action为指定字符串的Intent -->              
             <action android:name="com.jinyu.cqkxzsxy.android.intent.action.TEST_ACTION" />     
           <!-- 指定该Activity能响应Action属性为helloWorld的Intent -->               
           <action android:name="helloWorld" />           
                <category android:name="android.intent.category.DEFAULT" />            
         </intent-filter>        
       </activity>

上面Activity配置的代码指定该Activity能响应具有指定Action属性值、默认 Category属性值的Intent。其中有一行代码只是试验用的,对于本程序没有影响——它表明该Activity能响应Action属性值为helloWorld字符串、Category属性值为 android.intent.category.DEFAULT的Intent,但我们的程序并未尝试启动这样的Activity,可以自己尝试用这样的Intent来启动Activity,将会看到程序也会启动该Activity。

上面的配置代码中配置了一个实现类为SecondActivity的Activity,因此程序还应该提供这个Activity代码。代码如下:

public class SecondActivity extends AppCompatActivity { 
   @Override    
   protected void onCreate(Bundle savedInstanceState) {        
     super.onCreate(savedInstanceState);        
     setContentView(R.layout.activity_second);        
     TextView showTv = (TextView) findViewById(R.id.show_tv);        // 获取该Activity对应的Intent的Action属性        
     String action = getIntent().getAction();        // 显示Action属性        
     showTv.setText("Action为:" + action);    
}}

上面的程序代码很简单,它只是在启动时把启动该Activity的Intent的Action属性值显示在指定文本框内。

运行上面的程序,单击程序中的“启动指定 Action、默认Category对应的Activity”按钮,将看到下图所示界面。

实际上Android内部提供了大量标准的Action常量,其中用于启动Activity的标准的Action常量及对应的字符串如下表所示。

Action常量

对应的字符串

简单说明

ACTION_MAIN

android.intent.action.MAIN

应用程序入口

ACTION_VIEW

android.intent.action.VIEW

査看指定数据

ACTION_ATTACH_DATA

android.intent.action.ATTACHDATA

指定某块数据将被附加到其他地方

ACTION_EDIT

android.intent.action.EDIT

编辑指定数据

ACTION_PICK

android.intent.action.PICK

从列表中选择某项,并返回所选的数据

ACTION_CHOOSER

android.intent.action.CHOOSER

显示一个Activity选择器

ACTION_GET_CONTENT

android.intent.action.GET_CONTENT

让用户选择数据,并返回所选数据

ACTION_DIAL

android.intent.action.DIAL

显示拨号面板

ACTION_CALL

android.intent.action.CALL

直接向指定用户打电话

ACTION_SEND

android.intent.action.SEND

向其他人发送数据

ACTION_SENDTO

android.intent.action.SENDTO

向其他人发送消息

ACTION_ANSWER

android.intent.action.ANSWER

应答电话

ACTION_INSERT

android.intent.action.INSERT

插入数据

ACTION_DELETE

android.intent.action.DELETE

刪除数据

ACTION_RUN

android.intent.action.RUN

运行数据

ACT10N_SYNC

android.intent.action.SYNC

执行数据同步

ACTION_PICK_ACTIVITY

android.intent.action.PICKACTIVITY

用于选择Activity

ACTION_SEARCH

android.intent.action.SEARCH

执行搜索

ACTION_WEB_SEARCH

android.intent.action.WEBSEARCH

执行Web搜索

ACTION_FACTORY_TEST

android.intent.action.FACTORYTEST

工厂测试的入口点

三、Category属性

Intent的Category属性的值也是一个普通的字符串,用于为Action增加额外的附加类别信息。通常Action 属性与Category属性结合使用。

一个Intent对象最多只能包括一个Action属性,程序可调用Intent的 setAction(String str)方法来设置Action属性值;但一个Intent对象可以包括多个Category属性, 程序可调用Intent的addCategory (String str)方法来为Intent添加Category属性。当程序创建 Intent时,该Intent默认启动Category属性值为Intent.CATEGORY_DEFAULT常量(常量值为 android.intent.category.DEFAULT)的组件。

接下来的示例程序将会示范Category属性的用法。该程序的第一个Activity的代码如下:

public class MainActivity extends AppCompatActivity {    
private static final String TEST_ACTION = "com.jinyu.cqkxzsxy.android.intent.action.TEST_ACTION";    
private static final String TEST_CATEGORY = "com.jinyu.cqkxzsxy.android.intent.category.TEST_CATEGORY";   
 @Override    
 protected void onCreate(Bundle savedInstanceState) {     
    super.onCreate(savedInstanceState);        
    setContentView(R.layout.activity_main);        
    Button startBtn = (Button) findViewById(R.id.start_btn);        // 为bn按钮绑定事件监听器        
    startBtn.setOnClickListener(new View.OnClickListener() {            
    @Override           
     public void onClick(View arg0) {                // 创建Intent对象                
     Intent intent = new Intent();                // 为Intent设置Action属性(属性值就是一个普通字符串)                
     intent.setAction(MainActivity.TEST_ACTION);                // 添加Category属性                
     intent.addCategory(MainActivity.TEST_CATEGORY);                
     startActivity(intent);           
      }       
   });  
 }}

上面程序中的onClick回调方法里面的代码指定了该Intent的Action属性值为com.jinyu.cqkxzsxy.android.intent.action.TEST_ACTION字符串,并为该 Intent 添加 了 字符串为com.jinyu.cqkxzsxy.android.intent.category.TEST_CATEGORY属性。这意味着上面的程序所要启动的目标Activity里应该包含 <action.../> 子元素和<category.../>子元素。

下面是程序要启动的目标Action所对应的配置代码:

        <activity android:name=".SecondActivity">           
         <intent-filter>                
         <!-- 指定该Activity能响应action为指定字符串的Intent -->                
         <action android:name="com.jinyu.cqkxzsxy.android.intent.action.TEST_ACTION" />                
         <!-- 指定该Activity能响应category为指定字符串的Intent -->                
         <category android:name="com.jinyu.cqkxzsxy.android.intent.category.TEST_CATEGORY" />         
         <!-- 指定该Activity能响应category为android.intent.category.DEFAULT的Intent -->              
         <category android:name="android.intent.category.DEFAULT" />           
         </intent-filter>        
       </activity>

上面配置Activity时也指定该Activity的实现类为SecondActivity,该实现类的代码如下:

public class SecondActivity extends AppCompatActivity {  
  @Override    
  protected void onCreate(Bundle savedInstanceState) {       
   super.onCreate(savedInstanceState);        
   setContentView(R.layout.activity_second);        
   TextView showTv = (TextView) findViewById(R.id.show_tv);        // 获取该Activity对应的Intent的Action属性        
   String action = getIntent().getAction();        // 获取该Activity对应的Intent的Category属性        
   Set<String> cates = getIntent().getCategories();        // 显示Category属性        
   showTv.setText("Action为:" + action + "\nCategory属性为:" + cates);   
}}

上面的程序也很简单,它只是在启动时把启动该Activity的Intent的Action、Catetory属 性值分别显示在不同的文本框内。

运行上面的程序,单击程序中的“启动指定Action、指定 Category对应的Activity”按钮,将看到下图所示的界面。

实际上Android内部也提供了大量标准的Catetory常量,其中标准的Category常量及对应的字符串如下表所示。

Catetory常量

对应的字符串

简单说明

CATEGORY_DEFAULT

android.intent.category.DEFAULT

默认的Category

CATEGORY_BROWSABLE

android.intent.category.BROWSABLE

指定该Activity能被浏览器安全调用

CATEGORY_TAB

android.intent.category.TAB

指定Activity作为TabActivity 的Tab页

CATEGORY_LUNCHER

android.intent.category.LAUNCHER

Activity显示顶级程序列表

CATEGORY_INFO

android.intent.category.INFO

用于提供包信息

CATEGORY_HOME

android.intent.category.HOME

设置该Activity随系统启动而运行

CATEGORY_PREFERENCE

android.intent.category.PREFERENCE

该Activity是参数面板

CATEGORY_TEST

android.intent.category.TEST

该Activity是一个测试

CATEGORY_CAR_DOCK

android.intent.category.CAR_DOCK

指定手机被插入汽车底座(硬件)时运行该Activity

CATEGORY_DESK_DOCK

android.intent.category.DESK_DOCK

指定手机被插入桌面底座(硬件)时运行该Activity

CATEGORY_CAR_MODE

android.intent.category.CAR_MODE

设置该Activity可在车载环境下使用

关于Intent的Component、Action、Category三个属性先分享到这里,如果还不够熟悉,建议多加练习。

由于内容较多,本期先学习到这里,下期接着学习其他四个属性。

原文发布于微信公众号 - 分享达人秀(ShareExpert)

原文发表时间:2017-10-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android先生

我一行代码都不写实现Toolbar!你却还在封装BaseActivity?

距离 上篇文章 的发表时间已经过去两个多月了,这两个月时间里我没写文章但一直在更新着我的 MVPArms 框架,让他逐渐朝着 可配置化集成框架 发展

7410
来自专栏Android干货园

教你轻松几步实现底部导航栏

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/45...

12210
来自专栏Android干货

安卓开发_startActivityForResult的详细用法

36860
来自专栏codelang

纯手工打造Easy支付库

19840
来自专栏项勇

笔记56 | 管理网络的使用

17060
来自专栏Android研究院

强大灵活的WebView代理库-PrimWeb

PrimWeb 是一个代理的WebView基于的 Android WebView 和 腾讯 x5 WebView,容易、灵活使用以及功能非常强大的库,提供了 W...

35630
来自专栏androidBlog

ViewPager,ScrollView 嵌套ViewPager滑动冲突解决

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

2.2K30
来自专栏Vamei实验室

安卓第五夜 维纳斯的诞生

之前各讲中,分别讲解了安卓的开发环境、架构和基本概念。从这一讲开始,我将制作一个简单的应用,并通过逐步升级它的功能,连带出安卓开发的多个情境。 《维纳斯的诞生》...

20970
来自专栏Android-JessYan

我一行代码都不写实现Toolbar!你却还在封装BaseActivity?

原文地址: http://www.jianshu.com/p/75a5c24174b2 qq群:301733278

18340
来自专栏非著名程序员

Android实现两个ScrollView互相联动,同步滚动的效果

最近在做一个项目,用到了两个ScrollView互相联动的效果,简单来说联动效果意思就是滑动其中的一个ScrollView另一个ScrollView也一同跟着滑...

31650

扫码关注云+社区

领取腾讯云代金券