android如何获取系统开机时间

原创 2017年08月03日 22:59:33
开发过程中有时候需要获取android开机时间,这个是两年前遇到的一个问题,在此总结一下。
方法一、通过系统SystemClock接口运算
android.os.SystemClock的elapsedRealtimeNanos返回从系统开机现在的经历过的时间(单位:纳秒),包括系统休眠待机时间。所以我们可以使用当前时间减去系统开机到现在的时间计算出系统的启动时间
// 返回开机时间,单位微妙
long bootTime() {
    return System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() / 1000000;
}
方法二、通过读取/proc/stat文件获取系统开机时间
方法一获取系统开机时间非常方便,但是有一个缺点必须在Android 4.2以上才能支持该接口,也就是说在低平台调用接口会应为找不到该函数而闪退。

不过没关系,我们可以使用linux层提供的信息。
关于 /proc/stat文件: stat文件记录了当前系统常有状态,例如cpu时钟,内存页,开机时间等等。其中开机时间是btime字段后面的数值单位是秒
以下是本人手机设备的 /proc/stat内容(华为, Android6.0系统)
shell@HWGRA:/proc $ cat stat
cpu  1840729 131539 1145597 10753491 13057 57 45011 0 0 0
cpu0 246543 17369 249206 7219225 3792 11 32119 0 0 0
cpu1 282309 19254 210287 545809 2092 39 4639 0 0 0
cpu2 279958 19834 209812 547156 2380 3 2743 0 0 0
cpu3 276153 20196 203136 548855 2257 4 1970 0 0 0
cpu4 173666 14209 67996 502766 1131 0 1414 0 0 0
cpu5 205458 13675 70375 448196 528 0 703 0 0 0
cpu6 210211 13822 70829 449078 430 0 710 0 0 0
cpu7 166431 13180 63956 492406 447 0 713 0 0 0
intr 164085213 0 0 0 0 341 0 0 0 167 167 0 0 0 4 3 0 0 0 0 0 0 0 0 0 0 0 0 19263077 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50348 0 0 0 0 0 0 6615253 0 0 0 0 0 0 68541 0 0 620 0 0 0 0 3304 0 0 0 0 0 0 0 0 177234 26390930 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 53695 0 0 32981493 9285925 2391853 2011 0 0 0 0 0 0 0 0 0 485 0 0 0 0 0 1480860 100 2118249 0 0 0 0 5 998345 0 196 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 991829 51562 0 0 0 131664 0 918 0 429104 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69486 31005 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 21 0 0 0 0 0 0 286338 0 0 0 8 1 0 143155 1
ctxt 197939068
btime 1501803547
processes 238588
procs_running 2
procs_blocked 0
softirq 78287404 12496 14322913 16214 439295 11578 11578 45998374 3558439 4601 13911916
可以看到btime字段
btime 1501803547
表示从1970-01-01 00:00:00 +0000起始的时间,单位:秒
可以用java轻松实现,本博客使用jni实现。
主要实现方案
头文件:android_system_utils .h
#ifndef ANDROID_SYSTEM_UTILS_H
#define ANDROID_SYSTEM_UTILS_H

#include <cstddef>

class android_system_utils {
public:
    /**
     * get android system boot time(unit second).
     * time since 1970-01-01 00:00:00 +0000 (UTC).
     */
    static long getBootTime();

private:
    static long parseBootTime(const char* text, size_t size);
};

#endif
源文件:android_system_utils.cpp
#include "android_system_utils.h"

#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <cctype>

#include "common.h"
#include "file_utils.h"

static char TAG[] = "android_system_utils";

long android_system_utils::getBootTime() {
    const char filepath[] = "/proc/stat";

    if (!file_utils::isExists(filepath)) {
        return -1;
    }

    int fd = open(filepath, O_RDONLY);
    if (-1 == (fd)) {
        lerror(TAG, "getBootTime. open: %s file failed. errno: %d, error: %s", errno, strerror(errno));
        return -1;
    }
    errno = 0;
    char storebuf[128] = {0}; // 128bit is enough as we only concern about btime text.
    char buf[2] = {0};
    ssize_t len = 0;
    long ret = -1;
    do {
        memset(buf, 0, sizeof(buf));
        if ((len = safe_read(fd, buf, 1)) > 0) { // only read on character.
            if ('\n' == buf[0]) { // match a new line.
                if (-1 != (ret = parseBootTime(storebuf, strlen(storebuf)))) {
                    break;
                }
                memset(storebuf, 0, sizeof(storebuf));
            } else if (strlen(storebuf) < sizeof(storebuf) - 1) { // fill a line data.
                strcat(storebuf, buf);
            }
        }
    } while (len > 0);
    if (-1 == len) {
        lerror(TAG, "getBootTime. read error. errno: %d, error: %s", errno, strerror(errno));
    }

    close(fd);

    return ret;
};

long android_system_utils::parseBootTime(const char *text, size_t size) {
    const char btime[] = "btime";
    const char *find = strstr(text, btime);
    if (NULL == find) {
        return -1;
    }

    char c[2] = {0};
    char buf[64] = {0};
    for (size_t i = 0; i < size; i++) {
        c[0] = *(text + i);
        if (isdigit(c[0])) { // fill buf with digital.
            strcat(buf, c);
        }
    }
    if (0 == strlen(buf)) {
        return -1;
    }

    return atol(buf);
}
三、总结
虽然使用stat文件也能够获取开机时间,但是精度只能到达秒,还是没有系统SystemClock.elapsedRealtimeNanos的精度搞。因此我们折中处理,在android4.2高版本使用系统API接口,低版本使用stat数值接口,即保证兼容性又能够发挥高版本的精度问题。
DeviceHelper.java
package org.penny;

