Android启动Activity的方式原理分析

本文详细介绍了Android中Intent的两种调用方式:显示调用和隐式调用,并深入分析了隐式调用的内部原理。此外,还列举了在实际开发中常用的隐式调用示例,包括调用浏览器、地图、拨打电话等。

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

一.启动 Activity 的分类
在android 种启动4大组件的方式有很多种,但是不管再多,都从调用方式上分为以下2种:
1、显示调用(Intent显示跳转)
显式调用明确指定了调用的组件名称,对于显式调用的Intent,称之为“显式Intent”,如下面的例子:
(1)同一个应用程序中的Activity切换

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

(2)不同应用程序之间的Activity切换

   Intent intent = new Intent();
   intent.setClassName("com.intent.test.app","com.intent.test.app.SecondActivity");
   startActivity(intent);

并且在 com.intent.test.app/.SecondActivity 的 AndroidManifest.xm l要设置如下属性

        <activity
            android:name=".com.intent.test.app.SecondActivity"
            android:exported="true" >
        </activity>

2、隐式调用(通过IntentFilter来寻找)

对于没有明确指出目标组件名称的Intent,则称之为“隐式 Intent”。 Android系统使用IntentFilter 来寻找与隐式Intent相关的对象。
在 com.intent.test.app/.SecondActivity 的 AndroidManifest.xm l要设置如下属性

        <activity
            android:name="com.intent.test.app.SecondActivity"
            android:exported="true" >
            <intent-filter>
                <action android:name="SecondActivity" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

然后在第一个activity 中就可以通过下面的代码来访问了

   Intent intent = new Intent("SecondActivity");
   startActivity(intent);

3、显示调用跟隐式调用两者的区别
显示调用跟隐式调用两者的区别主要在于以下两点:
(1)显式Intent更多用于在应用程序内部传递消息。比如在某应用程序内,一个Activity启动一个Service。
隐式Intent恰恰相反,它不会用组件名称定义需要激活的目标组件,它更广泛地用于在不同应用程序之间传递消息。
(2)在显式Intent消息中,决定目标组件的唯一要素就是组件名称,因此,如果你的Intent中已经明确定义了目标组件的名称,那么你就完全不用再定义其他Intent内容。 而对于隐式Intent则 不同,由于没有明确的目标组件名称,所以必须由Android系统帮助应用程序寻找与Intent请求意图最匹配的组件。

小结:以上介绍的都是从用法上来介绍Android是如何来启动Activity的,那么接下来我们来分析它的内部原理,显示调用比较简单,所以我就不说了,我主要来介绍隐式调用的原理分析。
二、内部原理分析
这部分我们主要分析隐式调用方式的内部原理。
1、Intent 与组件的匹配
当我们使用隐式调用启动一个Acitivity的时候,Android会将Intent的请求内容和一个叫做IntentFilter的过滤器比较,IntentFilter中包含系统中所有可能的待选组件。如果IntentFilter中某一组件匹配隐式Intent请求的内容,那么Android就选择该组件作为该隐式Intent的目标组件。那么你肯定会问 Android如何知道应用程序能够处理某种类型的Intent请求呢?这就需要我们的应用程序在Android-Manifest.xml中声明自己所含 组件的过滤器(即可以匹配哪些Intent请求)。要明白一个没有声明Intent-Filter的组件只能响应指明自己名字的显式Intent请求,而无法响应隐式Intent请求。而一个声明了IntentFilter的组件既可以响应显式Intent请求,也可以响应隐式Intent请求。那么在比较的过程中,Android系统会用哪些因素作为选择的参考标准呢?答案是:在通过和 IntentFilter比较来解析隐式Intent请求时,Android将以下三个因素作为选择的参考标准。

  • Action:使用android:name特性来指定对响应的动作名。
  • Data/type:该标签允许你指定组件能作用的数据。
  • Category:使用android:category属性来指定在什么样的环境下动作才被响应。每个Intent Filter标签可以包含多个category标签。
  • Extras和flag:在解析收到Intent时是并不起作用的
    下面我们举个例子来说明一下,比如大家都比较熟悉的打电话,我们就以这个例子来说明一下吧。其实在打电话的时候,我们是使用以下方法:
Uri uri = Uri.parse("tel:23328674");
Intent intent=new Intent(Intent.ACTION_DIAL,uri);
startActivity(intent);

Intent 中定义的ACTION_DIAL为

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

那么接下来在我们自己的电话App中,我们需要定义对应的过滤器:

 <!-- phone -->
   <app-category
       settings:category_lable="@string/phone_category_title"
       settings:category_icon="@drawable/ic_settings_home"
       settings:category_rank="4">
        <intent android:action="android.intent.action.DIAL"
           android:data="tel:">
           <categories android:name="android.intent.category.DEFAULT" />
       </intent>
  </app-category>

看到这里你是不是对打电话整个流程有一个宏观上的认识呢?其实打电话的整个流程可以这样子理解:
Ams收到StartActivity的请求——>匹配所有组件中的Action——>检查Category来确定是否响应该Intent——>检查作用的数据——>启动组件并传入数据
到这里需要大家注意下面几点细节:

  1. 隐式调用适用与android的4大组件
  2. 隐式调用的组件默认category为
category为<category android:name="android.intent.category.DEFAULT"/>

所以要想能够顺利启动这个组件,最好要加上这个标记
3. 一个组件里可以有多对 只要匹配其中一对,即可启动这个组件。
4. 在里可以有多个 ,只需匹配其中一个即可
5. 在里可以有多个,只需匹配其中一个即可

三、开发中一些常见的隐式调用
1、调用浏览器

Uri uri = Uri.parse("www.baidu.com");
Intent it = new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);

2、调用地图上的某个坐标显示

Uri uri = Uri.parse("geo:56.23467,87.456723");
Intent it = new Intent(Intent.Action_VIEW,uri);
startActivity(it);

3、在地图上显示路径

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

4、拨打电话

Uri uri = Uri.parse("tel:1008611");
Intent it = new Intent(Intent.ACTION_DIAL, uri);
startActivity(it);

需要添加权限

<uses-permission id="android.permission.CALL_PHONE" />

5、发送短信

Uri uri = Uri.parse("smsto:10086");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
it.putExtra("sms_body", "cwj");
startActivity(it);

6、发送彩信

Uri uri = Uri.parse("content://media/external/images/media/11");
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra("sms_body", "text");
it.putExtra(Intent.EXTRA_STREAM, uri);
it.setType("image/png");
startActivity(it);

7、发送邮件

Uri uri = Uri.parse("mailto:985762@qq.com");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);

Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_EMAIL,"985762@qq.com");
it.putExtra(Intent.EXTRA_TEXT,"The email body text");
it.setType("text/plain");
startActivity(Intent.createChooser(it, "Choose Email Client"));

Intent it=new Intent(Intent.ACTION_SEND);
String[] tos={"985762@qq.com"};
String[] ccs={"985552@qq.com"};
it.putExtra(Intent.EXTRA_EMAIL, tos);
it.putExtra(Intent.EXTRA_CC, ccs);
it.putExtra(Intent.EXTRA_TEXT, "The email body text");
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.setType("message/rfc822");
startActivity(Intent.createChooser(it, "Choose Email Client"));

8、播放音乐

Uri playUri = Uri.parse("file:///sdcard/download/mu.mp3");
returnIt = new Intent(Intent.ACTION_VIEW, playUri);

9、播放媒体文件

Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/my.mp3");
it.setDataAndType(uri, "audio/mp3");
startActivity(it);

Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);

10、安装APK

Uri installUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值