安卓笔记之隐式启动Activity篇

         之前聊的关于启动Activtiy的都是在Intent对象中指明要启动哪一个Activtiy(Intent对象的构造中传参数或者Intent对象的setClass方法),这时一种显式的启动方式。其实还有一种隐式的启动方式,它不指明要开启的Activity类,而是通过匹配一些数据信息来寻找Activity。打个踢球叫人守门的比方,显式启动方式就是“xxx,你快去守门!”,隐式启动就是类似“谁以前守过门去守门”。要知道隐式启动Activity的原理,首先要理解Intent。

      之前已经聊过Intent了,现在再深入一点,按照惯例来段开发文档介绍(从上次聊的文档部分后开始):

      

      It is basically a passive data structure holding an abstract description of an action to be performed. The primary pieces of information in an intent are:

  • action -- The general action to be performed, such as ACTION_VIEWACTION_EDITACTION_MAIN, etc.

  • data -- The data to operate on, such as a person record in the contacts database, expressed as a Uri.

    大概意思就是Intent是一种携带对一种行为的抽象描述的数据的结构,在一个Intent对象中主要携带的信息有action和data,action指明将要进行的动作行为,data指明行为使用到的数据,而要隐式启动一个Activity,就是主要靠它们去匹配。

   常用的action和data的配对如下:

   

  • ACTION_VIEW content://contacts/people/1 -- Display information about the person whose identifier is "1".

  • ACTION_DIAL content://contacts/people/1 -- Display the phone dialer with the person filled in.

  • ACTION_VIEW tel:123 -- Display the phone dialer with the given number filled in. Note how the VIEW action does what what is considered the most reasonable thing for a particular URI.

  • ACTION_DIAL tel:123 -- Display the phone dialer with the given number filled in.

  • ACTION_EDIT content://contacts/people/1 -- Edit information about the person whose identifier is "1".

  • ACTION_VIEW content://contacts/people/ -- Display a list of people, which the user can browse through. This example is a typical top-level entry into the Contacts application, showing you the list of people. Selecting a particular person to view would result in a new intent { ACTION_VIEW content://contacts/N } being used to start an activity to display that person.     

      除了以上两个主要的属性外,Intent还包含其他次要的属性:
      
  • category -- Gives additional information about the action to execute. For example, CATEGORY_LAUNCHER means it should appear in the Launcher as a top-level application, whileCATEGORY_ALTERNATIVE means it should be included in a list of alternative actions the user can perform on a piece of data.

  • type -- Specifies an explicit type (a MIME type) of the intent data. Normally the type is inferred from the data itself. By setting this attribute, you disable that evaluation and force an explicit type.

  • component -- Specifies an explicit name of a component class to use for the intent. Normally this is determined by looking at the other information in the intent (the action, data/type, and categories) and matching that with a component that can handle it. If this attribute is set then none of the evaluation is performed, and this component is used exactly as is. By specifying this attribute, all of the other Intent attributes become optional.

  • extras -- This is a Bundle of any additional information. This can be used to provide extended information to the component. For example, if we have a action to send an e-mail message, we could also include extra pieces of data here to supply a subject, body, etc.

     大概意思是:category 指明了行为的额外信息,type显式指明了data的类型,component 就是像显式启动Activity一样指明组件,一旦这个属性指明后其它都成了非必须的可选属性,extras是Intent对象携带的一些附加信息,一般以键值对形式,比如之前聊的传递数据给启动的Activity。
      关于隐式Intent,官方的定义如下:
     
  • Implicit Intents have not specified a component; instead, they must include enough information for the system to determine which of the available components is best to run for that intent.

    关于隐式Intent的使用:
    There are three pieces of information in the Intent that are used for resolution: the action, type, and category. Using this information, a query is done on the PackageManager for a component that can handle the intent. The appropriate component is determined based on the intent information supplied in the AndroidManifest.xml file.

    因为在组件的AndroidManifest.xml文件中已经配置好相应的action、type、category系统的PackageManager会根据Intent对象的action、type、category来寻找合适的组件。
   当然,我们也可以自定义一个组件的action,data,category,官方文档是这样说的:

   There are a variety of standard Intent action and category constants defined in the Intent class, but applications can also define their own.

   
   组件的action、type、category在AndroidManifest.xml 配置是写在<intent-filter>标签中,我们俗称该标签为“意图过滤器”,特别要说的是,一个程序中默认启动的Activity的配置都是:
   
  <intent-filter>
  <actionandroid:name="android.intent.action.MAIN"/>
  <categoryandroid:name="android.intent.category.LAUNCHER"/>
  </intent-filter>

  
 代码是最好的老师,我们来看两个例子,第一个是通过隐式启动浏览器Activity,另一个是用自定义的intent-filter启动Activity。

  隐式启动浏览器Activity:
  
   
   MainActivty:
   
  
