启动activity

启动activity,第1张

application/vnd.ms-excel xls

audio/mpeg mp3

image/gif gif

image/jpeg jpg

application/msword doc

application/pdf pdf

1 隐式启动自己的活动

无论隐式启动自己的程序还是启动外部的程序,从原理上来说都是一致的

1.1 配置过滤器

1.1.1

每个activity都可以在清单文件中配置intent-filter,意图过滤器

1.1.2

在intent-filter中配置action,catagory,data,这三个参数用于过滤,即通过和这三个参数之间的匹配,确定要启动那个activity。

1.1.3

可以配置多个action,多个catagory,多个data。

如果显式启动程序,则不需要这三个参数,如果隐式启动程序,则至少需要一个action,一个catagory,data可以没有

1.1.4

action,和catagory中需要设置name,data主要可以设置scheme和mimetype,可以单独设置scheme或者单独设置mimetype,也可以既设置scheme,也设置mimetype。name,scheme,mimetype的值可以自己指定。

1.1.5

如果活动是主活动,即打开app自动启动的活动,则需要按下面的配置,格式是固定的,不能更改

如果活动不是主活动,而且需要隐式启动,则至少有一个action,名字随便,一个catagory 名字是android.intent.category.DEFAULT。其他的各种参数没有强制规定。

具体的格式如下

1.2 启动活动

1.2.1 活动的响应

启动活动需要使用intent对象,intent中设置action,catagory,data,action和catagory就是intent中定义的相应的名字,data需要设置mimetype和scheme。

如果没有设置data

则只要intent中设置的action和catagory在intent-filter中配置的action和catagory中都有,相应的活动就可以响应。例如1.1.5中配置的intent-filter,假设它没有配置data,现在有一个intent,设置了action为com.example.zyl,catagory为android.intent.category.DEFAULT那么这个活动就会被响应

如果设置了data

action和catagory匹配规则不变,intent中设置的对应data的参数(mimeType,scheme等)必须要匹配其中的任何一个data,也就是intent中设置的对应data参数必须和intent-filter中设置的data完全一致,才能被响应。还是上面中的那个例子,现在有一个intent,设置了action为com.example.zyl,catagory为android.intent.category.DEFAULT,还需要设置data的mimetype为zzz,scheme为zyl,这个活动才能被响应

1.2.2 设置action

首先定义一个Intent对象,Intent是活动,广播,服务之前相互启动和通信的桥梁,并设置action,action就是zai有两种方式

第一种,直接在intent的参数中传入action

第二种,用setAction方法设置action

1.2.3 设置catagory

当要启动活动的时候,调用startActivity时,系统会自动为intent添加一个catagory属性,这个catagory属性的名字是android.intent.category.DEFAULT。也就是说所有隐式启动的活动都会有这个catagory这个属性,这也就是为什么活动的intent-filter中必须配置android.intent.category.DEFAULT这个属性。

所以,既然所有的intent-filter中都有android.intent.category.DEFAULT这个属性,而启动活动时系统又会为intent添加这个属性,那么catagory这个属性就不用自己配置也会匹配的。

如果想要进一步过滤的话,也可以为intent继续设置catagory这个属性。设置的方法是

传入需要过滤的catagory的名字

1.2.4 设置data

如果intent-filter中没有设置data,那么上面两步就可以隐式的启动一个活动了,但是如果intent-filter中设置了data属性,那么如果想要启动那个活动,就必须为intent设置data。

这里只说两个比较重要的data的属性,scheme和mimetype

scheme

scheme通过setData设置

产生一个Uri对象,如下。调用Uri.parse方法产生Uri对象,这个对象中传入一个字符串,中间用:分开,前面对应的就是scheme参数,这个scheme需要和intent-filter中配置的scheme一致,后面就是需要通过setData方法传入的参数。

然后

将Uri对象传入

mimeType

设置mimeType,如果intent-filter中设置了mimetype属性,则通过setType方法,为intent设置mimeType,这个mimeType需要和intent-filter中设置的mimeType一致,自己定义的mineType的格式必须满足 / 这种形式,*代表任何字符。

------------------------------一个重要的问题-------------------------------------

如果在intent-filter中只设置scheme或者只设置了mimeType,则用上面的方法就可以了。

但是如果intent-filter中同时设置scheme和mimeType,那么就会产生一个问题,因为调用setData时会屏蔽setType,而setType时,会屏蔽setData。所以这时需要用一个方法,同时设置data和mimeType。这个方法叫setDataAndType,如下

-----------------------------另一个说明--------------------------------------------

setData有两个作用,一个作用是匹配scheme,另一个作用是传递数据

调用setData时,可以指定scheme也可以不指定scheme,如果intent-filter中配置了scheme,可以在setData指定scheme,启动这个活动同时传递数据,如果intent-filter中没有指定scheme,在setData时,可以不指定scheme,只传递数据,例如下面这种写法,,也是可以的。对于setData传递数据这一块,在下面数据的传递那一块进行说明。

2 隐式启动其他的应用程序

通过和意图过滤器相互匹配就可以打开相应的活动,所以只要知道其他应用的意图过滤器是怎么配置的,自然就可以通过隐式启动的方法启动其他app中的活动

2.1 打电话

2.1.1 设置action

跳转到拨号界面,不直接拨打,对应的action为Intent.ACTION_DIAL,这个是系统封装好的字符串,对应拨号界面的action

直接拨打电话,对应的action为Intent.ACTION_CALL

或者

2.2.2 设置scheme

还需要设置scheme为tel

