`
OliveExcel
  • 浏览: 71758 次
文章分类
社区版块
存档分类
最新评论

一个获取Android应用(或Activity)启动时间的工具

阅读更多

需求: 要求得到某个Activity的启动时间

 

实现:

1. adb shell下面存在am命令, 使用start -W -n参数, 即可获取Activity启动时间的信息;

2. 上述Activity的启动信息中, 包含了本次启动时间.

 

================================= 需求变更的分割线 =================================

 

需求: 要求得到某个Activity的启动时间, 需要将此功能集成到APK

 

实现:

1. 通过Process process = Runtime.getRuntime().exec(cmd)执行命令;

2. 通过上述process.getInputStream()获取命令执行结果;

3. 解析命令执行结果, 得到Activity启动时间.

 

但是, 上面这个方案看着不是很爽, 想找个替代方案.

百度了一下, 豁然开朗: am命令是用java实现的, cat一下system/bin/am, 就可以看到它里面实际上封装了system/framework/am.jar. 然后在源码中找到了am.jar的工程(此处存在一堆找代码的过程, 最后再扯).

 

来读一下代码:

1. 既然是java工程, 那势必要先找到public static void main();

2. 发现里面就一句话:

 

(new Am()).run(args);
3. 我X, 过分, 这个run()方法还是在父类BaseCommand里的. 没错, 这一步我就是写来吐槽找代码麻烦的!

 

4. 父类的run()方法的关键代码:

 

public void run(String[] args) {
    if (args.length < 1) {
        onShowUsage(System.out);
        return;
    }
    ...
    onRun();
    ...
}
即校验完参数个数, 就开始入正题了, 正题跑的是Am.onRun();

 

5. 接下来就好办了, 找start参数的处理逻辑: 由于我关心的是最后输出内容中的"ThisTime", 因此找到它是怎样赋值, 就算是定位到数据源. 于是有了方案如下:

 

实现二:

1. Am.java中, 通过IActivityManager.startActivityAndWait()方法, 启动目标Activity, 并从方法返回值中获取Activity启动时间等信息. 由于IActivityManager及其方法是hide的, 所以需要通过反射获取;

2. 获取IActivityManager实例:

 

Class activityManagerNativeClazz = Class.forName("android.app.ActivityManagerNative");
Method getIActivityManager = activityManagerNativeClazz.getDeclaredMethod("getDefault", new Class[] {});
Object iActivityManagerInstance = getIActivityManager.invoke(activityManagerNativeClazz, null);
2. 从IActivityManager中找到startActivityAndWait()这个方法(没有通过方法 + 参数类型来拿, 是因为懒, 这个方法有好多参数... 并且同名的方法就这一个, 不怕拿错):

 

Method startActivityAndWait = null;
for (Method method : iActivityManagerInstance.getClass().getDeclaredMethods()) {
    if ("startActivityAndWait".equals(method.getName())) {
        startActivityAndWait = method;
        break;
    }
}

3. 构造启动Activity的Intent. Am.java中, 通过目标包名 + 目标Activity类名构造Intent, 可以照搬为如下代码:

 

Intent intent = new Intent();
intent.setComponent(ComponentName.unflattenFromString(packageName + "/" + activityName));
4. invoke方法, 启动目标Activity:
startActivityAndWait.invoke(iActivityManagerInstance, params);
5. 上一步执行的返回值是android.app.IActivityManager$WaitResult类型的, 由于它也属于hide API, 所以获取到实例后, 再次通过反射拿到WaitResult.thisTime的值, 作为Activity启动时间.

 

 

================================= 与方案无关的分割线 =================================

 

补上找代码的过程:

1. 如果am.jar不是第三方的库(应该不会是, 因为这个jar包处理的是Android的东西), 那么就应该由系统中的java文件编译而来. 那么就一定会有编译中间件. 经查找中间件, 发现其中包含有am_intermediates, 那么可以确定一个信息, am.jar的module name就是am;

2. 通过对mk文件进行检索, 关键字: LOCAL_MODULE := am;

3. 定位到工程源码位于frameworks/base/cmds/am;

4. 这是个java工程, 并且整个工程只有一个源码文件...

5. Am.java的父类BaseCommand, 通过文件名检索, 可以找到位于frameworks/base/core/java/com/android/internal/os路径下.

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    Android父Activity获取子Activity返回信息demo

    在Android应用开发中,Activity是构成应用程序的基本组件,它代表用户界面的一个屏幕。有时,我们需要在子Activity执行某些操作后将结果返回给父Activity。这个过程通常涉及到Intent的使用,Intent不仅用于启动新的...

    Android利用Intent启动和关闭Activity

    Intent不仅能够启动一个新的Activity,还能在Activity之间传递数据,实现应用内部或应用间的交互。 ### 一、Intent启动Activity #### 1. 显式启动 显式启动是通过Intent明确指定要启动的Activity的类名。创建...

    安卓获取apk package activity工具

    "安卓获取apk package activity工具"是一个专门用于解析和获取APK文件中Package(包名)和Activity(活动)信息的实用工具。了解这个工具对于开发者来说非常重要,因为掌握如何获取和操作这些信息对于调试、分析或...

    Android深入理解Activity!

    每个任务是一个包含多个Activity的堆栈,当用户按下回退键或新启动一个Activity时,系统会在栈中进行相应的操作。理解这一机制对于避免用户在应用中迷失方向至关重要。 四、Intent传递 Intent是Android中用于启动...

    Android 通过反射启动未安装的APK中的Activity

    每个Android应用都是由一个或多个组件构成的,包括Activity、Service、BroadcastReceiver和ContentProvider。Activity是用户与应用交互的入口点,通常我们需要在AndroidManifest.xml中声明每个Activity,以便系统...

    Android一个apk启动另外一个apk

    在Android平台上,一个APK应用启动另一个APK应用是一个常见的需求,这可能涉及到应用之间的交互、服务调用或者用户引导到不同的应用体验。这个过程主要依赖于Android的Intent机制,Intent是Android系统中用于组件间...

    Android高级应用源码-获取手机应用信息.zip

    这个"Android高级应用源码-获取手机应用信息.zip"的压缩包很可能包含了一个示例项目,用于演示如何通过编程方式来获取这些信息。让我们深入探讨一下这个主题,了解相关的核心知识点。 首先,Android提供了`...

    android Activity启动模式(launchMode)

    在Android应用开发中,Activity是用户界面的基本单元,它的启动模式(launchMode)是一个非常重要的概念,它决定了当用户点击应用图标或者从其他地方启动Activity时,系统如何管理和创建Activity实例。理解并合理...

    88个Android应用程序

    手势识别是Android应用程序中一个重要的交互方式。GestureRecognizeSample可能是一个实现了自定义手势识别的示例项目,它展示了如何使用Android的手势库(GestureOverlayView)或自定义手势识别算法来解析用户的...

    拦截Activity的项目

    在Android中,可以使用如dexopener或Xposed等工具,它们可以在运行时修改或替换类的行为,实现Activity启动的拦截。 四、AndroidManifest.xml配置 在AndroidManifest.xml中,我们可以为每个Activity设置...

    androidkit(android应用开发工具包)

    androidkit是一个android应用开发工具包,包含SQLiteOpenHelper的简单实现类、获取指定URL中返回的内容的String对象、View控件的截图、获取 本程序的图标、名字、版本、包名等信息、再按一次退出、抽象类,继承并...

    Android 两个Activity之间传值

    在Android应用开发中,Activity是用户界面的基本单元,经常需要在不同的Activity之间传递数据。本文将详细介绍如何在Android的两个Activity之间进行值的传递,并结合实际案例进行解析。 首先,我们可以通过Intent...

    android Service 与Activity绑定

    在Android应用开发中,Service和Activity是两个非常重要的组件,它们各自承担着不同的职责。Service主要负责在后台长时间运行的任务,而Activity则专注于用户界面的交互。本篇将深入探讨Service与Activity之间的绑定...

    service中启动activity

    然而,Service本身并不能直接启动一个Activity,因为它们属于不同的Android组件生命周期。通常,Service启动Activity是通过发送意图(Intent)来实现的。 **一、Service启动Activity的基本流程** 1. **创建Intent**:...

    Android获取包名方法

    以下是几种常见的获取Android应用程序包名的方法,每种方法都各具特点,适用于不同的操作环境和使用场景。 方法一:使用adb命令行工具 首先,确保你的计算机上安装了Android Debug Bridge (adb) 工具,该工具是...

    Android开发 两个Activity之间通过Intent跳转传值

    在Android应用开发中,Intent是连接应用程序组件的重要桥梁,它被用来启动新的Activity或Service,也可以传递数据。本文将深入探讨如何在两个Activity之间通过Intent进行数据传递。 首先,理解Intent的基本概念。...

    从网页启动Activity

    【标题】"从网页启动Activity"这一主题主要探讨的是如何在Android应用开发中,通过网页链接触发Android设备上的Activity启动,实现Web与App之间的交互。这通常涉及到WebView组件的使用,以及利用Intent过滤器来捕获...

    Android应用管理器

    总的来说,Android应用管理器是一个集多种技术于一体的工具,它涉及到Android系统的多个核心组件和服务,如PackageManager、ActivityManager和Intent机制。通过理解和掌握这些知识,开发者不仅能创建出高效且用户...

    Android-ResourceInspector一个调试工具用于显示当前Activity所使用的布局文件

    - 当Activity启动或改变状态时,工具会捕获到这些变化,并将使用的布局文件信息展示出来。 2. **使用方法**: - 首先,将`nekocode-ResourceInspector-1cee97b`压缩包解压,获取源代码。 - 将源代码导入Android ...

    Android应用源码时光日志本一句话记录每一天

    这款应用的核心功能是让用户每天用简洁的语言记录下自己的所思所感,形成一个时间线式的个人日记。通过源码分析,我们可以深入理解Android应用程序的开发原理和技术细节。 首先,我们要探讨的是Android应用的基本...

Global site tag (gtag.js) - Google Analytics