public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	
	
	public void click(View view){
//        <action android:name="android.intent.action.VIEW" />
//        <category android:name="android.intent.category.DEFAULT" />
//        <category android:name="android.intent.category.BROWSABLE" />
//        <data android:scheme="http" />
//        <data android:scheme="https" />
//        <data android:scheme="about" />
//        <data android:scheme="javascript" />
		Intent intent = new Intent();
		//关键代码,分别为Intent对象定义了要访问Activtiy的action,category,data
		intent.setAction("android.intent.action.VIEW");
		intent.addCategory("android.intent.category.DEFAULT");
		intent.addCategory("android.intent.category.BROWSABLE");
		intent.setData(Uri.parse("http://www.baidu.com"));
		startActivity(intent);
	}

}

   
     运行程序:
   
     

     因为Intent对象的data是百度的网址,所以隐式启动浏览器后打开的是百度的首页:

     

  为什么能够打开浏览器页面呢,我们看看安卓中浏览器程序的源代码的AndroidManifest.xml中关于BrowerActivity的配置:
   
<span style="color:#333333;"> <activity android:name="BrowserActivity"
                  android:label="@string/application_name"
                  android:launchMode="singleTask"
                  android:alwaysRetainTaskState="true"
                  android:configChanges="orientation|keyboardHidden"
                  android:theme="@style/BrowserTheme"
                  android:windowSoftInputMode="adjustResize" >
            <intent-filter>
                <action android:name="android.speech.action.VOICE_SEARCH_RESULTS" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <!-- For these schemes were not particular MIME type has been
                 supplied, we are a good candidate. -->
           </span><span style="color:#ff0000;"> <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="http" />
                <data android:scheme="https" />
                <data android:scheme="about" />
                <data android:scheme="javascript" />
            </intent-filter></span><span style="color:#333333;">
            <!--  For these schemes where any of these particular MIME types
                  have been supplied, we are a good candidate. -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="http" />
                <data android:scheme="https" />
                <data android:scheme="inline" />
                <data android:mimeType="text/html"/>
                <data android:mimeType="text/plain"/>
                <data android:mimeType="application/xhtml+xml"/>
                <data android:mimeType="application/vnd.wap.xhtml+xml"/>
            </intent-filter>
            <!-- We are also the main entry point of the browser. -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.BROWSABLE" />
            </intent-filter>
            <!-- The maps app is a much better experience, so it's not
                 worth having this at all... especially for a demo!
            <intent-filter android:label="Map In Browser">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/postal-address" />
            </intent-filter>
            -->
            <intent-filter>
                <action android:name="android.intent.action.WEB_SEARCH" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="" />
                <data android:scheme="http" />
                <data android:scheme="https" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_SEARCH" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <meta-data android:name="android.app.searchable"
                    android:resource="@xml/searchable" />
        </activity></span>
  
   我们看到一个Activity并不是只有一个<intent-filter>标签,事实上只要Intent对象可以匹配到其中一个标签就可以启动这个Activity。<data android:scheme="http" />表示data可以是以“http”为开头的数据,因为是浏览器Activity,所以就是一个http开头的网址。
  
  以下是关于匹配的性质:


  1.任何一个需要隐式启动的Activity都必须要有这项:<category android:name="android.intent.category.DEFAULT"/>
例外情况是:android.intent.category.MAIN和android.intent.category.LAUNCHER的filter中没有必要加入android.intent.category.DEFAULT,当然加入也没有问题。


  2.如果category和action都相同的话,会跳出一个对话框让用户选择要启动哪一个activity;
如果category相同,而action不相同,就可以匹配到相应的activity。


  3.单单靠添加addCategory属性而没有Action等其他属性时,是不能匹配。


  4.当匹配不上任何Activity的话,会发生异常,跳出对话框:很抱歉...某某应用程序意外停止,请重试。

  
  再举一个自定义Activity的<intent-filter>例子:
   
  MainActivity:
   
  
public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void click(View view) {
		// 打 action
		// 人 数据
		// 附件的数据 Category 类别
		Intent intent = new Intent();
		intent.setAction("com.itheima.intent2.open2");
		intent.addCategory(Intent.CATEGORY_DEFAULT);

		// URL:统一资源定位符 http https ftp rtsp: URI:统一资源标识符 url是uri的一个子集
		// intent.setData(Uri.parse("jianren:张三"));
		// intent.setType("application/person");
		intent.setDataAndType(Uri.parse("jianren:张三"), "application/person");
		startActivity(intent);
	}
}

 这个意图的配置很有意思,翻译过来就是动作是“打”,类型是“人”,被打的数据是“贱人:张三”。值得注意的是,当一个intent的data和type都要设置时,就要写成intent.setDataAndType,因为setData和setType两个方法不兼容。
  
 要跳转到的Activity只有一个onCreate方法,重点看AndroidManifest.xml文件对两个Activity的配置:
   
 
<activity
            android:name="com.itheima.intent2.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.itheima.intent2.SecondActivity" >
            <intent-filter>
                <action android:name="com.itheima.intent2.open2" />

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

                <data android:mimeType="application/person" />
                <data android:scheme="jianren" />
            </intent-filter>
     
        </activity>

 看运行效果,很简单:
  
  

 点击按钮,马上跳转:

  


  以下是常见的Activity的action 
 其中ACTION_MAIN 和ACTION_EDIT最为常见。


  常见的Category:
  
  关于Intent的东西还不止这些,另外两大安卓组件BroadcastReceiver 和Service都将运用到它,以后再聊。
  
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值