Android源码分析-am命令的实现

 在Android系统中,可以用am命令来启动一个组件。例如,可以用下面的命令启动Camera:

# am start -n com.android.camera/com.android.camera.Camera

传送门:

Android开发-使用am命令启动Activity,Service等组件,以及发送广播等操作

Android源码分析-ActivityManagerService(AMS)源码分析

am是client端:

从代码实现上来说,在Android系统中,Android Framework层的各个service作为服务端,而使用者通过RPC(远程过程调用)调用这些服务,使用者就是Client端。

从进程间通信角度来说,Android Framework层的各个service作为服务端,提供具体的功能;同时,应用程序为了访问这些service,需要通过binder机制与service进行通信,这些运行在app端的代码就是client端(诸如ActivityManagerProxy等各种服务代理)。

具体到今天分析的am来说,am作为client端,与Framework的server端的AMS通过binder进行交互;从而实现AMS提供的各种功能,如图:

am的编译:

# Copyright 2008 The Android Open Source Project
#
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := am
include $(BUILD_JAVA_LIBRARY)

include $(CLEAR_VARS)
ALL_PREBUILT += $(TARGET_OUT)/bin/am
$(TARGET_OUT)/bin/am : $(LOCAL_PATH)/am | $(ACP)
   $(transform-prebuilt-to-target)

NOTICE_FILE := NOTICE
files_noticed := bin/am

# Generate rules for a single file. The argument is the file path relative to
# the installation root
define make-notice-file

$(TARGET_OUT_NOTICE_FILES)/src/$(1).txt: $(LOCAL_PATH)/$(NOTICE_FILE)
   @echo Notice file: $$< -- $$@
   @mkdir -p $$(dir $$@)
   @cat $$< >> $$@

$(TARGET_OUT_NOTICE_FILES)/hash-timestamp: $(TARGET_OUT_NOTICE_FILES)/src/$(1).txt

endef

$(foreach file,$(files_noticed),$(eval $(call make-notice-file,$(file))))

Am类相关代码的分析:

Am类图如下: 

说明(主要对Am类进行说明):

1. Am类:即am命令的入口类,有main方法。Am是client端组件,拥有一个远程代理组建mAm;

2. 数据成员mAm:

mAm:Am类通过mAm来实现相关的功能,包括启动一个activity或service,发送一个广播等。

mAm的真正实体类型是AcitivtyManagerProxy类型,因为mActivityManager是一个接口,无法实例化,而继承自mActivityManager的AcitivtyManagerProxy可以实例化。

mArgs:即am命令的参数;

3. 方法:

runStartService:启动一个service;

sendBroadcast:发送一个广播;

其余相关组件,请参考:

Android源码分析-ActivityManagerService(AMS)源码分析

run方法的分析:

am是可执行程序,其对应的实现在Am.java中,当然有main方法。在main方法中,调用了run方法。

main方法调用run,代码如下:

public static void main(String[] args) {
        try {
            (new Am()).run(args);
        } 
        ......
}

而在run方法中,对命令行参数进行解析:

private void run(String[] args) throws Exception {
        if (args.length < 1) {
            showUsage();
            return;
        }

        mAm = ActivityManagerNative.getDefault();
        if (mAm == null) {
            System.err.println(NO_SYSTEM_ERROR_CODE);
            throw new AndroidException("Can't connect to activity manager; is the system running?");
        }

        mArgs = args;
        String op = args[0];
        mNextArg = 1;

        if (op.equals("start")) {
            runStart();
        } else if (op.equals("startservice")) {
            runStartService();
        } 
......
}

其中,

1. mAm = ActivityManagerNative.getDefault(); 通过rpc方式,返回了ActivityManagerProxy的一个实例;

2. showUsage:显示了am的用法;

3. runStart:当命令行参数的option是start时(例如,本篇文章最开始的 am start 命令),执行该方法;

4. runStartService:顾名思义,启动一个service。

我们主要分析runStart。

runStart方法的分析:

runStart的主要功能是根据输入的参数,来构建mAm的startActivity的参数。

我们知道,要strat 一个acitivty,从client的角度来看,需要通过ActivityManagerProxy调用到AMS的

startActivity方法中,

现在,mAm就是ActivityManagerProxy的实例。

过程如下:

(1)intent的构建:

Intent intent = makeIntent();

(2)停止当前的应用:

根据是否停止的标志来判断,

if (mStopOption) {

       ......   

  mAm.forceStopPackage(packageName);
  Thread.sleep(250);

}

(3)调用mAm的startActivity:

if (mWaitOption) {
    result = mAm.startActivityAndWait(null, intent, mimeType,
                null, null, 0, mStartFlags, mProfileFile, fd, null);
    res = result.result;
} else {
    res = mAm.startActivity(null, intent, mimeType,
            null, null, 0, mStartFlags, mProfileFile, fd, null);
}

这样,就调用到了mAm(即ActivityManagerProxy)的对应的startActivity方法中了。

关于startActivity的源码,可以参考:

Android源码分析-ActivityManagerService(AMS)源码分析


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值