Android可视化显示手机电池电量信息

最近做了个小功能,打算写出来分享一下。文笔不好,标题起得不怎么样,一眼看去可能看不出是要说什么内容,但是又不想起个特别长的标题,就这样吧,随缘

进入正文,最近学习了Python,结合自己当前从事的Android开发的工作,想到了一个小功能,就是通过Python解析android log,提取其中电量的日志进行可视化显示。这是一个很小众的功能,估计基本上不会有人用得上,但是个人感觉是很有趣的一件事。

先上效果图:

battery_level.html

文章内容主要是通过以下几个方面描述,尽可能通俗易懂

  1. 获取日志
  2. 脚本编写
  3. 运行结果

1. 获取日志

电池电量信息我们可以从android日志的events log中获取,events log可通过以下命令获取

adb logcat -b events > events.log

其中,电池电量的关键字是battery_level

11-19 06:15:40.076  1502  1538 I battery_level: [91,4164,302]
11-19 06:18:36.180  1502  2042 I battery_level: [90,4224,325]
11-19 06:26:30.404  1502  2042 I battery_level: [89,4203,338]
11-19 06:33:11.701  1502  2042 I battery_level: [88,4179,345]
11-19 06:40:53.762  1502  2042 I battery_level: [87,4184,349]
11-19 06:46:58.554  1502  2042 I battery_level: [86,4160,355]
11-19 06:52:14.718  1502  2042 I battery_level: [85,4150,359]
11-19 06:58:37.736  1502  2042 I battery_level: [84,4143,352]

battery_level在代码中的描述如下:

 battery_level (level|1|6),(voltage|1|1),(temperature|1|1)
  • 第一个参数level表示当前电池电量
  • 第二个参数voltage表示当前电池电压
  • 第三个参数temperature表示当前电池温度

2. 脚本编写

通过battery_level的log格式可以大致得出以下步骤:

  1. 定义Battery相关类
  2. 逐行读取events log的日志并提取出battery_level行,解析行转换成Battery类
  3. 通过highcharts显示数据

2.1 定义Battery类

class Battery:
    # 日期
    date = ''
    # 时间
    timestamp = ''
    # 电量
    level = 0
    # 电压
    voltage = 0
    # 温度,log中单位需要除以10才是摄氏度的单位,用浮点数表示
    temperature = 0.0

2.2 解析日志

# events.log
inputfile = ''

def check_battery():
    if os.path.exists(inputfile):
        battery_array = []
        f = open(inputfile, 'rb')
        line = f.readline()
        while line:
            if "battery_level" in line:
                battery = Battery()
                temp_line = line.split()
                battery.date = temp_line[0]
                battery.timestamp = temp_line[1]
                # 有些日志可能会有些奇怪的问题,这里加个判断规避异常情况
                if len(temp_line) > 6:
                    # 这里应该是可以用正则表达式进行优化
                    conf = temp_line[6].replace("[", "").replace("]", "").split(",")
                    battery.level = int(conf[0])
                    battery.voltage = int(conf[1])
                    battery.temperature = int(conf[2]) / 10.0
                battery_array.append(battery)
            line = f.readline()
        f.close()
        if len(battery_array) > 0:
            # 生成报告,可视化显示,在2.3节中介绍
            generate_report(battery_array)
    else:
        print ("No evnet log file found")
    print ("Done")

2.3 可视化显示

结果是通过html显示,用到的是highchart显示折线图。这里不详细介绍highcharts的使用,有兴趣的可自行搜索了解。这里简单介绍一下highcharts的参数

  • title: 标题
  • xAxis: 横坐标的值和描述
  • tooltip: 折线弹出气泡
  • legend: 图表样式
  • series: 折线数据

先将运行后生成的html简化后内容贴出来会比较容易理解生成报告的脚本,以下内容直接复制到一个文本文件,修改后缀为html打开后就是文章前面截图的效果

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<html>
<head>
<!-- highcharts 需要引用的js库 -->
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
</head>
<style>
body {margin: 0 auto; width:80%; padding: 20px}
</style>
<body>
<div id="level_container" style="width: 100%; height: 300px; margin: 0 auto"></div>
</body>
<script type="text/javascript">
$(document).ready(function() {
var title = { text: 'Battery Level' };
var xAxis = {
// 脚本生成是一行,为了显示清楚手动换行
categories: ['06:15:40.076','06:18:36.180','06:26:30.404','06:33:11.701',
'06:40:53.762','06:46:58.554','06:52:14.718','06:58:37.736',
'07:05:06.852','07:12:36.779','07:20:43.179','07:26:35.815',
'07:32:16.296','07:37:56.775','07:43:37.262','07:49:17.738',
'07:55:22.713','08:00:26.691','08:05:18.531','08:11:56.862',
'08:18:01.665','08:23:50.243','08:25:51.842','08:29:06.399']
};
var yAxis = {title: {text: 'Level'},
plotLines: [{value: 0, width: 1, color: '#808080'}]};
var tooltip = {valueSuffix: ''}
var legend = {layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0};
var series =  [{
name: 'Level',
data: [91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68]
}];
var json = {};
json.title = title;
json.xAxis = xAxis;
json.yAxis = yAxis;
json.tooltip = tooltip;
json.legend = legend;
json.series = series;
$('#level_container').highcharts(json);
});
</script>
</html>

