androdi intent

本文详细解析了Android中Intent的工作原理,包括Intent的构造、如何启动四大组件(Activity、Service、ContentProvider、BroadcastReceiver)、Intent的属性设置及其作用,如Action、Data、Category等,以及如何响应Intent和在组件间传递数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是intent

android 应用主要有四大组建构成(activity、service、content provider、broadcast receiver)而着四个组建是独立的,如果让他们产生联系就需要intent
在这里插入图片描述

intent的构造

先看看简单的实例
显式:


//方式一:
Intent intent = new Intent(Test.this, TestB.class);
startActivity(intent);
//方式二:
Intent intent = new Intent();
intent.setClass(TestBundle.this, Target.class);
intent.putExtras(mBundle); //传递信息
startActivity(intent);

隐式:

//浏览网页 (系统预定义配置)
Uri uri = Uri.parse("http://www.google.com");
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent);

公共构造函数:

  • Intent()   空构造函数
  • Intent(Intent o)   拷贝构造函数
  • Intent(String action)   指定action类型的构造函数
  • Intent(String action, Uri uri)   指定Action类型和Uri的构造函数,URI主要是结合程序之间的数据共享ContentProvider
  • Intent(Context packageContext, Class cls)   传入组件的构造函数
  • Intent(String action, Uri uri, Context packageContext, Class cls)  前两种结合体

通过intent启动四大组建

Activity:
使用Context.startActivity() 或 Activity.startActivityForResult(),传入一个intent来启动一个activity。使用 Activity.setResult(),传入一个intent来从activity中返回结果。
service:
将intent对象传给Context.startService()来启动一个service或者传消息给一个运行的service。将intent对象传给 Context.bindService()来绑定一个service。
Broadcast
将intent对象传给 Context.sendBroadcast(),Context.sendOrderedBroadcast(),或者Context.sendStickyBroadcast()等广播方法,则它们被传给 broadcast receiver。

intent属性的设置

android 通过这些字段来查找符合标准的组建,然后启动他们。

component

Component属性明确指定Intent的目标组件的类名称

通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。这个右脚显示intent,官方不推荐。

实例代码

button1.setOnClickListener(new OnClickListener() {            
            @Override
            public void onClick(View v) {
                //创建一个意图对象
                Intent intent = new Intent();
                //创建组件,通过组件来响应
                ComponentName component = new ComponentName(MainActivity.this, SecondActivity.class);
                intent.setComponent(component);                
                startActivity(intent);                
            }
        });

或者

iIntent intent = new Intent();
//setClass函数的第一个参数是一个Context对象
//Context是一个类,Activity是Context类的子类,也就是说,所有的Activity对象,都可以向上转型为Context对象
//setClass函数的第二个参数是一个Class对象,在当前场景下,应该传入需要被启动的Activity类的class对象
 intent.setClass(MainActivity.this, SecondActivity.class);
 startActivity(intent)

又或者

      Intent intent = new Intent(MainActivity.this,SecondActivity.class);
      startActivity(intent);

Action

在Intent中,Action就是描述做、写等动作的,当你指明了一个Action,执行者就会依照这个动作的指示,接受相关输入,表现对应行为,产生符合的输出。在Intent类中,定义了大量的动作,比如ACTION_VIEW,ACTION_PICK等, 基本涵盖了常用动作。加的动作越多,越精确。

具体的可以查阅android SDK-> reference中的Android.content.intent类,里面的constants中定义了所有的action。

Category

下面是 一个app的manifest文件

<activity 
            android:name=".SecondActivity">
            <intent-filter>
                 <action android:name="com.example.smyh006intent01.MY_ACTION"/>
                 <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>            
        </activity>

如果没有指定的category,则必须使用默认的DEFAULT

只有<action>和<category>中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应Intent。

我们为了让这个app响应,就要在设置intent的时候使用相应的action和category。如果category是android.intent.category.DEFAULT的话就不需要设置category了(系统默认添加的就是这个)

button1.setOnClickListener(new OnClickListener() {            
            @Override
            public void onClick(View v) {
                //启动另一个Activity,(通过action属性进行查找)
                Intent intent = new Intent();
                //设置动作(实际action属性就是一个字符串标记而已)
                intent.setAction("com.example.smyh006intent01.MY_ACTION"); //方法:Intent android.content.Intent.setAction(String action)
                startActivity(intent);        
            }
        });

或者

button1.setOnClickListener(new OnClickListener() {            
            @Override
            public void onClick(View v) {
                //启动另一个Activity,(通过action属性进行查找)
                Intent intent = new Intent("com.example.smyh006intent01.MY_ACTION");//方法: android.content.Intent.Intent(String action)                
                startActivity(intent);        
            }
        });

如果intent 发出了之后,有很多相同的结果。就会弹出来让用户自己选择

对于非android.intent.category.DEFAULT的category:

button1.setOnClickListener(new OnClickListener() {            
            @Override
            public void onClick(View v) {
                //启动另一个Activity,(通过action属性进行查找)
                Intent intent = new Intent();
                //设置动作(实际action属性就是一个字符串标记而已)
                intent.setAction("com.example.smyh006intent01.MY_ACTION"); //方法:Intent android.content.Intent.setAction(String action)
                intent.addCategory("com.example.smyh006intent01.MY_CATEGORY");
                startActivity(intent);        
            }
        });

或者

具体同样可以参考android SDK-> reference中的Android.content.intent类。

Data

Data是用一个uri对象来表示的,uri代表数据的地址,属于一种标识符。通常情况下,我们使用action+data属性的组合来描述一个意图:做什么。通过这种组合我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得Android多个应用程序之间的功能共享成为了可能。比如应用程序中需要展示一个网页,没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要条用系统的浏览器来打开这个网页就行了。

调用系统的浏览器:

button1.setOnClickListener(new OnClickListener() {            
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                Uri data = Uri.parse("http://www.baidu.com");
                intent.setData(data);                
                startActivity(intent);        
            }
        });

或者可以简写成这成这样

button1.setOnClickListener(new OnClickListener() {            
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("http://www.baidu.com"));                
                startActivity(intent);        
            }
        });

上面的Uri.parse负责把字符串变成Uri对象,setData负责添加。这样这个intent会被如下的app回应。

<activity 
            android:name=".SecondActivity">
            <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="http" android:host="www.baidu.com"/>                 
            </intent-filter>            
        </activity>

匹配优先级:

  • 当Intent匹配成功的组件有多个时,显示优先级高的组件,如果优先级相同,显示列表让用户自己选择
  • 优先级从-1000至1000,并且其中一个必须为负的才有效

可以在intent-filter 标签中设置 android:priority

<activity 
            android:name=".SecondActivity">
            <intent-filter android:priority="-1">
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="http" android:host="www.baidu.com"/>                                  
            </intent-filter>            
        </activity>

Type

Type属性用于明确指定Data属性的数据类型或MIME类型,但是通常来说,当Intent不指定Data属性时,Type属性才会起作用,否则Android系统将会根据Data属性值来分析数据的类型,所以无需指定Type属性。

如果Intent对象中既包含Uri又包含Type,那么,在中也必须二者都包含才能通过测试。

data和type属性一般只需要一个,通过setData方法会把type属性设置为null,相反设置setType方法会把data设置为null,如果想要两个属性同时设置,要使用Intent.setDataAndType()方法。

button.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                Uri data = Uri.parse("file:///storage/sdcard0/平凡之路.mp3");
                //设置data+type属性
                intent.setDataAndType(data, "audio/mp3"); //方法:Intent android.content.Intent.setDataAndType(Uri data, String type)
                startActivity(intent);                
            }            
        });

extras

是其它所有附加信息的集合;
使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

Flags

期望这个意图的运行模式。
一个程序启动后系统会为这个程序分配一个task供其使用,另外同一个task里面可以拥有不同应用程序的activity。那么,同一个程序能不能拥有多个task?这就涉及到加载activity的启动模式,这个需要单独讲一下。

注:android中一组逻辑上在一起的activity被叫做task,自己认为可以理解成一个activity堆栈。

intent intent = new Intent(MainActivity.this,SecondActivity.class);
//相当于singleTask
 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
 Intent intent = new Intent(MainActivity.this,SecondActivity.class);
 //相当于singleTop
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

综上可以看出,action、 data/type、category和extras 一起形成了一种语言,这种语言可以是android可以表达出诸如“给张三打电话”之类的短语组合。

android 通过intent filter 来识别这种语言。
在这里插入图片描述

响应intent

通过在AndroidManifest.xm中配置intent-filter可以很好的告诉android 我可以响应生命intent

action :

/*
    < 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>匹配。

category :

/* 
   < 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>声明并不会导致匹配失败。一个没有指定任何类别测试的 Intent-filter仅仅只会匹配没有设置类别的Intent请求。
  
data:

<intent-filter ... >
    <data android:type=”video/mpeg” 
      android:scheme=”http”
      android:host="www.google.com" ... />
</intent-filter>

元素指定了希望接受的Intent请求的数据URI和数据类型,URI被分成三部分来进行匹配:scheme、 authority和path。其中,用setData()设定的Inteat请求的URI数据类型必须与IntentFilter中scheme所指定的一致。若Intent-filter中还指定了authority或path,它们也需要相匹配才会通过测试。

例如:使用Intent激活Android自带的电话拨号程序,通过这个实例你会发现,使用Intent并不像其概念描述得那样难。

Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse(”tel:13800138000));
//创建好Intent之后,你就可以通过它告诉Android希望启动新的Activity了。
startActivity(intent);

利用Intent在Activity之间传递数据

发送:

Bundle bundle = new Bundle();
bundle.putStringArray("NAMEARR", nameArr);
Intent intent = new Intent(Main.this, CountList.class);
intent.putExtras(bundle);
startActivity(intent);

接受:

Bundle bundle = this.getIntent().getExtras();
String[] arrName = bundle.getStringArray("NAMEARR");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值