import android.os.Build;
import android.os.SystemClock;

/**
 * Created by lucky on 05/08/2017.
 */

public class DeviceHelper {
    static {
        System.loadLibrary("Pannel");
    }

    /**
     * get android system boot time(unit milli second).
     * time since 1970-01-01 00:00:00 +0000 (UTC).
     */
    public static long getBootTime() {
        if (Build.VERSION.SDK_INT < 17) {
            return native_getBootTime() * 1000;
        }
        return System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() / 1000000;
    }

    /**
     * get android system boot time(unit second).
     * time since 1970-01-01 00:00:00 +0000 (UTC).
     */
    public static native long native_getBootTime();
}
DeviceHelperTest.java
package org.penny;

import android.os.Build;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;

/**
 * Created by lucky on 05/08/2017.
 */

@RunWith(AndroidJUnit4.class)
public class DeviceHelperTest {
    private static final String TAG = DeviceHelperTest.class.getSimpleName();

    @Test
    public void testNativeGetBootTime() {
        Log.d(TAG, "testNativeGetBootTime...");
        Log.d(TAG, "boot time: " + DeviceHelper.native_getBootTime());
    }

    @Test
    public void testGetBootTime() {
        Log.d(TAG, "testGetBootTime...");
        Log.d(TAG, "boot time: " + DeviceHelper.getBootTime());

        if (Build.VERSION.SDK_INT >= 17) {
            assertEquals(DeviceHelper.native_getBootTime(), DeviceHelper.getBootTime() / 1000);
        }
    }
}
测试用例结果
--------- beginning of main
08-05 21:36:35.114 11597 11612 D DeviceHelperTest: testGetBootTime...
08-05 21:36:35.119 11597 11612 D DeviceHelperTest: boot time: 1501803547791
08-05 21:36:35.126 11597 11612 D DeviceHelperTest: testNativeGetBootTime...
08-05 21:36:35.128 11597 11612 D DeviceHelperTest: boot time: 1501803547
因为写博客的时候顺便跑过代码,所以就把代码发到github上面
https://github.com/FreeJack007/Pannel

Android开机时间分析

一、 关于本篇博文 该文档简单主要描述了如何找出开机各个阶段耗时情况,以及对开机各个阶段的分析方法和如何优化开机时间,减少耗时。便于读者可以通过此文档了解开机时间的各个阶段的耗时情况。 二、开机各阶段...
  • huangyabin001
  • huangyabin001
  • 2015年01月16日 15:26
  • 10796

Android设备开机时间统计

一篇关于Android设备的开机时间统计文章。
  • JeromeLiee
  • JeromeLiee
  • 2017年06月05日 12:27
  • 1235

Android开机速度优化

开机速度优化 主要关注当Java世界起来以后(即zygote起来之后)的开机速度优化。 从zygote到home显示的过程中,有如下几个耗时的过程: 1.preload-class。 ...
  • a87636764
  • a87636764
  • 2015年04月20日 20:14
  • 1193

代码获取android开机启动时间,已经开机启动应用

  • 2012年10月25日 16:37
  • 657KB
  • 下载

Android开机速度优化简单回顾

Android的开机速度,基本上没人说快的,通常移植完系统后,马上要看的事情就是优化开机时间,以下是简单回忆以下以前做优化的那些事。 开机时间都花在哪? 优化开机时间,通常做的首先是那有有没有BUG,...
  • freshui
  • freshui
  • 2016年12月17日 00:23
  • 6920

Android开机时间分析

一、 关于本篇博文 该文档简单主要描述了如何找出开机各个阶段耗时情况,以及对开机各个阶段的分析方法和如何优化开机时间,减少耗时。便于读者可以通过此文档了解开机时间的各个阶段的耗时情况。 二、开机各...
  • xiaodanpeng
  • xiaodanpeng
  • 2016年07月07日 09:07
  • 1064

有关android加快开机速度

有关android加快开机速度       我们知道,android开机速度慢,在恢复出厂设置后开机速度更慢,其中优化dex文件的过程就耗时很多。那么我们就可以尝试将优化dexopt步骤...
  • haima1998
  • haima1998
  • 2014年06月04日 23:18
  • 1271

浅谈Android开机启动速度优化(含应用程序启动速度优化)

众所周知Android开机启动速度较慢,于是如何加快启动速度便成为一个值得讨论的问题。在查阅过许多资料后(特别是Google Group的android-platform),我整理总结出下面几点基本看...
  • jackyu613
  • jackyu613
  • 2010年11月30日 00:41
  • 58315

Android下获取开机时间

  • 2011年09月28日 15:12
  • 56KB
  • 下载

Android 获取系统开机时长 启动时长

Android中SystemClock类,是专门用来统计系统启动后至当前的时长,也就是设备从开机到目前的时间。在Andriod中关于线程一部分中经常会遇到计算时间的操作,这里面应用较多的是System...
  • jiujiedexiaoming
  • jiujiedexiaoming
  • 2015年07月16日 01:06
  • 3831
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android如何获取系统开机时间
举报原因:
原因补充:

(最多只允许输入30个字)