脚本没什么特别的地方,就是打开文件写内容:

# report.html
outputfile = ''

def write_report(line):
    f = open(outputfile, 'a+')
    f.write(line)
    f.write('\n')
    f.close()

def battery_report(battery_array):
    write_report("<script type=\"text/javascript\">")
    #level
    write_report("$(document).ready(function() {")
    write_report("var title = { text: 'Battery Level' };")
    write_report("var xAxis = {")
    timestamps = '['
    for i in battery_array:
        timestamps = timestamps + "'" + i.timestamp + "',"
    timestamps = timestamps[:-1]
    timestamps = timestamps + "]"
    write_report("categories: " + timestamps)
    write_report("};")
    write_report("var yAxis = {title: {text: 'Level'},")
    write_report("plotLines: [{value: 0, width: 1, color: '#808080'}]};")
    write_report("var tooltip = {valueSuffix: ''}")
    write_report("var legend = {layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0};")
    write_report("var series =  [{")
    write_report("name: 'Level',")
    levels = []
    for i in battery_array:
        levels.append(i.level)
    write_report("data: " + str(levels))
    write_report("}];")
    write_report("var json = {};")
    write_report("json.title = title;")
    write_report("json.xAxis = xAxis;")
    write_report("json.yAxis = yAxis;")
    write_report("json.tooltip = tooltip;")
    write_report("json.legend = legend;")
    write_report("json.series = series;")
    write_report("$('#level_container').highcharts(json);")   
    write_report("});")
    # voltages
    write_report("$(document).ready(function() {")
    write_report("var title = { text: 'Battery Voltage' };")
    write_report("var xAxis = {")
    timestamps = '['
    for i in battery_array:
        timestamps = timestamps + "'" + i.timestamp + "',"
    timestamps = timestamps[:-1]
    timestamps = timestamps + "]"
    write_report("categories: " + timestamps)
    write_report("};")
    write_report("var yAxis = {title: {text: 'Voltage (mV)'},")
    write_report("plotLines: [{value: 0, width: 1, color: '#808080'}]};")
    write_report("var tooltip = {valueSuffix: 'mV'}")
    write_report("var legend = {layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0};")
    write_report("var series =  [{")
    write_report("name: 'Voltage',")
    voltages = []
    for i in battery_array:
        voltages.append(i.voltage)
    write_report("data: " + str(voltages))
    write_report("}];")
    write_report("var json = {};")
    write_report("json.title = title;")
    write_report("json.xAxis = xAxis;")
    write_report("json.yAxis = yAxis;")
    write_report("json.tooltip = tooltip;")
    write_report("json.legend = legend;")
    write_report("json.series = series;")
    write_report("$('#voltage_container').highcharts(json);")   
    write_report("});")
    # temperature
    write_report("$(document).ready(function() {")
    write_report("var title = { text: 'Battery Temperature' };")
    write_report("var xAxis = {")
    timestamps = '['
    for i in battery_array:
        timestamps = timestamps + "'" + i.timestamp + "',"
    timestamps = timestamps[:-1]
    timestamps = timestamps + "]"
    write_report("categories: " + timestamps)
    write_report("};")
    write_report("var yAxis = {title: {text: 'Temperature (\\xB0C)'},")
    write_report("plotLines: [{value: 0, width: 1, color: '#808080'}]};")
    write_report("var tooltip = {valueSuffix: '\\xB0C'}")
    write_report("var legend = {layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0};")
    write_report("var series =  [{")
    write_report("name: 'Temperature',")
    temperatures = []
    for i in battery_array:
        temperatures.append(i.temperature)
    write_report("data: " + str(temperatures))
    write_report("}];")
    write_report("var json = {};")
    write_report("json.title = title;")
    write_report("json.xAxis = xAxis;")
    write_report("json.yAxis = yAxis;")
    write_report("json.tooltip = tooltip;")
    write_report("json.legend = legend;")
    write_report("json.series = series;")
    write_report("$('#temperature_container').highcharts(json);")   
    write_report("});")
    write_report("</script>")

