开发过程中有时候需要获取android开机时间,这个是两年前遇到的一个问题,在此总结一下。

方法一、通过系统SystemClock接口运算

android.os.SystemClock的elapsedRealtimeNanos返回从系统开机现在的经历过的时间(单位:纳秒),包括系统休眠待机时间。所以我们可以使用当前时间减去系统开机到现在的时间计算出系统的启动时间

// 返回开机时间,单位微妙
long bootTime() {return System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() / 1000000;
}

根据SmarxPan的提示可以使用毫秒函数SystemClock.elapsedRealtime()

// 返回开机时间,单位微妙
long bootTime() {return System.currentTimeMillis() - SystemClock.elapsedRealtime();
}

方法二、通过读取/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();@Testpublic void testNativeGetBootTime() {Log.d(TAG, "testNativeGetBootTime...");Log.d(TAG, "boot time: " + DeviceHelper.native_getBootTime());}@Testpublic 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如何获取系统开机时间相关推荐

  1. C# 获取系统开机时间

    C# 获取系统开机时间 原文:C# 获取系统开机时间 ///         ///  获取系统开机时间          ///         ///         private DateTi ...

  2. python 获取系统开机时间

    from psutil import boot_time from time import time def main():bootTime = (time()-boot_time())/3600pr ...

  3. java 查询启动时间_java获取系统开机时间

    Runtime.getRuntime().exec来得到, 头疼, 上代码: import java.io.BufferedReader; import java.io.IOException; im ...

  4. VC++ 获取Windows系统开机时间

    以下提供两种方法获取Windows系统的开机时间 第一种是使用C++的函数,该方法使用当前时间减去系统运行时间,秒级的,偶尔存在1秒的差异 第二种是使用Windows的API,该方法获取到的时间与cm ...

  5. android service 样例(电话录音和获取系统当前时间)

    关于android service 的具体解释请參考: android四大组件--android service具体解释.以下将用两个实例具体呈现Android Service的两种实现. 一个是st ...

  6. android自动获取系统时间,Android获取系统时间的多种方法

    Android中获取系统时间有多种方法,可分为Java中Calendar类获取,java.util.date类实现,还有android中Time实现. 现总结如下: 方法一: void getTime ...

  7. android 获取系统当前时间

    android 获取系统当前时间 来源 1 2 3 完事 来源 @听着music睡 ---- 关于安卓开始实现最简单地获取系统时间 @Android学院 ---- Android获取当前系统日期和时间 ...

  8. Android 系统(194)---Android实践 -- 设置系统日期时间和时区

    Android实践 -- 设置系统日期时间和时区 转自:https://www.cnblogs.com/Free-Thinker/p/6627813.html 设置系统日期时间和时区 设置系统的日期时 ...

  9. c 获取当前时间插入oracle数据库,Oracle如何获取系统当前时间等操作实例,c++获取系统时间...

    Oracle如何获取系统当前时间等操作实例,c++获取系统时间 获取系统当前时间 date类型的 select sysdate from dual; char类型的 select to_char(sy ...

  10. oracle 取系统当前年份_Oracle如何获取系统当前时间等操作实例

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 获取系统当前时间 date类型的 ? 1 select sysdate from dual; char类型的 ? 123456 select to_cha ...

最新文章

  1. Java finally语句到底是在return之前还是之后执行?
  2. 9道最佳解酒方法[转]
  3. glance was not installed properly
  4. wxWidgets:wxRichTextFormattingDialog类用法
  5. PAT(乙级) 1001 害死人不偿命的(3n+1)猜想 C++
  6. 人生苦短,Python值得!这些Pandas隐藏小技巧你知道吗?
  7. Photos_2017 China MVP Community Connection
  8. java实现modbus rtu协议与 modscan等工具(3)物理连接
  9. Java小项目---电影购票系统
  10. SIP协议详解(二)
  11. 绝对高效实现! 给你一个包含n个整数的数组nums,判断nums是否存在三个元素a,b,c使得a+b+c =0...
  12. nginx的 ngx.var ngx.ctx ngx.req
  13. Volkswagen profit roars back two yea iot L?sungen rs after 'dieselgate'
  14. 版权和商标权有什么关系?版权和商标的区别在哪里?
  15. Java化小数为分数_杭电oj1717——小数化分数(java实现)
  16. execute immediate在存储过程中的使用
  17. 关于The C10K problem的一些资料
  18. 深度学习目标检测---使用yolov5训练自己的数据集模型(Windows系统)
  19. 数字化转型 — 新能源汽车 — 产品设计与研发流程
  20. 欢聚时代(YY)视频编解码面经

热门文章

  1. 【16年浙江省赛 B ZOJ 3937】More Health Points【树上dfs、斜率优化dp、动态维护下凸壳】
  2. 278.第一个错误版本(力扣leetcode) 博主可答疑该问题
  3. [Luogu] 被污染的河流
  4. 采购订单暂存和持有相关的问题?
  5. 《Android权威编程指南(The Big Nerd Ranch Guide)(第二版)》12.4挑战练习
  6. android深度探索第二章
  7. 远程执行命令不成功的问题
  8. Java笔记1(2015-8-30)
  9. Java虚拟机垃圾回收
  10. SpringCloud整合Feign的调用源码流程解析