intent 订阅
Intent(意图)主要是解决Android应用的各项组件之间的通讯。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给被调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。例如,在一个联系人维护的应用中,当我们在一个联系人列表屏幕(假设对应的Activity为listActivity)上,点击某个联系人后,希望能够跳出此联系人的详细信息屏幕(假设对应的Activity为detailActivity)为了实现这个目的,listActivity需要构造一个 Intent,这个Intent用于告诉系统,我们要做“查看”动作,此动作对应的查看对象是“某联系人”,然后调用startActivity (Intent intent),将构造的Intent传入,系统会根据此Intent中的描述,到ManiFest中找到满足此Intent要求的Activity,系统会调用找到的 Activity,即为detailActivity,最终传入Intent,detailActivity则会根据此Intent中的描述,执行相应的操作。 展开全文
Intent(意图)主要是解决Android应用的各项组件之间的通讯。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给被调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。例如,在一个联系人维护的应用中,当我们在一个联系人列表屏幕(假设对应的Activity为listActivity)上,点击某个联系人后,希望能够跳出此联系人的详细信息屏幕(假设对应的Activity为detailActivity)为了实现这个目的,listActivity需要构造一个 Intent,这个Intent用于告诉系统,我们要做“查看”动作,此动作对应的查看对象是“某联系人”,然后调用startActivity (Intent intent),将构造的Intent传入,系统会根据此Intent中的描述,到ManiFest中找到满足此Intent要求的Activity,系统会调用找到的 Activity,即为detailActivity,最终传入Intent,detailActivity则会根据此Intent中的描述,执行相应的操作。
信息
作    用
解决Android应用各项组件的通讯
提供信息
组件互相调用的相关信息
实现目的
调用者与被调用者之间的解耦
中文名
意图
性    质
媒体中介
外文名
intent
intent术语解释
在Android参考文档中,对Intent的定义是执行某操作的一个抽象描述(确实很抽象)。我们先来看看这里的抽象描述,到底描述了什么。首先,是要执行的动作(action)的一个简要描述,如VIEW_ACTION(查看)、EDIT_ACTION(修改)等,Android为我们定义了一套标准动作:MAIN_ACTIONVIEW_ACTIONEDIT_ACTIONPICK_ACTIONGET_CONTENT_ACTIONDIAL_ACTIONCALL_ACTIONSENDTO_ACTIONANSWER_ACTIONINSERT_ACTIONDELETE_ACTIONRUN_ACTIONLOGIN_ACTIONCLEAR_CREDENTIALS_ACTIONSYNC_ACTIONPICK_ACTIVITY_ACTIONWEB_SEARCH_ACTION此外,我们还可以根据应用的需要,定义我们自己的动作,并可定义相应的Activity来处理我们的自定义动作。其次,是执行动作要操作的数据(data),Android中采用指向数据的一个URI来表示,如在联系人应用中,一个指向某联系人的URI可能为:content://contacts/1。这种URI表示,通过 ContentURI这个类来描述,具体可以参考android.net.ContentURI类的文档。以联系人应用为例,以下是一些action / data对,及其它们要表达的意图:VIEW_ACTION content://contacts/1-- 显示标识符为"1"的联系人的详细信息EDIT_ACTION content://contacts/1-- 编辑标识符为"1"的联系人的详细信息VIEW_ACTION content://contacts/-- 显示所有联系人的列表PICK_ACTION content://contacts/-- 显示所有联系人的列表,并且允许用户在列表中选择一个联系人,然后把这个联系人返回给父activity。例如:电子邮件客户端可以使用这个Intent,要求用户在联系人列表中选择一个联系人另外,除了action和data这两个重要属性外,还有一些附加属性:category(类别),被执行动作的附加信息。例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。type(数据类型),显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。component(组件),指定Intent的的目标组件的类名称。通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。extras(附加信息),是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。总之,action、 data/type、category和extras 一起形成了一种语言。这种语言使系统能够理解诸如“查看某联系人的详细信息”之类的短语。随着应用不断的加入到系统中,它们可以添加新的action、 data/type、category来扩展这种语言。应用也可以提供自己的Activity来处理已经存在的这样的“短语”,从而改变这些“短语”的行为。
收起全文
精华内容
下载资源
问答
  • Intent

    千次阅读 2013-08-14 17:49:29
    在android中,intent就像是一个邮差,辛勤高效的在各个组件之间来回穿梭。我们可以通过它启动一个Activity或者Service,或者是发送给广播组件,又或者是与后台的Service进行通信。所谓的Intent,字面意思就是"意图,...

          在android中,intent就像是一个邮差,辛勤高效的在各个组件之间来回穿梭。我们可以通过它启动一个Activity或者Service,或者是发送给广播组件,又或者是与后台的Service进行通信。所谓的Intent,字面意思就是"意图,目的",在android中的定义就是一个动作的抽象描述,类似于接口是抽象的行为协议一样,但这两者在实现上是不同的东西。

          即使是好的邮差,如果没有邮递地址,依然无法正确的将货物送到指定的地方。这个完全交给系统来处理,它会帮Intent寻找合适的邮递地址,像是发送给Activity的Intent就会准确的发送给该Activity,发送个各个广播的Intent就会发送给指定的广播,从不会出错。

    一.Intent的组成

          Intent所包含的信息主要包括两个方面:action和data。

          action就是所要执行的动作,像是我们经常在根文件中声明的Activity的动作:ACTION_MAIN,表示应用程序的入口。action通常是一个大写表示的字符串,用来简要的描述动作,当然,我们也可以自定义自己应用的Intent,不过在使用的时候必须指定全称,也就是包名。

          正如方法签名包含了参数和返回值一样,action的名字也必须尽量包含了该action的信息,所以在自定义自己的action的时候,名字是非常重要的,必须尽可能的与其他的action区分开来,而且还要将该名字与intent的其他部分紧密的结合在一起,简而言之,不是单独的定义action,而是要定义其他组件能够处理的完整协议。

          我们可以通过setAction()来设置action和通过getAction()来获取action。

           一般的action像是这样:

    public static final String ACTION_DIAL = "android.intent.action.DIAL"

          data是我们的动作所要操作的数据,通常是以Uri的形式表示。data并不是单独的出现,它们经常和action成对出现,像是这样:ACTION_VIEW content://contacts/people/1,就是用于展现手机中通讯录标识为1的人的信息,而且还提示了数据的存放地点是在设备上,并且是由content provider所控制。

          当一个Intent被发送给适合的组件时,我们除了要知道data的Uri之外,还必须知道数据的类型,也就是MIME type。我们可以显式地指明data的Uri和MIME type,可以通过setData()指明数据的uri,setType()指明数据的MIME type,setDataAndType()指明数据的Uri和MIME type,getData()用于获取Uri,而getType()用于获取type。

          除了上面的主要属性外,Intent还可以包含其他信息:category,type,component和extras。

          category给出了action执行的其他信息,像是CATEGORY_LAUNCHER表示目标Activity是应用程序中最优先被执行的Activity,也就是所谓的top-level Activity。还有CATEGORY_HOME,表示的就是手机开机启动后或者按下HOME键后显示的Activity,CATEGORY_BROWSABLE表示的就是能通过在网页浏览器中点击链接而激活的Activity,而CATEGORY_PREFERENCE表示Activity是用于设置的Activity。

          type是显式的指明data的MIME type,一旦指明了type,就只能使用该类型的data。

          component是显式的指明了使用Intent的组件,这时其他属性的设置就是可选的,因为它们的设置都是为了方便寻找合适的组件。

          extras正如字面意思,就是额外的信息,它们使用Bundle类型进行数据传递,也就是键值对,像是time-zone代表的就是新的时间区域。通常它代表的是Intent的扩展信息,像是我们的action如果能够发送邮件,那么我们可以将邮件的标题和内容放在extras里面。

          像是这样:

    Bundle bundle = new Bundle();
    intent.putExtras(bundle);

         flags的作用像是告诉系统应该如何启动Activity,或者在启动后应该如何处理该Activity等。

     二.Intent的使用

          Intent可以分为两类:显式的Intent和隐式的Intent。

          显式的Intent指定了使用Intent的组件,所以它并不需要其他信息。通常它使用在应用程序的内部,像是启动应用程序的其他Activity或者内部定义的Service。

          隐式的Intent并没有指定组件,所以它需要更加详细的信息以确保系统能够发送给正确的组件。但是这些还是不够的,组件本身还是要提供信息来确保它接收到正确的Intent,这就是intent-filter的作用。我们经常在根文件中注册一个组件的时候,指明它的intent-filter,像是在程序中使用广播组件的时候,我们可以显式的指明intent-filter,像是这样:registerReceiver(BroadcastReceiver, IntentFilter)。

          我们在声明intent-filter的时候,通常只需要指定三个属性:action,data和category,但是一般情况下我们有时候也不会完整的设定这三个属性,像是只设定action和category,那么这时的filter就只会匹配没有data的intent。在intent-filter中的data还进一步划分成几个属性:type,scheme,authority和path。type就是我们熟悉的MIME type,我们简单的讲解一下其他我们不熟悉的属性。

           所谓的sheme就是我们上面讲的content:Uri等信息,值得注意的是,如果我们只是声明了scheme而没有声明type的话,那么filter就只会匹配没有type的Intent,而像是content:Uri是不会被匹配的,因为content provider在存储的时候是有保存MIME type的信息,所以如果没有提供type的话,是无法从里面提取出data。如果我们只提供type而没有提供scheme的话,那就表示匹配没有Uri或者包含content:Uri和file:Uri的Intent。如果scheme和type都没有,那么匹配的将会是没有data或者type的Intent。值得注意的是,当我们需要指定authority的时候,authority的scheme列表和我们的intent-filter的scheme列表必须相同,而path则需要包括authority和scheme列表。

          我们来一个例子:

    content://com.example.project:200/folder/subfolder/etc

           其中,content就是scheme,com.example.project就是host,而200是port,path就是folder/subfolder/etc,host和port加起来就是URI authority,但注意,如果host没有指定,那么port也是没有必要的。

          以上介绍的属性都是可选的,但这并不意味着它们是独立的:如果想要声明一个authority,那么scheme就是必要的。如果想要声明一个path,scheme和authority都是必要的。

           我们再来看一个例子:

    <intent-filter>
         <data android:mimeType="audio/mpeg"/>
    </intent-filter>

          这里我们可以使用audio/*,这就表示audio的所有子类型都可以匹配。

          像是这样:

    <data android:scheme="http" android:type="video/*"/>

          表示我们的数据类型是video,然后可以通过网络来获取。

          在实际的应用中,我们使用隐式的Intent比较多,之所以使用隐式的Intent,是因为我们想要让系统来决定哪个组件是最适合该Intent的,通常系统会比人更加清楚什么才是最适合的,只要我们给出的信息足够详细。

           最好的情况就是我们在注册一个组件的时候,如果希望它接收Intent,那么就必须在根文件中声明它的intent-filter,这样无论是显式的还是隐式的Intent它都能接收到,如果没有,那么它只会接收显式的Intent。

          IntentFilter并不像它的名字一样,具有过滤保护的作用,因为它无法阻止显式的Intent发送给组件,它只能阻止隐式的Intent发送给该组件。

          一个intent-filter可以包含多个action:

    <intent-filter>
          <action android:name="android.intent.action.VIEW"/>
          <action android:name="android.intent.action.EDIT"/>
          <action android:name="android.intent.action.PICK"/>
          <category android:name="android.intent.category.DEFAULT"/>
          <data android:mimeType="vnd.android.cursor.dir/vnd.google.note"/>
    </intent-filter>

          这个filter声明了很多action,它允许用户view或者edit目录,也允许从目录中pick一个note出来。
          值得注意的是,filter声明了DEFAULT这个category。之所以声明为DEFAULT,是因为Context.startActivity()和Activity.startActivityForResult()这两个方法都默认Intent包含DEFAULT这个category,除了两个例外情况:显式的声明目标activity的名字和包含action-MAIN和category-LAUNCHER的Intent。

          这里还有一个特别的东西:data的mimeType。我们看到,这里的的mimeType声明为vnd.android.cursor.dir/vnd.google.note,说明我们可以从Content Provider中获取Cursor并进一步获取Note Pad的数据。

          最后发送给Activity的Intent大概像是这样子:

          {action:android.intent.action.VIEW data:content://com.google.provider.NotePad/notes}

          {action:android.intent.action.PICK data:content://com.google.provider.NotePad/notes}

          {action:android.intent.action.EDIT data:content://com.google.provider.NotePad/notes}

          当然,这里的Intent并不是完整的,还得考虑一下Activity的情况。如果该Activity用于展示所有的数据,Intent就是上面这样子, 但如果只是单独作用于一条数据的Activity,就算intent-filter是一样的,实际上的Intent应该像是这样子:

          {action:android.intent.action.VIEW data:content://com.google.provider.NotePad/notes/ID}

           再来看一个例子:

    <intent-filter android:label="@string/resolve_title">
         <action android:name="com.android.notepad.action.EDIT_TITLE"/>
         <category android:name="android.intent.category.DEFAULT"/>
         <category android:name="android.intent.category.ALTERNATIVE"/>
         <category android:name="android.intent.category.SELECTED_ALTERNATIVE"/>
         <data android:mimeType="vnd.android.cursor.item/vnd.google.note"/>
    </intent-filter>

          这个Filter声明的action是修改title。为了能够支持DEFAULT这个category,我们还必须支持其他两个标准的categories:ALTERNATIVE和SELECTED_ALTERNATIVE。这个Intent大概就是这样子:
          {action:com.android.notepad.action.EDIT_TITLE data:content://com.google.provider.NotePad/notes/ID}

          android系统本身就定义了大量的标准action和category,如果有需要的话,可以自己查阅官方文档。

         接下来我们就针对常见的使用场景来分析如何使用Intent。

    1.Activity的跳转:

    Intent intent = new Intent(Activity1.this, Activity2.class);
    startActivity(intent);

        关于Activity的跳转,还有一个知识点需要补充。我们知道,在android中有一个Task(栈),专门用于存放Activity,它遵循的是"先进后出"的原则,但如果我们不想要遵循这个原则,想要取出指定的Activity,我们就可以利用一个东西:Flag,也就是上面提到的Flag:

    Intent intent = new Intent(Activity1.this, Activity2.class);
    //如果Activity在Task中存在,并且是在最顶端,不会启动新的Activity
    intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
    
    //如果Activity在Task中存在,将Activity上面的所有Activity结束掉
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    
    //默认的跳转类型。将Activity放到一个新的Task中
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
    //如果Activity已经运行到Task,再次跳转不会再运行这个Activity
    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    2.向另一个Activity传递数据:

    Intent intent = new Intent(Activity1.this, Activity2.class);
    Bundle bundle = new Bundle();
    bundle.putString("name", "Jack");
    intent.putExtras(bundle);
    startActivity(intent);

        至于接收数据:

    Bundle bundle = new Bundle();
    String name = bundle.getString("name");

    3.向上一个Activity返回结果,这种情况针对的是startActivityForResult(intent, requestCode)启动的Activity:

    Intent intent = getIntent();
    Bundle bundle = new Bundle();
    bundle.putString("name", "Jack");
    intent.putExtras(bundle);
    setResult(RESULT_OK, intent);

    4.回调上一个Activity的结果处理函数:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
         super.onActivityResult(requestCode, resultCode, data);
         if(requestCode == REQUEST_CODE){
              if(resultCode == RESULT_OK){
                   String temp = null;
                   Bundle bundle = data.getExtras();
                   ....
              }
         }
    }

         接下来就是一些调用官方应用程序的使用场景:
    1.显示网页:

    Uri uri = Uri.parse("http://google.com");  
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);  
    startActivity(intent); 

    2.显示地图:

    Uri uri = Uri.parse("geo:38.899533,-77.036476");  
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);   
    startActivity(intent);   

    3.路径规划:

    Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");  
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);  
    startActivity(intent);  

    4.打电话:
    (1)叫出拨号程序:

    Uri uri = Uri.parse("tel:0800000123");  
    Intent intent = new Intent(Intent.ACTION_DIAL, uri);  

    (2)直接打电话:

    Uri uri = Uri.parse("tel:0800000123");  
    Intent intent = new Intent(Intent.ACTION_CALL, uri);  
    startActivity(intent);  

         这些都要在根文件中声明权限:<user-permission id="android.permission.CALL_PHONE"/>
    5.发送SMS(短信)和MMS(彩信):

    //调用短信程序 
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);  
    intent.putExtra("content", "你好");   
    it.setType("vnd.android-dir/mms-sms");  
    startActivity(intent); 
    //发送短信
    Uri uri = Uri.parse("smsto://0800000123");  
    Intent intent = new Intent(Intent.ACTION_SENDTO, uri);  
    intent.putExtra("content", "你好");  
    startActivity(intent); 
    //发送彩信
    Uri uri = Uri.parse("content://media/external/images/media/23");  
    Intent intent = new Intent(Intent.ACTION_SEND);   
    intent.putExtra("content", "。。。");   
    intent.putExtra(Intent.EXTRA_STREAM, uri);  
    intent.setType("image/png");   
    startActivity(intent);  

    6.发送Email:

    Uri uri = Uri.parse("mailto:xxx@abc.com");  
    Intent intent = new Intent(Intent.ACTION_SENDTO, uri);  
    startActivity(intent);  
    
    
    Intent intent = new Intent(Intent.ACTION_SEND);  
    intent.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");  
    intent.putExtra(Intent.EXTRA_TEXT, "The email body text");  
    intent.setType("text/plain");  
    startActivity(Intent.createChooser(intent, "Choose Email Client"));  
    
    
    Intent intent=new Intent(Intent.ACTION_SEND);    
    String[] tos={"me@abc.com"};    
    String[] ccs={"you@abc.com"};    
    intent.putExtra(Intent.EXTRA_EMAIL, tos);    
    intent.putExtra(Intent.EXTRA_CC, ccs);    
    intent.putExtra(Intent.EXTRA_TEXT, "The email body text");    
    intent.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");    
    intent.setType("message/rfc822");    
    startActivity(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");  sendIntent.setType("audio/mp3");  
    startActivity(Intent.createChooser(intent, "Choose Email Client")); 

    7.播放多媒体:

    Uri uri = Uri.parse("file:///sdcard/song.mp3");  
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);  
    intent.setType("audio/mp3");  
    startActivity(intent); 
    
    Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");  
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);  
    startActivity(intent); 

    8.Market相关:

    //寻找某个应用 
    Uri uri = Uri.parse("market://search?q=pname:pkg_name"); 
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);  
    startActivity(intent);
      
    //显示某个应用的相关信息 
    Uri uri = Uri.parse("market://details?id=app_id");  
    Intent intent = new Intent(Intent.ACTION_VIEW, uri); 
    startActivity(intent); 
     

    9.Uninstall应用程序:

    Uri uri = Uri.fromParts("package", strPackageName, null); 
    Intent intent = new Intent(Intent.ACTION_DELETE, uri);   
    startActivity(intent);  

     

        

     

         

         

         

         

         

         

         

       


    展开全文
  • Intent以及IntentFilter详解

    万次阅读 多人点赞 2016-09-23 16:05:44
    在Android中有四大组件,这些组件中有三个组件与Intent相关,可见Intent在Android整个生态中的地位高度。Intent是信息的载体,用它可以去请求组件做相应的操作,但是相对于这个功能,Intent本身的结构更值得我们去...

    转载注明出处:http://blog.csdn.net/xiaohanluo/article/details/52637520

    1. 前言

           在Android中有四大组件,这些组件中有三个组件与Intent相关,可见Intent在Android整个生态中的地位高度。Intent是信息的载体,用它可以去请求组件做相应的操作,但是相对于这个功能,Intent本身的结构更值得我们去研究。

    2. Intent与组件

           Intent促进了组件之间的交互,这对于开发者非常重要,而且它还能做为消息的载体,去指导组件做出相应的行为,也就是说Intent可以携带数据,传递给Activity/Service/BroadcastReceiver。

    • 启动Activity。Activity可以简单的理解为手机屏幕中的一个页面,你可以通过将Intent传入startActivity方法来启动一个Activity的实例,也就是一个页面,同时,Intent也可以携带数据,传递给新的Activity。如果想要获取新建的Activity执行结果,可以通过onActivityResult()方法去启动Activity。
    • 启动Service。Service是一个不呈现交互画面的后台执行操作组件,可以通过将Intent穿入startService()方法来启动一个Service来启动服务。
    • 传递广播BroadCast。广播是任何应用都可以接收到的消息,通过将Intent传递给 sendBroadcast()sendOrderedBroadcast()sendStickyBroadcast()方法,可以将广播传递接收方。

    3. Intent类型

    在Android中,Intent分为两种类型,显式和隐式。

    • 显式Intent,可以通过类名来找到相应的组件,在应用中用显式Intent去启动一个组件,通常是因为我们知道这个组件(Activity或者Service)的名字。如下代码,我们知道具体的Activity的名字,要启动一个新的Activity,下面就是用的显示Intent。

      Intent intent = new Intent(context,XXActivity.class);
      startActivity(intent);
      
    • 隐式Intent,不指定具体的组件,但是它会声明将要执行的操作,从而匹配到相应的组件。最简单的Android中调用系统拨号页面准备打电话的操作,就是隐式Intent。

      Intent intent = new Intent(Intent.ACTION_DIAL);
      Uri data = Uri.parse("tel:" + "135xxxxxxxx");
      intent.setData(data);
      startActivity(intent);
      

    使用显示Intent去启动Activity或者Service的时候,系统将会立即启动Intent对象中指定的组件。

           使用隐式Intent的时候,系统通过将Intent对象中的IntentFilter与组件在AndroidManifest.xml或者代码中动态声明的IntentFilter进行比较,从而找到要启动的相应组件。如果组件的IntentFilter与Intent中的IntentFilter正好匹配,系统就会启动该组件,并把Intent传递给它。如果有多个组件同时匹配到了,系统则会弹出一个选择框,让用户选择使用哪个应用去处理这个Intent,比如有时候点击一个网页链接,会弹出多个应用,让用户选择用哪个浏览器去打开该链接,就是这种情况。

           IntentFilter通常是定义在AndroidManifest.xml文件中,也可以动态设置,通常是用来声明组件想要接受哪种Intent。例如,你如果为一个Activity设置了IntentFilter,你就可以在应用内或者其他应用中,用特定的隐式Intent来启动这个Activity,如果没有为Activity设置IntentFilter,那么你就只能通过显示Intent来启动这个Activity。

    注意,为了确保系统的稳定性,官方建议使用显示Intent来启动Service,同时也不要为Service设置IntentFilter,因为如果使用隐式Intent去启动Service,我们并不知道那些服务会响应Intent,而且由于服务大多是不可见的,我们也不知道那些服务被启动了,这是非常危险的。在Android 5.0(API 21)以后,如果使用隐式的Intent去调用bindService()方法,系统会抛出异常。

    4. Intent的属性

           Intent作为消息的载体,系统根据它去决定启动哪个具体的组件同时将组件执行中需要的信息传递过去。Intent能够包含的属性有Component、Action、Data、Category、Extras、Flags,关于这些属性的更详细信息可查看这里

    • Component,要启动的组件名称。这个属性是可选的,但它是显式Intent的一个重要属性,设置了这个属性后,该Intent只能被传递给由Component定义的组件。隐式Intent是没有该属性的,系统是根据其他的信息(例如,Action、Data等)来判断该Intent应该传递给哪个组件。这个属性是目标的组件的具体名称(完全限定类名),例如,com.example.DemoActivity。该属性可以通过setComonentName()setClass()setClassName()或者Intent的构造函数来设置。
    • Action,表明执行操作的字符串。它会影响Intent的其余信息,比如Data、Extras。该属性可以通过setAction()方法或者Intent的构造函数来设置。用户可以自定义这个属性,也可以使用系统中已经有的Action值。下面列出启动Activity时候的一些通用Action属性。
      • ACTION_VIEW,当有一些信息需要展示出来,可以设置Intent的Action为这个值,并调用startActivity()方法
      • ACTION_SEND,当用户有一些信息需要分享到其他应用,可以设置Intent的Action为这个值,并调用startActivity()方法
      • ACTION_DIAL,拨打电话,可以设置Intent的Action为这个值,并调用startActivity()方法
      • ACTION_EDIT,编辑某些文件,可以设置Intent的Action为这个值,并调用startActivity()方法
    • Data,它是待操作数据的引用URI或者数据MIME类型的URI,它的值通常与Intent的Action有关联。比如,如果设置Action的值为ACTION_EDIT,那么Data的值就必须包含被编辑文档的URI。当我们创建Intent的时候,设置MIME类型非常重要。例如,一个可以显示图片的Activity可能不能播放音频,图片和音频的URI非常类似,如果我们设置了MIME类型,可以帮助系统找到最合适的组件接受Intent。有时候,MIME类型也可以从URI判断出来,例如当Data是一个包含content:字符串的URI时候,可以明确的知道,待处理的数据存在设备中,而且由ContentProvider控制。
      • 使用setData()方法设置数据引用的URI,使用setType()方法设置数据的MIME类型,使用setDataAndType()方法同时设置这两个属性。

      • 注意:如果想要设置两个的属性,直接用setDataAndType()方法,不要同时调用setData()setType()方法,因为这两个方法设置的值会相互覆盖

        public Intent setData(Uri data) {
        	mData = data;
        	mType = null;
        	return this;
        }
            
        public Intent setType(String type) {
            mData = null;
            mType = type;
            return this;
        }
        
    • Category,这个属性是对处理该Intent组件信息的补充。它是一个ArraySet类型的容器,所以可以向里面添加任意数量的补充信息,同时,Intent没有设置这个属性不会影响解析组件信息。可以通过addCategory()方法来设置该属性。下面列出一些常用的Category的值。
      • CATEGORY_BROWSABLE,设置Category为该值后,在网页上点击图片或链接时,系统会考虑将此目标Activity列入可选列表,供用户选择以打开图片或链接。
      • CATEGORY_LAUNCHER,应用启动的初始Activity,这个Activity会被添加到系统启动launcher当中。

    以上列出的这些关于Intent的属性(Component、Action、Data、Category)可以帮助系统来确定具体的组件,但是有一些Intent的属性,不会影响到组件的确定。

    • Extras,以key-value键值对的形式来存储组件执行操作过程中需要的额外信息,可以调用putExtra()方法来设置该属性,这个方法接受两个参数,一个是key,一个是value。也可以通过实例化一个储存额外信息的Bundle对象,然后调用putExtras()方法将我们实例化的Bundle添加到Intent中。
    • Flags,这个属性可以指示系统如何启动一个Activity,以及启动之后如何处理。例如Activity属于哪一个task(参考Activity的四种启动方式)。

    5. 显式Intent示例

           上文说到,显式Intent是用于启动某个特定的组件(Activity或者Service)的Intent,穿创建显式的Intent的时候需要设置组件名称(Component)属性,其他的属性都是可选属性。

    // fileUrl是一个URL字符串,例如 "http://www.example.com/image.png"
    Intent downloadIntent = new Intent(context, DownloadService.class);
    downloadIntent.setData(Uri.parse(fileUrl));
    startService(downloadIntent);
    

    这里的Intent的构造函数传入了两个参数,context和组件名(Component),调用了startService()方法后,会在当前的应用中启动DownloadService这个服务。
    显示Intent中设置的组件名(Component)需要在AndroidManifest.xml进行注册,所以它一般用来启动当前应用内的组件。

    6. 隐式Intent示例

           隐式Intent比显示的Intent会复杂一些,它既可以启动当前应用内的组件,也可以启动当前应用外的组件。如果当前应用无法处理隐式Intent,但是其他应用中的组件可以处理,那么系统会弹框让用户选择启动哪个应用中的组件。

           例如,如果用户有内容想分享给其他应用,就创建一个Intent,将它的Action属性设置为ACTION_SEND,然后将要分享的内容设置到Extras属性中,然后调用startActivity()方法,用户就可以选择将内容分享到哪一个应用。

    注意,如果没有任何应用能处理用户发送的隐形Intent,调用组件失败,应用可能会崩溃。调用resolveActivity()方法可以确认是否有Activity能够处理这个Intent,如果返回为非空,那么至少有一个组件能够处理这个Intent,调用startActivity()就很安全了;如果返回的是空(null),那么说明没有组件能够处理这个Intent,这个时候就不应该使用这个隐式的Intent了。

    // 要将textMessage信息分享出去
    Intent sendIntent = new Intent();
    sendIntent.setAction(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
    sendIntent.setType("text/plain");
    
    // 确认是否有组件能够处理这个隐式Intent
    if (sendIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(sendIntent);
    }
    

           调用startActivity()传入一个隐式Intent时候,系统会检查设备中所有的应用,确定哪些应用可以处理这个隐式的Intent(含有startActivity()操作并携带text/plain类型的Intent),如果只有一个应用可以处理这个Intent,那么直接唤起这个应用,并将Intent传给它;如果有多个应用可以处理这个Intent,那么系统会弹出一个选择框,让用户选择唤起哪个应用。

    7. 强制唤起选择框

           上文说了,如果多个应用可以处理同一个隐式Intent,系统会弹出选择框,让用户选择唤起哪个应用,并设置该应用为默认的打开方式,以后就不会弹出选择框了。如果用户希望以后一直使用该用户处理这个隐式Intent(比如打开网页,用户通常会倾向于使用同一个web浏览器),那么十分方便。

           但是如果用户想每一次都用不同的应用去处理这个隐式的Intent的,就应该每次弹出选择框,用户可以在选择框中选择唤起的应用,但是无法设置默认的打开方式。例如,当用户想根据当前的位置将内容分享到不同的应用,所以每次都需要弹出选择框。

    用户需要通过Intent.createChooser()创建一个Intent,然后调用startActivity()

    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    ...
    
    // 分享的标题
    String title = getResources().getString(R.string.chooser_title);
    // 创建一个调用选择框的Intent
    Intent chooser = Intent.createChooser(sendIntent, title);
    
    // 确认是否有应用可以处理这个Intent
    if (sendIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(chooser);
    }
    

    8. 接受隐式Intent

           想配置你的应用可以处理哪些隐式的Intent,需要在AndroidManifest.xml文件中使用<intent-filter>标签为组件设置一个或者多个过滤器。每一个过滤器基于ActionDataCategory来指定自身可以处理的Intent类型。如果隐式Intent的能够匹配到用户设置的其中一个过滤器,系统才能唤起这个应用相应的组件并将Intent传递给这个组件。

           组件应该为为一个它可以处理的操作单独设置一个处理器。例如,相册中的Activity可能有两个过滤器,一个过滤器对应浏览照片的操作,另一个过滤器对应编辑照片的操作。当这个Activity被启动的时候,根据Intent中携带的信息来决定执行哪种操作。

           每一个过滤器是在AndroidManifest.xml使用<intent-filter>标签来定义的,嵌套在组件标签中,例如<activity><service>标签。在<intent-filter>标签中,用户可以使用一下三个属性中的一个或者多个来指定可以接受的Intent。

    • <action>,在这个属性中,声明该组件可以执行的操作。该值必须是关于操作的一个字符串,并不是类常量
    • <data>,使用一个或者多个数据URI(scheme、host、port、path等等)和数据的MIME类型来指定接受的数据类型
    • <category>,声明接受的Intent类型

           Activity组件要接受隐式Intent,它必须有一个<category>属性为CATEGORY_DEFAULT的过滤器,因为startActivity()和startActivityForResult()方法处理Intent时候,默认的认为接受组件有一个<category>属性为CATEGORY_DEFAULT的过滤器。如果一个Activity组件不声明这样一个过滤器,它就接收不到隐式Intent。

    例如,以下代码声明了一个Activity组件,这个组件可以处理action属性为ACTION_SEND,数据类型是文本(text/plain)的隐式Intent。

    <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"/>
        </intent-filter>
    </activity>
    

    用户也可以创建一个包含多个<action><data><category>标签的过滤器,创建时候仅需要确定该组件能够处理过滤器定义的操作即可。

    如果是根据<action><data><category>标签的组合来处理多个Intent,那么需要为这个组件声明多个过滤器。

    系统会以这三个属性将隐式Intent与所有组件声明的过滤器进行对比,如果这三个属性全部能够匹配上,系统才有可能将这个隐式Intent传递给这个组件,因为如果多个应用的组件都能匹配上会弹出选择框,让用户选择一个应用去处理这个隐式Intent。

    为了避免无意中启动了其他的Service,所以在应用内,建议一直使用显示的Intent去启动服务,这样就不必再AndroidManifest.xml文件中为Service声明过滤器了。

    对于Activity的过滤器,必须在AndroidManifest.xml文件中声明,也可以不声明,直接使用显示Intent唤起Activity组件。

    广播接收器的过滤器声明可以在AndroidManifest.xml文件中声明,也可以使用registerReceiver()方法动态注册,使用完毕后,使用unregisterReceiver()方法动态注销。

    9. 过滤器声明示例

    下面一些过滤器的声明能够帮助你更好的理解。

    <activity android:name="MainActivity">
        <!-- 该Activity是该应用的启动入口页面,它会被储存在系统的launcher列表中 -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
    <activity android:name="ShareActivity">
        <!-- 该Activity能够处理ACTION_SEND行为且数据类型为text/plain的隐式Intent -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain"/>
        </intent-filter>
        <!-- 该Activity能够处理ACTION_SEND行为且数据类型是媒体内容的隐式Intent -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <action android:name="android.intent.action.SEND_MULTIPLE"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="image/*"/>
            <data android:mimeType="video/*"/>
        </intent-filter>
    </activity>
    

    第一个名为MainActivity的组件,是应用的启动入口页面,当用户点击应用图标,该Activity会被启动。

    • android.intent.action.MAIN,表示该Activity是应用的启动入口,且不需要任何Intent携带的数据。
    • android.intent.category.LAUNCHER,表示将该Activity的图标设为手机主屏幕上的应用图标,如果它没有图标,就用Application的图标。

    第二个名为ShareActivity的组件,能够处理两种隐式Intent,可以接受文本和媒体内容的分享操作,也就是说如果一个隐式Intent能够匹配到任意一个过滤器都可以唤起该Activity。当然,也可以直接通过显示Intent指定启动它。

    9. PendingIntent

    PendingIntent是对Intent的一种封装。它主要作用在于,让外部的应用执行内部的Intent时候,就好像是在你的应用中还行一样。

    通常在以下场景中会使用PendingIntent。

    • 当用户点击通知栏时候,才执行的Intent(系统的NotificationManager执行的Intent),详情参考这里
    • 当用户操作悬浮在主屏幕中的小工具,才执行的Intent(主屏幕应用执行的Intent),详情参考这里
    • 在未来某一个特定时间执行的Intent(系统的AlarmManager执行的Intent)

    因为每一个Intent对象都是针对具体的组件类别(Activity/Service/BroadcastReceiver)进行实例化,因此在创建PendingIntent的时候,也要基于相同的因素去实例化,使用以下方法实例化PendingIntent。

    • PendingIntent.getActivity(),返回一个适用于Activity组件的PendingIntent
    • PendingIntent.getService(),返回一个适用于Service组件的PendingIntent
    • PendingIntent.getBroadcast(),返回一个适用于BroadcastReceiver的PendingIntent

    当然官方还有一些其他获取PendingIntent对象的方法,不过内部也是使用上面三个方法来获取实例化对象的。

    这三个方法都需要当前应用的context,需要封装的Intent,以及一个或者多个该如何使用该Intent的标志(例如,是否可以多次使用该Intent)。

    关于Pending的具体使用也不再这里展开,需要了解具体使用的可以查看Notification中PendingIntent的使用悬浮工具栏中PendingIntent的使用

    10. Intent匹配规则

           上文中提到了,当发送一个隐式Intent后,系统会将它与设备中的每一个组件的过滤器进行匹配,匹配属性有ActionCategoryData三个,需要这三个属性都匹配成功才能唤起相应的组件。

    10.1 Action匹配规则

    一个过滤器可以一个Action属性也可以声明多个Action属性。如下:

    <intent-filter>
        <action android:name="android.intent.action.EDIT" />
        <action android:name="android.intent.action.VIEW" />
        ...
    </intent-filter>
    

    隐式Intent中的Action属性,与组件中的某一个过滤器的Action能够匹配(如果一个过滤器声明了多个Action属性,只需要匹配其中一个就行),那么就算是匹配成功。

    如果过滤器没有声明Action属性,那么只有没有设置Action属性的隐式Intent才能匹配成功。

    10.2 Category匹配规则

    一个过滤器可以不声明Category属性也可以声明多个Category属性,如下:

    <intent-filter>
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        ...
    </intent-filter>
    
    

           隐式Intent中声明的Category必须全部能够与某一个过滤器中的Category匹配才算匹配成功。比如说一个Category属性设为CATEGORY_BROWSABLE的隐式Intent也可以通过上面的过滤器,也就是说,过滤器的Category属性内容必须是大于或者等于隐式Intent的Category属性时候,隐式Intent才能匹配成功。

    如果一个隐式Intent没有设置Category属性,那么它可以通过任何一个过滤器的Category匹配。

    10.3 Data匹配规则

    一个过滤器可以不声明Data属性也可以声明多个Data属性,如下:

    <intent-filter>
        <data android:mimeType="video/mpeg" android:scheme="http" ... />
        <data android:mimeType="audio/mpeg" android:scheme="http" ... />
        ...
    </intent-filter>
    
    

    每个Data属性都可以指定数据的URI结构和数据MIME类型。URI包括scheme、host、port 和path四个部分,host和port合起来也成authority(host:port)部分。

    <scheme>://<host>:<port>/<path>
    

    例如:

    content://192.168.0.1:8080/folder/subfolder/etc
    

    在这个URI中,scheme是content,host是192.168.0.1,port是8080,path是folder/subfolder/etc。我们平时使用的网络url就是这种格式。

    在URI中,每个组成部分都是可选的,但是有线性的依赖关系

    • 如果没有scheme部分,那么host部分会被忽略
    • 如果没有host部分,那么port部分会被忽略
    • 如果host部分和port部分都没有,那么path部分会被忽略

    当进行URI匹配时候,并不是比较全部,而是局部对比,以下是URI匹配规则。

    • 如果一个URI仅声明了scheme部分,那么所有拥有与其相同的scheme的URI都会通过匹配,其他部分不做匹配
    • 如果一个URI声明了scheme部分和authority部分,那么拥有与其相同schemeauthority的URI才能匹配成功,path部分不做匹配
    • 如果一个URI所有的部分都声明了,那么只有所有部分都相同的URI才能匹配成功

    注意:path部分可以使用通配符(*),也就是path其中的一部分进行匹配。

    Data匹配时候,MIME类型和URI两者都会进行匹配,匹配规则如下:

    • 如果过滤器未声明URI和MIME类型,则只有不含URI和MIME类型的隐形Intent才能匹配成功
    • 如果过滤器中声明URI但是未声明MIME类型(也不能从URI中分析出MIME类型),则只有URI与过滤器URI相同且不包含IME类型的隐式Intent才能匹配成功
    • 如果过滤器声明MIME类型但是未声明URI,只有包含相同MIME类型但是不包含URI的隐式Intent才能匹配成功
    • 如果过滤器声明了URI和MIME类型(既可以是直接设置,也可以是从URI分析出来),只有包含相同的URI和MIME类型的隐式Intent才能匹配成功

    注意:进行匹配时候必须以过滤器为单位进行匹配,不能跨过滤器匹配。如果一个过滤器声明了多个ActionCategoryData,隐式Intent包含的ActionCategoryData都能在过滤器中匹配到相应的属性即可,也就是说过滤器中声明的属性是大于或者等于Intent中包含的属性,Intent才能匹配成功

    11. 其他

           系统通过过滤器去匹配Intent,启动相应组件,在PackageManager类中提供了一系列的查询(queryIntentActivities()/queryIntentServices()/queryBroadcastReceivers())方法去查询可以处理某个Intent的组件,也提供了一系列的解析(resolveActivity()/resolveService())方法来确定最佳启动组件。这些方法在某些场景下是非常有用的,也可以帮助我们降低程序crash风险。

    12. 思考

           上文中对Intent以及IntentFilter进行了详细的讲解,大多都是系统级别的处理过程。但是Intent作为一个官方已经封装好的信息携带者,我们可以用它来做很多事情。比如可以写自己的一套匹配规则,Intent仅仅作为数据携带者,通过它去传递一些信息,实现Fragment/Activity的页面跳转逻辑。关于Intent的使用,我相信还有更多的用处,需要用户一步一步的去探索。

    展开全文
  • IntentIntent 过滤器

    万次阅读 2017-12-04 14:56:17
    IntentIntent 过滤器 本文内容 Intent 类型构建 Intent 显式 Intent 示例隐式 Intent 示例强制使用应用选择器 接收隐式 Intent 过滤器示例 使用待定 IntentIntent 解析 操作测试类别...

    Intent 和 Intent 过滤器

    Intent 是一个消息传递对象,您可以使用它从其他应用组件请求操作。尽管 Intent 可以通过多种方式促进组件之间的通信,但其基本用例主要包括以下三个:

    • 启动 Activity

      Activity 表示应用中的一个屏幕。通过将 Intent 传递给 startActivity(),您可以启动新的 Activity 实例。Intent 描述了要启动的 Activity,并携带了任何必要的数据。

      如果您希望在 Activity 完成后收到结果,请调用 startActivityForResult()。在 Activity 的onActivityResult() 回调中,您的 Activity 将结果作为单独的 Intent 对象接收。如需了解详细信息,请参阅 Activity 指南。

    • 启动服务

      Service 是一个不使用用户界面而在后台执行操作的组件。通过将 Intent 传递给 startService(),您可以启动服务执行一次性操作(例如,下载文件)。Intent 描述了要启动的服务,并携带了任何必要的数据。

      如果服务旨在使用客户端-服务器接口,则通过将 Intent 传递给 bindService(),您可以从其他组件绑定到此服务。如需了解详细信息,请参阅服务指南。

    • 传递广播

      广播是任何应用均可接收的消息。系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播。通过将 Intent 传递给 sendBroadcast()sendOrderedBroadcast() 或 sendStickyBroadcast(),您可以将广播传递给其他应用。

    Intent 类型


    Intent 分为两种类型:

    • 显式 Intent:按名称(完全限定类名)指定要启动的组件。 通常,您会在自己的应用中使用显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,启动新 Activity 以响应用户操作,或者启动服务以在后台下载文件。
    • 隐式 Intent :不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。 例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。

    创建显式 Intent 启动 Activity 或服务时,系统将立即启动 Intent 对象中指定的应用组件。

    图 1. 隐式 Intent 如何通过系统传递以启动其他 Activity 的图解:[1] Activity A 创建包含操作描述的 Intent,并将其传递给 startActivity()[2] Android 系统搜索所有应用中与 Intent 匹配的 Intent 过滤器。 找到匹配项之后,[3] 该系统通过调用匹配 Activity(Activity B)的 onCreate() 方法并将其传递给 Intent,以此启动匹配 Activity。

    创建隐式 Intent 时,Android 系统通过将 Intent 的内容与在设备上其他应用的清单文件中声明的 Intent 过滤器进行比较,从而找到要启动的相应组件。 如果 Intent 与 Intent 过滤器匹配,则系统将启动该组件,并向其传递 Intent 对象。 如果多个 Intent 过滤器兼容,则系统会显示一个对话框,支持用户选取要使用的应用。

    Intent 过滤器是应用清单文件中的一个表达式,它指定该组件要接收的 Intent 类型。 例如,通过为 Activity 声明 Intent 过滤器,您可以使其他应用能够直接使用某一特定类型的 Intent 启动 Activity。同样,如果您没有为 Activity 声明任何 Intent 过滤器,则 Activity 只能通过显式 Intent 启动。

    注意:为了确保应用的安全性,启动 Service 时,请始终使用显式 Intent,且不要为服务声明 Intent 过滤器。使用隐式 Intent 启动服务存在安全隐患,因为您无法确定哪些服务将响应 Intent,且用户无法看到哪些服务已启动。从 Android 5.0(API 级别 21)开始,如果使用隐式 Intent 调用 bindService(),系统会引发异常。

    构建 Intent


    Intent 对象携带了 Android 系统用来确定要启动哪个组件的信息(例如,准确的组件名称或应当接收该 Intent 的组件类别),以及收件人组件为了正确执行操作而使用的信息(例如,要采取的操作以及要处理的数据)。

    Intent 中包含的主要信息如下:

    组件名称
    要启动的组件名称。

    这是可选项,但也是构建显式 Intent 的一项重要信息,这意味着 Intent 应当仅传递给由组件名称定义的应用组件。 如果没有组件名称,则 Intent 是隐式的,且系统将根据其他 Intent 信息(例如,以下所述的操作、数据和类别)决定哪个组件应当接收 Intent。 因此,如需在应用中启动特定的组件,则应指定该组件的名称。

    注:启动 Service 时,您应始终指定组件名称。 否则,您无法确定哪项服务会响应 Intent,且用户无法看到哪项服务已启动。

    Intent 的这一字段是一个 ComponentName 对象,您可以使用目标组件的完全限定类名指定此对象,其中包括应用的软件包名称。 例如,com.example.ExampleActivity。您可以使用 setComponent()setClass()setClassName() 或 Intent 构造函数设置组件名称。

    操作
    指定要执行的通用操作(例如,“查看”或“选取”)的字符串。

    对于广播 Intent,这是指已发生且正在报告的操作。操作在很大程度上决定了其余 Intent 的构成,特别是数据和 extra 中包含的内容。

    您可以指定自己的操作,供 Intent 在您的应用内使用(或者供其他应用在您的应用中调用组件)。但是,您通常应该使用由 Intent 类或其他框架类定义的操作常量。以下是一些用于启动 Activity 的常见操作:

    ACTION_VIEW
    如果您拥有一些某项 Activity 可向用户显示的信息(例如,要使用图库应用查看的照片;或者要使用地图应用查看的地址),请使用 Intent 将此操作与 startActivity() 结合使用。
    ACTION_SEND
    这也称为“共享”Intent。如果您拥有一些用户可通过其他应用(例如,电子邮件应用或社交共享应用)共享的数据,则应使用 Intent 将此操作与 startActivity() 结合使用。

    有关更多定义通用操作的常量,请参阅 Intent 类参考文档。 其他操作在 Android 框架中的其他位置定义。例如,对于在系统的设置应用中打开特定屏幕的操作,将在 Settings 中定义。

    您可以使用 setAction() 或 Intent 构造函数为 Intent 指定操作。

    如果定义自己的操作,请确保将应用的软件包名称作为前缀。 例如:

    static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
    数据
    引用待操作数据和/或该数据 MIME 类型的 URI(Uri 对象)。提供的数据类型通常由 Intent 的操作决定。例如,如果操作是 ACTION_EDIT,则数据应包含待编辑文档的 URI。

    创建 Intent 时,除了指定 URI 以外,指定数据类型(其 MIME 类型)往往也很重要。例如,能够显示图像的 Activity 可能无法播放音频文件,即便 URI 格式十分类似时也是如此。因此,指定数据的 MIME 类型有助于 Android 系统找到接收 Intent 的最佳组件。但有时,MIME 类型可以从 URI 中推断得出,特别当数据是 content: URI 时尤其如此。这表明数据位于设备中,且由 ContentProvider 控制,这使得数据 MIME 类型对系统可见。

    要仅设置数据 URI,请调用 setData()。 要仅设置 MIME 类型,请调用 setType()。如有必要,您可以使用 setDataAndType() 同时显式设置二者。

    注意:若要同时设置 URI 和 MIME 类型,请勿调用 setData() 和 setType(),因为它们会互相抵消彼此的值。请始终使用 setDataAndType()同时设置 URI 和 MIME 类型。

    类别
    一个包含应处理 Intent 组件类型的附加信息的字符串。 您可以将任意数量的类别描述放入一个 Intent 中,但大多数 Intent 均不需要类别。 以下是一些常见类别:
    CATEGORY_BROWSABLE
    目标 Activity 允许本身通过网络浏览器启动,以显示链接引用的数据,如图像或电子邮件。
    CATEGORY_LAUNCHER
    该 Activity 是任务的初始 Activity,在系统的应用启动器中列出。

    有关类别的完整列表,请参阅 Intent 类描述。

    您可以使用 addCategory() 指定类别。

    以上列出的这些属性(组件名称、操作、数据和类别)表示 Intent 的既定特征。 通过读取这些属性,Android 系统能够解析应当启动哪个应用组件。

    但是,Intent 也有可能会一些携带不影响其如何解析为应用组件的信息。 Intent 还可以提供:

    Extra
    携带完成请求操作所需的附加信息的键值对。正如某些操作使用特定类型的数据 URI 一样,有些操作也使用特定的 extra。

    您可以使用各种 putExtra() 方法添加 extra 数据,每种方法均接受两个参数:键名和值。您还可以创建一个包含所有 extra 数据的 Bundle 对象,然后使用 putExtras() 将Bundle 插入 Intent 中。

    例如,使用 ACTION_SEND 创建用于发送电子邮件的 Intent 时,可以使用 EXTRA_EMAIL 键指定“目标”收件人,并使用 EXTRA_SUBJECT 键指定“主题”。

    Intent 类将为标准化的数据类型指定多个 EXTRA_* 常量。如需声明自己的 extra 键(对于应用接收的 Intent),请确保将应用的软件包名称作为前缀。 例如:

    static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
    标志
    在 Intent 类中定义的、充当 Intent 元数据的标志。 标志可以指示 Android 系统如何启动 Activity(例如,Activity 应属于哪个任务),以及启动之后如何处理(例如,它是否属于最近的 Activity 列表)。

    如需了解详细信息,请参阅 setFlags() 方法。

    显式 Intent 示例

    显式 Intent 是指用于启动某个特定应用组件(例如,应用中的某个特定 Activity 或服务)的 Intent。 要创建显式 Intent,请为 Intent 对象定义组件名称 — Intent 的所有其他属性均为可选属性。

    例如,如果在应用中构建了一个名为 DownloadService、旨在从网页下载文件的服务,则可使用以下代码启动该服务:

    // Executed in an Activity, so 'this' is the Context
    // The fileUrl is a string URL, such as "http://www.example.com/image.png"
    Intent downloadIntent = new Intent(this, DownloadService.class);
    downloadIntent.setData(Uri.parse(fileUrl));
    startService(downloadIntent);

    Intent(Context, Class) 构造函数分别为应用和组件提供 Context 和 Class 对象。因此,此 Intent 将显式启动该应用中的 DownloadService 类。

    如需了解有关构建和启动服务的详细信息,请参阅服务指南。

    隐式 Intent 示例

    隐式 Intent 指定能够在可以执行相应操作的设备上调用任何应用的操作。 如果您的应用无法执行该操作而其他应用可以,且您希望用户选取要使用的应用,则使用隐式 Intent 非常有用。

    例如,如果您希望用户与他人共享您的内容,请使用 ACTION_SEND 操作创建 Intent,并添加指定共享内容的 extra。 使用该 Intent 调用 startActivity()时,用户可以选取共享内容所使用的应用。

    注意:用户可能没有任何应用处理您发送到 startActivity() 的隐式 Intent。如果出现这种情况,则调用将会失败,且应用会崩溃。要验证 Activity 是否会接收 Intent,请对 Intent 对象调用 resolveActivity()。如果结果为非空,则至少有一个应用能够处理该 Intent,且可以安全调用 startActivity()。 如果结果为空,则不应使用该 Intent。如有可能,您应停用发出该 Intent 的功能。

    // Create the text message with a string
    Intent sendIntent = new Intent();
    sendIntent.setAction(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
    sendIntent.setType("text/plain");
    
    // Verify that the intent will resolve to an activity
    if (sendIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(sendIntent);
    }

    注:在这种情况下,系统并没有使用 URI,但已声明 Intent 的数据类型,用于指定 extra 携带的内容。

    调用 startActivity() 时,系统将检查已安装的所有应用,确定哪些应用能够处理这种 Intent(即:含 ACTION_SEND 操作并携带“text/plain”数据的 Intent )。 如果只有一个应用能够处理,则该应用将立即打开并为其提供 Intent。 如果多个 Activity 接受 Intent,则系统将显示一个对话框,使用户能够选取要使用的应用。

    图 2. 选择器对话框。

    强制使用应用选择器

    如果有多个应用响应隐式 Intent,则用户可以选择要使用的应用,并将其设置为该操作的默认选项。 如果用户可能希望今后一直使用相同的应用执行某项操作(例如,打开网页时,用户往往倾向于仅使用一种网络浏览器),则这一点十分有用。

    但是,如果多个应用可以响应 Intent,且用户可能希望每次使用不同的应用,则应采用显式方式显示选择器对话框。 选择器对话框每次都会要求用户选择用于操作的应用(用户无法为该操作选择默认应用)。 例如,当应用使用 ACTION_SEND 操作执行“共享”时,用户根据目前的状况可能需要使用另一不同的应用,因此应当始终使用选择器对话框,如图 2 中所示。

    要显示选择器,请使用 createChooser() 创建 Intent,并将其传递给 startActivity()。例如:

    Intent sendIntent = new Intent(Intent.ACTION_SEND);
    ...
    
    // Always use string resources for UI text.
    // This says something like "Share this photo with"
    String title = getResources().getString(R.string.chooser_title);
    // Create intent to show the chooser dialog
    Intent chooser = Intent.createChooser(sendIntent, title);
    
    // Verify the original intent will resolve to at least one activity
    if (sendIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(chooser);
    }

    这将显示一个对话框,其中有响应传递给 createChooser() 方法的 Intent 的应用列表,并且将提供的文本用作对话框标题。

    接收隐式 Intent


    要公布应用可以接收哪些隐式 Intent,请在清单文件中使用 <intent-filter> 元素为每个应用组件声明一个或多个 Intent 过滤器。每个 Intent 过滤器均根据 Intent 的操作、数据和类别指定自身接受的 Intent 类型。 仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。

    注:显式 Intent 始终会传递给其目标,无论组件声明的 Intent 过滤器如何均是如此。

    应用组件应当为自身可执行的每个独特作业声明单独的过滤器。例如,图像库应用中的一个 Activity 可能会有两个过滤器,分别用于查看图像和编辑图像。 当 Activity 启动时,它将检查 Intent 并根据 Intent 中的信息决定具体的行为(例如,是否显示编辑器控件)。

    每个 Intent 过滤器均由应用清单文件中的 <intent-filter> 元素定义,并嵌套在相应的应用组件(例如,<activity> 元素)中。 在 <intent-filter> 内部,您可以使用以下三个元素中的一个或多个指定要接受的 Intent 类型:

    <action>
    在 name 属性中,声明接受的 Intent 操作。该值必须是操作的文本字符串值,而不是类常量。
    <data>
    使用一个或多个指定数据 URI 各个方面(schemehostportpath 等)和 MIME 类型的属性,声明接受的数据类型。
    <category>
    在 name 属性中,声明接受的 Intent 类别。该值必须是操作的文本字符串值,而不是类常量。

    注:为了接收隐式 Intent,必须将 CATEGORY_DEFAULT 类别包括在 Intent 过滤器中。 方法 startActivity() 和 startActivityForResult() 将按照已申明 CATEGORY_DEFAULT 类别的方式处理所有 Intent。 如果未在 Intent 过滤器中声明此类别,则隐式 Intent 不会解析为您的 Activity。

    例如,以下是一个使用包含 Intent 过滤器的 Activity 声明,当数据类型为文本时,系统将接收 ACTION_SEND Intent :

    <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"/>
        </intent-filter>
    </activity>

    您可以创建一个包括多个 <action><data> 或 <category> 实例的过滤器。创建时,仅需确定组件能够处理这些过滤器元素的任何及所有组合即可。

    如需仅以操作、数据和类别类型的特定组合来处理多种 Intent,则需创建多个 Intent 过滤器。

    系统通过将 Intent 与所有这三个元素进行比较,根据过滤器测试隐式 Intent。 隐式 Intent 若要传递给组件,必须通过所有这三项测试。如果 Intent 甚至无法匹配其中任何一项测试,则 Android 系统不会将其传递给组件。 但是,由于一个组件可能有多个 Intent 过滤器,因此未能通过某一组件过滤器的 Intent 可能会通过另一过滤器。如需了解有关系统如何解析 Intent 的详细信息,请参阅下文的 Intent 解析部分。

    注意:为了避免无意中运行不同应用的 Service,请始终使用显式 Intent 启动您自己的服务,且不必为该服务声明 Intent 过滤器。

    注:对于所有 Activity,您必须在清单文件中声明 Intent 过滤器。但是,广播接收器的过滤器可以通过调用 registerReceiver() 动态注册。 稍后,您可以使用 unregisterReceiver() 注销该接收器。这样一来,应用便可仅在应用运行时的某一指定时间段内侦听特定的广播。

    过滤器示例

    为了更好地了解一些 Intent 过滤器的行为,我们一起来看看从社交共享应用的清单文件中截取的以下片段。

    <activity android:name="MainActivity">
        <!-- This activity is the main entry, should appear in app launcher -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
    <activity android:name="ShareActivity">
        <!-- This activity handles "SEND" actions with text data -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain"/>
        </intent-filter>
        <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <action android:name="android.intent.action.SEND_MULTIPLE"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="application/vnd.google.panorama360+jpg"/>
            <data android:mimeType="image/*"/>
            <data android:mimeType="video/*"/>
        </intent-filter>
    </activity>

    第一个 Activity MainActivity 是应用的主要入口点。当用户最初使用启动器图标启动应用时,该 Activity 将打开:

    • ACTION_MAIN 操作指示这是主要入口点,且不要求输入任何 Intent 数据。
    • CATEGORY_LAUNCHER 类别指示此 Activity 的图标应放入系统的应用启动器。 如果 <activity> 元素未使用 icon 指定图标,则系统将使用 <application> 元素中的图标。

    这两个元素必须配对使用,Activity 才会显示在应用启动器中。

    第二个 Activity ShareActivity 旨在便于共享文本和媒体内容。 尽管用户可以通过从 MainActivity 导航进入此 Activity,但也可以从发出隐式 Intent(与两个 Intent 过滤器之一匹配)的另一应用中直接进入 ShareActivity

    注:MIME 类型 application/vnd.google.panorama360+jpg 是一个指定全景照片的特殊数据类型,您可以使用 Google panorama API 对其进行处理。

    使用待定 Intent


    PendingIntent 对象是 Intent 对象的包装器。PendingIntent 的主要目的是授权外部应用使用包含的 Intent,就像是它从您应用本身的进程中执行的一样。

    待定 Intent 的主要用例包括:

    由于每个 Intent 对象均设计为由特定类型的应用组件(ActivityService 或 BroadcastReceiver)进行处理,因此还必须基于相同的考虑因素创建PendingIntent。使用待定 Intent 时,应用不会使用调用(如 startActivity())执行该 Intent。相反,通过调用相应的创建器方法创建 PendingIntent时,您必须声明所需的组件类型:

    除非您的应用正在从其他应用中接收待定 Intent,否则上述用于创建 PendingIntent 的方法可能是您所需的唯一 PendingIntent 方法。

    每种方法均会提取当前的应用 Context、您要包装的 Intent 以及一个或多个指定应如何使用该 Intent 的标志(例如,是否可以多次使用该 Intent)。

    如需了解有关使用待定 Intent 的详细信息,请参阅通知应用小部件 API 指南等手册中每个相应用例的相关文档。

    Intent 解析


    当系统收到隐式 Intent 以启动 Activity 时,它根据以下三个方面将该 Intent 与 Intent 过滤器进行比较,搜索该 Intent 的最佳 Activity:

    • Intent 操作
    • Intent 数据(URI 和数据类型)
    • Intent 类别

    下文根据如何在应用的清单文件中声明 Intent 过滤器,描述 Intent 如何与相应的组件匹配。

    操作测试

    要指定接受的 Intent 操作,Intent 过滤器既可以不声明任何 <action> 元素,也可以声明多个此类元素。例如:

    <intent-filter>
        <action android:name="android.intent.action.EDIT" />
        <action android:name="android.intent.action.VIEW" />
        ...
    </intent-filter>

    要通过此过滤器,您在 Intent 中指定的操作必须与过滤器中列出的某一操作匹配。

    如果该过滤器未列出任何操作,则 Intent 没有任何匹配项,因此所有 Intent 均无法通过测试。 但是,如果 Intent 未指定操作,则会通过测试(只要过滤器至少包含一个操作)。

    类别测试

    要指定接受的 Intent 类别, Intent 过滤器既可以不声明任何 <category> 元素,也可以声明多个此类元素。 例如:

    <intent-filter>
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        ...
    </intent-filter>

    若要使 Intent 通过类别测试,则 Intent 中的每个类别均必须与过滤器中的类别匹配。反之则未必然,Intent 过滤器声明的类别可以超出 Intent 中指定的数量,且 Intent 仍会通过测试。 因此,不含类别的 Intent 应当始终会通过此测试,无论过滤器中声明何种类别均是如此。

    :Android 会自动将 CATEGORY_DEFAULT 类别应用于传递给 startActivity() 和 startActivityForResult() 的所有隐式 Intent。因此,如需 Activity 接收隐式 Intent,则必须将 "android.intent.category.DEFAULT" 的类别包括在其 Intent 过滤器中(如上文的 <intent-filter> 示例所示)。

    数据测试

    要指定接受的 Intent 数据, Intent 过滤器既可以不声明任何 <data> 元素,也可以声明多个此类元素。 例如:

    <intent-filter>
        <data android:mimeType="video/mpeg" android:scheme="http" ... />
        <data android:mimeType="audio/mpeg" android:scheme="http" ... />
        ...
    </intent-filter>

    每个 <data> 元素均可指定 URI 结构和数据类型(MIME 媒体类型)。 URI 的每个部分均包含单独的 schemehostport 和 path 属性:

    <scheme>://<host>:<port>/<path>

    例如:

    content://com.example.project:200/folder/subfolder/etc

    在此 URI 中,架构是 content,主机是 com.example.project,端口是 200,路径是 folder/subfolder/etc

    在 <data> 元素中,上述每个属性均为可选,但存在线性依赖关系:

    • 如果未指定架构,则会忽略主机。
    • 如果未指定主机,则会忽略端口。
    • 如果未指定架构和主机,则会忽略路径。

    将 Intent 中的 URI 与过滤器中的 URI 规范进行比较时,它仅与过滤器中包含的部分 URI 进行比较。 例如:

    • 如果过滤器仅指定架构,则具有该架构的所有 URI 均与该过滤器匹配。
    • 如果过滤器指定架构和权限,但未指定路径,则具有相同架构和权限的所有 URI 都会通过过滤器,无论其路径如何均是如此。
    • 如果过滤器指定架构、权限和路径,则仅具有相同架构、权限和路径的 URI 才会通过过滤器。

    注:路径规范可以包含星号通配符 (*),因此仅需部分匹配路径名即可。

    数据测试会将 Intent 中的 URI 和 MIME 类型与过滤器中指定的 URI 和 MIME 类型进行比较。 规则如下:

    1. 仅当过滤器未指定任何 URI 或 MIME 类型时,不含 URI 和 MIME 类型的 Intent 才会通过测试。
    2. 对于包含 URI 但不含 MIME 类型(既未显式声明,也无法通过 URI 推断得出)的 Intent,仅当其 URI 与过滤器的 URI 格式匹配、且过滤器同样未指定 MIME 类型时,才会通过测试。
    3. 仅当过滤器列出相同的 MIME 类型且未指定 URI 格式时,包含 MIME 类型、但不含 URI 的 Intent 才会通过测试。
    4. 仅当 MIME 类型与过滤器中列出的类型匹配时,同时包含 URI 类型和 MIME 类型(通过显式声明,或可以通过 URI 推断得出)的 Intent 才会通过测试的 MIME 类型部分。 如果 Intent 的 URI 与过滤器中的 URI 匹配,或者如果 Intent 具有 content: 或 file: URI 且过滤器未指定 URI,则 Intent 会通过测试的 URI 部分。 换言之,如果过滤器只是列出 MIME 类型,则假定组件支持 content: 和 file: 数据。

    最后一条规则,即规则 (d),反映了期望组件能够从文件中或内容提供程序获得本地数据。因此,其过滤器可以仅列出数据类型,而不必显式命名 content: 和 file: 架构。这是一个典型的案例。 例如,下文中的 <data> 元素向 Android 指出,组件可从内容提供商处获得并显示图像数据:

    <intent-filter>
        <data android:mimeType="image/*" />
        ...
    </intent-filter>

    由于大部分可用数据均由内容提供商分发,因此指定数据类型(而非 URI)的过滤器也许最为常见。

    另一常见的配置是具有架构和数据类型的过滤器。例如,下文中的 <data> 元素向 Android 指出,组件可从网络中检索视频数据以执行操作:

    <intent-filter>
        <data android:scheme="http" android:type="video/*" />
        ...
    </intent-filter>

    Intent 匹配

    通过 Intent 过滤器匹配 Intent,这不仅有助于发现要激活的目标组件,还有助于发现设备上组件集的相关信息。 例如,主页应用通过使用指定 ACTION_MAIN 操作和 CATEGORY_LAUNCHER 类别的 Intent 过滤器查找所有 Activity,以此填充应用启动器。

    您的应用可以采用类似的方式使用 Intent 匹配。PackageManager 提供了一整套 query...() 方法来返回所有能够接受特定 Intent 的组件。此外,它还提供了一系列类似的 resolve...() 方法来确定响应 Intent 的最佳组件。 例如,queryIntentActivities() 将返回能够执行那些作为参数传递的 Intent 的所有 Activity 列表,而 queryIntentServices() 则可返回类似的服务列表。这两种方法均不会激活组件,而只是列出能够响应的组件。 对于广播接收器,有一种类似的方法: queryBroadcastReceivers()

    展开全文
  • 详解显式intent和隐式intent

    千次阅读 2018-07-11 18:35:43
    Intent是Android程序中各组件之间进行交互的一种重要方式。它不仅可以指明activity想要执行的动作,也可以在不同组件之间传输数据。 Intent分为两种,显式intent和隐式intent,以下分别进行描述: 一、显式intent ...

    Intent是Android程序中各组件之间进行交互的一种重要方式。它不仅可以指明activity想要执行的动作,也可以在不同组件之间传输数据。
    Intent分为两种,显式intent和隐式intent,以下分别进行描述:

    一、显式intent

     bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent1 = new Intent(MainActivity.this,secondActivity.class);
                    startActivity(intent1);
                }
            });
    
    

    显式intent非常简单,直接创建一个intent对象,第一个参数代表启动活动的上下文,第二个代表想要启动的目标,之后调用startactivity即可。

    二、隐式intent

    相比于显式intent,隐式intent含蓄了很多,他并不明确指定要启动哪一个服务,而是用一系列的action和category等信息去过滤,然后交由系统分析这个intent,并帮我们找到合适的activity去启动。

    <activity android:name=".secondActivity">
                <intent-filter>
                    <action android:name="com.example.aries.androidtest.ACTION_START"></action>
                    <category android:name="android.intent.category.DEFAULT"></category>
                </intent-filter>
    </activity>

    上述的action标签中的内容可以随便用一个字符串,比如上述的,也可以使用系统内置的,比如主活动的action;category标签则是添加了一系列附加信息,更加精确的指出当前activity能够响应的intent还必须包含带有的category。只有action和category中的内容同时响应intent的action和category时,这个activity才能被响应;
    代码段如下所示:

    bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent("com.example.aries.androidtest.ACTION_START");
                    startActivity(intent);
                }
            });

    注:一个intent只能指定一个action,但是可以指定多个category,满足其中一个category即可启动。单action多category如下所示:

    <activity android:name=".secondActivity">
                <intent-filter>
                    <action android:name="com.example.aries.androidtest.ACTION_START"></action>
                    <category android:name="android.intent.category.DEFAULT"></category>
                    <category android:name="my_category"></category>
                </intent-filter>
            </activity>

    三、更多隐式intent的用法

    intent-filter下面可以有三种标签,分别是action、category和data,前两个都已经讲述,现在来探讨一下data这个属性。
    使用隐式intent,我们不仅可以启动自己程序内的activity,还可以调用其他程序中的activity,先看一个简单的例子,我们要展示一个网页,自己去实现一个浏览器不科学的,所以我们可以调用系统浏览器去打开,代码如下:

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

    这里我们首先指定了intent的action对象为Intent.ACTION_VIEW,这是安卓内置的动作,然后指定intent的data值-一个uri对象。

    data标签究竟可以有哪些内容呢,我们发现如下:

    android:scheme 用于指定数据的协议部分,如上例中的http;
    android:host 用于指定数据的主机名部分,如www.baidu.comandroid:port 用于指定数据的端口部分,一般在主机名之后;
    android:path 用于指定主机名和端口后面的部分;
    android:mimeType 用于指定可以处理的数据类型。

    如下面代码就可以响应打开一个网页的intent:

    <activity android:name=".secondActivity">
                <intent-filter tools:ignore="AppLinkUrlError">
                    <action android:name="android.intent.action.VIEW"></action>
                    <category android:name="android.intent.category.DEFAULT"></category>
                    <data android:scheme="http"></data>
                </intent-filter>
            </activity>

    四、intent在activity中传递数据

    1、向下一个activity传递数据
    第一个activity代码如下:

     bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(MainActivity.this,secondActivity.class);
                    intent.putExtra("data","this is data");
                    startActivity(intent);
                }
            });

    接收方的第二个activity:

     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
    
            TextView tv = findViewById(R.id.textView);
            Intent intent = getIntent();
            String data = intent.getStringExtra("data");
            tv.setText(data);
        }

    2、返回数据给上一个活动
    不在使用startactivity这个方法,而是使用startactivityforresult方法;
    第一个activity:

    public class MainActivity extends AppCompatActivity {
        TextView tv;
        Button bt;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            bt = findViewById(R.id.bt1);
            tv = findViewById(R.id.textView);
            bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(MainActivity.this,secondActivity.class);
                    startActivityForResult(intent,1);//第二个参数是请求码
                }
            });
        }
    
        //请求码,返回数据的结果码,携带数据的intent
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            switch (requestCode){
                case 1:
                    if (resultCode == 4){
                        Log.i("info",data.getStringExtra("data"));
                        tv.setText(data.getStringExtra("data"));
                    }
            }
        }
    }
    

    第二个activity:

    public class secondActivity extends AppCompatActivity {
        Button bt;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
    
            bt = findViewById(R.id.bt);
            bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent();
                    intent.putExtra("data","second返回的数据");
                    setResult(4,intent);
                    finish();
                }
            });
        }
    }

    注意:一个activity可以跳转到很多个activity,应用请求码和结果码可以进行区分;

    展开全文
  • 显式Intent和隐式Intent区别

    千次阅读 2017-03-21 13:11:27
    显式Intent和隐式Intent区别
  • 显示Intent,隐式Intent

    千次阅读 2014-03-03 11:22:49
    Intent 分为两种显示Intent,隐式Intent
  • Intent的基本知识

    万次阅读 2018-09-27 12:31:41
    我们知道,Intent 是一个消息传递对象,使用它可以向其他Android组件请求操作。Intent的基本用途主要包括:启动 Activity、启动服务、传递广播。Intent分为显式Intent和隐式Intent。下面我通过启动Activity来讲解...
  • 现在可以看中文的部分文档,可是内容真心不好记。看过之后就无名的又忘记了。还是摘抄一道的方式去加深记忆和当做一次笔记方便后面自己快速查找。记录一下,IntentIntent的过滤和 常用的通用 IntentIntent . . .
  • 常用Intent合集 Android

    千次阅读 2021-03-24 10:32:34
    Android常用Intent集合 //1.拨打电话 // 给移动客服10086拨打电话 Uri uri = Uri.parse("tel:10086"); Intent intent = new Intent(Intent.ACTION_DIAL, uri); startActivity(intent);
  • Android显式intent和隐式intent

    千次阅读 2018-06-11 14:43:34
    要启动一个Activity有两种方法,一种是通过显式Intent启动,而另一种是通过隐式Intent启动。 一、显示Intent 显示Intent是明确目标Activity的类名。 1、通过Intent(Context packageContext, Class&lt;?&...
  • 隐式Intent与显示Intent的区别

    千次阅读 2018-08-19 17:51:08
    显式Intent:通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,去调用Intent.setComponent()、Intent.setClassName()或Intent.setClass()方法或者在new Intent(A.this,B.class)指明需要转向到...
  • 什么是IntentIntent是Android中各个组件之间进行交互的一种重要方式 他不仅可以表示当前组件想要执行的步骤,而且还可以在不同组件之间传递数据 Intent的分类 大致分为两种:显性Intent、隐性Intent ...
  • Intent及其七大属性及intent-filter设置

    千次阅读 2019-06-12 17:53:35
    一、知识点回顾:Activity (一)、如何实现Activity页面...Intent intent = new Intent(MainActivity.this,NextActivity.class); startActivity(intent); //第二种方式: Intent intent = new Intent(); intent....
  • Android之Intent详解

    千次阅读 2019-01-20 00:18:05
    1.Intent的作用?都有哪些属性? Intent是应用程序种各个组件联系的桥梁,通信的载体,负责应用程序中数据的传递(运输大队长) 启动一个Acitivity: Context.this.startActivity(intent);   启动一个Sercvie ...
  • Android 开发遇到的问题: ...Intent intent =new Intent(getActivity(),DeliverListActivity.class); startActivity(intent); 遇到问题:Cannot resolve method’getActivity’ 解决这个问题首先要查看一下app–&g...
  • Android中的IntentIntent-filter总结

    万次阅读 多人点赞 2016-10-20 20:29:21
    Intent中文意思指”意图”,按照Android的设计理念,Android使用Intent来封装程序的”调用意图”,不管启动Activity、Service、BroadcastReceiver,Android都使用统一的Intent对象来封装这一”启动意图”。此外,Intent也...
  • Intent的种类

    千次阅读 2019-04-04 16:54:31
    Intent是activity之间的信使 分为显式Intent和隐式Intent 显式Intent Intent intent = new Intent(Mainactivity.this,xxxx.class) //xxxx是另外一个activaty的名称 startActivity(intent); 隐式Intent: ...
  • android之android.intent.category.DEFAULT的用途和使用

    万次阅读 多人点赞 2013-08-18 18:18:50
    1、要弄清楚这个问题,首先需要弄明白什么是implicit(隐藏) intent什么是explicit(明确) intent。 Explicit Intent明确的指定了要启动的Acitivity ,比如以下Java代码: Intent intent= new Intent(this, B....
  • intent.putExtra与intent.getStringExtra

    万次阅读 2017-05-08 09:43:32
    在当前Activity1使用startActvity(intent)或者startActivityForResult(intent, code)方法跳转到另一个Activity2之前,如果要传递某些String类型数据给Activity2,则会执行: intent.putExtra(String str, String Key)...
  • Intent详解

    千次阅读 2015-06-05 11:41:21
    以及Android的三个基本组件——Activity,Service和Broadcast Receiver——都是通过Intent机制激活的,不同类型的组件有不同的传递Intent方式,可以通过我的另一篇博客,Intent和pendingIntent机制详解里有?...
  • 显示Intent和隐式Intent的区别

    千次阅读 2015-11-12 07:56:10
    显示Intent和隐式Intent的区别 1:都是用来在一个activity中启动另外一个activity 2:显示Intent直接指明要启动activity的定义,即activity.class;隐式intent通过在androidmanifest.xml配置action来隐式的启动...
  • Android Intent and Intent Filter

    万次阅读 热门讨论 2010-05-10 20:26:00
    Intents and Intent Filters Intent Objects Intent对象 Intent Resolution Intent解析 Intent filtersFilters and security Filter和安全 Common cases 常见情况 Using intent matching 使用intent匹配Note Pa
  • Android Intent详解

    千次阅读 2018-12-28 11:19:05
    什么是Intent 翻译就是意图,就是你想做的事情,比如我想成为资深攻城狮,具体的就是在Activity中我想跳转到下一个Activity中,或者我想开启服务,我想发送广播,都是需要用到Intent(意图)的。 ...
  • Android IntentIntent Filter介绍

    千次阅读 2013-05-26 13:47:39
    ...本文主要介绍IntentIntent Filter的概念及作用、Intent的结构、两种类型IntentIntentIntent Filter 的匹配规则、利用Intent调用其他常见程序。 1、IntentIntent Filter
  • Intent过滤器

    千次阅读 2016-04-29 08:38:06
    隐式启动Activity时,并没有在Intent中指明Acitivity所在的类,因此,Android系统一定存在某种匹配机制,使Android系统能够根据Intent中的数据信息,找到需要启动的Activity。这种匹配机制是依靠Android系统中的...
  • Android中Intent对象与Intent Filter过滤匹配过程详解

    万次阅读 多人点赞 2015-09-16 01:12:45
    如果对Intent不是特别了解,可以参见博文《Android中Intent概述及使用》,该文对本文要使用的action、category以及data都进行了详细介绍。本文在描述组件在manifest中注册的Intent Filter过滤器时,统一用intent-...
  • 最近app出现了两三次由于Service的onStartCommand(intent, flags, startId)方法中获取intent携带参数时抛出的Intent.getIntExtra() on a null object异常,intent空指针。这个错误是因为没有对onStartCommand()方法...
  • 显式intent和隐式intent区别

    千次阅读 2013-07-23 00:10:20
    android当中显式intent和隐式intent的区别 定义: Intent定义:Intent是一种在不同组件之间传递的请求消息,是应用程序发出的请求和意图。作为一个完整的消息传递机制,Intent不仅需要发送端,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 387,296
精华内容 154,918
关键字:

intent