2.2.3 开启权限

要实现打电话功能,还需要在manifest中注册权限

2.2.4 开启活动

以上四步就实现了打电话的功能

2.2 发短信

2.2.1 设置action

2.2.2 传递要发送的联系人和设置scheme

2.2.3 传递要发送的短信内容

2.2.4 开启活动

以上四布就可以进入发送短信的界面,但是要手动发送短信,如果想直接发送短信,需要借助发送短信的manager类方法,详情在manager那部分写着

3 打开各种文件

对于手机中的各种文件,如果想调用相应的程序打开这些软件,就可以使用Intent.ACTION_VIEW,通过设置data传入数据内容,通过设置type筛选打开文件的程序的类型。这时就需要采用setDataAndType

例子如下

上面的例子就会调取可以打开这个文件的程序,供用户选择。

主要的就是设置数据和type,数据就直接从文件中读取就可以了,最重要的就是通过type来过滤应用程序。下面列出一个主要的mimeType类型

如果显式启动程序,那么不需要配置任何的intent-filter

直接在intent中传入当前活动的对象,和要打开的活动的.class对象,然后开启活动即可

1 传递数据的方法

传递数据也通过intent,intent携带着数据,从一个活动,到另一个活动,传递数据有两种方法,一种是setData方法,一种是putExtra方法。无论是显式启动还是隐式启动,都可以调用这两种方法。

1.1 setData方法

1.1.1

在第一个活动中intent调用setData的方法,携带数据,传入一个Uri类型的数据,根据另一个活动中的相应配置,可以携带scheme参数,也可以不携带scheme参数

1.1.2

在另一个活动中接收数据

首先获取到传入的intent对象,然后通过getData()(返回一个Uri类型的数据),或者getDataString()(返回一直String类型的数据),如果传入的数据是一个String类型,则直接调用getDataString()就可以得到这个数据。

一般在自己的程序内部很少使用这种方式传递数据,当启动外部程序,外部程序又规定需要使用setData传递数据时,才会使用setData方式

1.2 putExtra方法

这种方法是传递数据最常用的方法

1.2.1 传递普通类型的数据

传入数据

获取数据

1.2.2 传递实体类对象的数据

想要传递实体类对象,首先创建实体类时要实现Serializable接口

现在准备实体类对象,和一个对象list

开始传递数据

第一种方式

传入数据时使用putExtra方式,即可以传入单个对象,也可以传入对象的list

获取数据

第二种方式

通过Bundle传递数据,同样既可以传入单个实体类对象,也可以传入实体类list

传入数据

接收数据

2 接收从下一个活动返回的数据

上面传递数据都是直接传递给下一个活动,现在想从下一个活动返回数据,启动活动是的方法就从startActivity变成了startActivityForResult

2.1 向下一个活动传递数据

2.2 下一个活动返回数据

2.3 第一个活动接收数据

想接收返回的数据,需要重写第一个活动的onActivityResult

相关源码:

调用 startActivity 或 startActivityForResult 来启动Activity。那么启动的Activity有两种情况:第一种是启动同进程内的Activity第二种是启动不同进程的根Activity,比如在桌面点击启动App,就是启动不同进程的Activity。这两种情况的Activity的启动流程大致相同,其流程大致是以下三个过程:

以下逐一讲解这三大过程:

下图是调用进程向system_server进程发起请求的过程:

startActivityForResult方法继续调用 Instrumentation.execStartActivity 方法。而Instrumentation类主要用来监控应用程序和系统的交互。

下图是ATMS处理startActivity过程,并回调启动进程的ApplicationThread

ATMS. startActivity:

ATMS类通过一系列方法调用最终来到 startActivityAsUser 的方法,该方法先检查调用进程的权限,然后通过 getActivityStartController().obtainStarter 创建 ActivityStarter 类,并把参数设置到 ActivityStarter.Request 类中,最后执行 ActivityStarter.execute() 方法。

ActivityStarter准备堆栈

在 ActivityStarter. executeRequest 方法中先做一系列的检查,包括调用进程的检查、Intent的检查、权限的检查、向PKMS获取启动Activity的ActivityInfo等信息,然后调用 startActivityUnchecked 方法开始对要启动的Activity做堆栈管理。

在 startActivityInner 方法中,根据启动模式计算出flag,在根据flag等条件启动的Activity的ActivityRecord是加入现有的Task栈中,还是创建新Task栈。为Activity准备好堆栈后,调用 RootWindowContainer.resumeFocusedStacksTopActivities 方法

ActivityStack对栈的管理:

对于启动Activity对应的 ActivityStack 来说,是管理其栈中Activity的显示逻辑。而后继续调用 ActivityStackSupervisor.startSpecificActivity

ActivityStackSupervisor检查启动进程和回调ApplicationThread

在ActivityStackSupervisor中先检查要启动Activity的进程是否存在,不存在则创建进程,存在则调用 realStartActivityLocked ,realStartActivityLocked方法通过事务给回调 ApplicationThread. scheduleTransaction 方法。

下图为ActivityThread启动Activity过程的时序图:

ApplicationThread类绕了一大圈,最后调用在ATMS阶段设置的ClientTransaction的CallBack的execute方法,也就是 LaunchActivityItem. execute 方法,此方法创建一个 ActivityClientRecord 对象,然后调用 ActivityThread. handleLaunchActivity 开启真正的Actvity启动。

真正启动Activity:


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/7792821.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-09
下一篇 2023-04-09

发表评论

登录后才能评论

评论列表(0条)

保存