def generate_report(battery_array):
    write_report("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">")
    write_report("<html align='left'>")
    write_report("<head>")
    write_report("<script src=\"http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js\"></script>")
    write_report("<script src=\"http://code.highcharts.com/highcharts.js\"></script>")
    write_report("</head>")
    write_report("<style>")
    write_report("body {margin: 0 auto; width:80%; padding: 20px}")
    write_report("</style>")
    write_report("<body>")
    write_report("<div id=\"level_container\" style=\"width: 100%; height: 300px; margin: 0 auto\"></div>")
    write_report("<div id=\"voltage_container\" style=\"width: 100%; height: 300px; margin: 0 auto\"></div>")
    write_report("<div id=\"temperature_container\" style=\"width: 100%; height: 300px; margin: 0 auto\"></div>")
    write_report("</body>")
    # 电池电量可视化
    battery_report(battery_array)
    write_report("</html>")

3. 运行结果

附上所有代码,加上命令行传参功能:

import getopt
import os
import sys


inputfile = ''
outputfile = 'report.html'


class Battery:
    date = ''
    timestamp = ''
    level = 0
    voltage = 0
    temperature = 0.0


def write_report(line):
    f = open(outputfile, 'a+')
    f.write(line)
    f.write('\n')
    f.close()


def battery_report(battery_array):
    write_report("<script type=\"text/javascript\">")
    #level
    write_report("$(document).ready(function() {")
    write_report("var title = { text: 'Battery Level' };")
    write_report("var xAxis = {")
    timestamps = '['
    for i in battery_array:
        timestamps = timestamps + "'" + i.timestamp + "',"
    timestamps = timestamps[:-1]
    timestamps = timestamps + "]"
    write_report("categories: " + timestamps)
    write_report("};")
    write_report("var yAxis = {title: {text: 'Level'},")
    write_report("plotLines: [{value: 0, width: 1, color: '#808080'}]};")
    write_report("var tooltip = {valueSuffix: ''}")
    write_report("var legend = {layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0};")
    write_report("var series =  [{")
    write_report("name: 'Level',")
    levels = []
    for i in battery_array:
        levels.append(i.level)
    write_report("data: " + str(levels))
    write_report("}];")
    write_report("var json = {};")
    write_report("json.title = title;")
    write_report("json.xAxis = xAxis;")
    write_report("json.yAxis = yAxis;")
    write_report("json.tooltip = tooltip;")
    write_report("json.legend = legend;")
    write_report("json.series = series;")
    write_report("$('#level_container').highcharts(json);")   
    write_report("});")
    # voltages
    write_report("$(document).ready(function() {")
    write_report("var title = { text: 'Battery Voltage' };")
    write_report("var xAxis = {")
    timestamps = '['
    for i in battery_array:
        timestamps = timestamps + "'" + i.timestamp + "',"
    timestamps = timestamps[:-1]
    timestamps = timestamps + "]"
    write_report("categories: " + timestamps)
    write_report("};")
    write_report("var yAxis = {title: {text: 'Voltage (mV)'},")
    write_report("plotLines: [{value: 0, width: 1, color: '#808080'}]};")
    write_report("var tooltip = {valueSuffix: 'mV'}")
    write_report("var legend = {layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0};")
    write_report("var series =  [{")
    write_report("name: 'Voltage',")
    voltages = []
    for i in battery_array:
        voltages.append(i.voltage)
    write_report("data: " + str(voltages))
    write_report("}];")
    write_report("var json = {};")
    write_report("json.title = title;")
    write_report("json.xAxis = xAxis;")
    write_report("json.yAxis = yAxis;")
    write_report("json.tooltip = tooltip;")
    write_report("json.legend = legend;")
    write_report("json.series = series;")
    write_report("$('#voltage_container').highcharts(json);")   
    write_report("});")
    # temperature
    write_report("$(document).ready(function() {")
    write_report("var title = { text: 'Battery Temperature' };")
    write_report("var xAxis = {")
    timestamps = '['
    for i in battery_array:
        timestamps = timestamps + "'" + i.timestamp + "',"
    timestamps = timestamps[:-1]
    timestamps = timestamps + "]"
    write_report("categories: " + timestamps)
    write_report("};")
    write_report("var yAxis = {title: {text: 'Temperature (\\xB0C)'},")
    write_report("plotLines: [{value: 0, width: 1, color: '#808080'}]};")
    write_report("var tooltip = {valueSuffix: '\\xB0C'}")
    write_report("var legend = {layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0};")
    write_report("var series =  [{")
    write_report("name: 'Temperature',")
    temperatures = []
    for i in battery_array:
        temperatures.append(i.temperature)
    write_report("data: " + str(temperatures))
    write_report("}];")
    write_report("var json = {};")
    write_report("json.title = title;")
    write_report("json.xAxis = xAxis;")
    write_report("json.yAxis = yAxis;")
    write_report("json.tooltip = tooltip;")
    write_report("json.legend = legend;")
    write_report("json.series = series;")
    write_report("$('#temperature_container').highcharts(json);")   
    write_report("});")
    write_report("</script>")


def generate_report(battery_array):
    write_report("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">")
    write_report("<html>")
    write_report("<head>")
    write_report("<script src=\"http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js\"></script>")
    write_report("<script src=\"http://code.highcharts.com/highcharts.js\"></script>")
    write_report("</head>")
    write_report("<style>")
    write_report("body {margin: 0 auto; width:80%; padding: 20px}")
    write_report("</style>")
    write_report("<body>")
    write_report("<div id=\"level_container\" style=\"width: 100%; height: 300px; margin: 0 auto\"></div>")
    write_report("<div id=\"voltage_container\" style=\"width: 100%; height: 300px; margin: 0 auto\"></div>")
    write_report("<div id=\"temperature_container\" style=\"width: 100%; height: 300px; margin: 0 auto\"></div>")
    write_report("</body>")
    battery_report(battery_array)
    write_report("</html>")


def check_battery():
    if os.path.exists(inputfile):
        battery_array = []
        f = open(inputfile, 'rb')
        line = f.readline()
        while line:
            if "battery_level" in line:
                battery = Battery()
                temp_line = line.split()
                battery.date = temp_line[0]
                battery.timestamp = temp_line[1]
                if len(temp_line) > 6:
                    conf = temp_line[6].replace("[", "").replace("]", "").split(",")
                    battery.level = int(conf[0])
                    battery.voltage = int(conf[1])
                    battery.temperature = int(conf[2]) / 10.0
                battery_array.append(battery)
            line = f.readline()
        f.close()
        if len(battery_array) > 0:
            generate_report(battery_array)
    else:
        print ("No evnet log file found")
    print ("Done")


def remove_report():
    if os.path.exists(outputfile):
        os.remove(outputfile)


def help():
    print ("python check_battery.py -i event.log -o report.html")


def main(argv):
    if len(argv) < 1:
        print ("args must more than one. please use -h to see more")
        sys.exit()
    try:
        opts, args = getopt.getopt(argv, "hi:o:",["inputfile=", "outputfile="])
    except getopt.GetoptError:
        sys.exit(2)
    for opt, arg in opts:
        if opt == "-h":
            help()
            sys.exit()
        elif opt in ("-i", "--inputfile"):
            global inputfile
            inputfile = arg
        elif opt in ("-o", "--outputfile"):
            if not arg.endswith(".html"):
                arg = arg + ".html"
            global outputfile
            outputfile = arg
    remove_report()
    check_battery()


if __name__ == "__main__":
    main(sys.argv[1:])

运行:

$ python check_battery.py -i event.log

输出结果:report.html

report.html

总结

python确实是个特别好的工具,工作中有很大的帮助。工作中我不止写了解析电池的脚本,还写了解析属性文件、应用信息、系统设置的脚本,后续还会考虑使用脚本解析anr、watchdog等trace log。当然,这个解析工作有些复杂,特别是watchdog类型的trace要考虑的情况比较多,先立个flag,共勉。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 本文由作者张迎贞授权网易云社区发布。 APP性能测试除了需要监控PCU、内存占用、流量等,还需要获取APP的电量数...
    43ce3d72fadb阅读 772评论 0 0
  • 安卓系统通过广播来接受电池状态,下面是我写的一个简单电池管理项目。 广播接受类BatteryReceiver如下:...
    简单Liml阅读 1,545评论 0 1
  • 一 三月,北方的残冬未尽,积雪还未消融,南方却已春风拂柳,梨花带雨。“绿杨烟外晓寒轻,红...
    落梅姐阅读 1,490评论 7 12
  • 纷纷扰扰的世界 像我一样的人 会有什么样的颜色的梦想呢 五颜六色的 但是我只喜欢灰色的梦想 那是一种朦胧的梦 那是...
    半分微凉阅读 150评论 0 2
  • 这个深夜 我失眠了 在一张窄窄的小床上 翻来覆去的思念 可那个他啊 已经走远了 说出口的话啊 覆水难收 明明知道 ...
    超级胡萝卜大大阅读 928评论 13 17