获取小米运动APP体重数据

王大佬说想看体重变化曲线,但小米运动App不能看长时间段的曲线,并且App中数据没有对外提供接口,故有了这篇文章。

获取备份文件

方法一 - 用ADB方式获取备份文件

  1. 下载adb

    see: https://stackoverflow.com/questions/31374085/installing-adb-on-macos

  2. 进入adb shell

    adb shell
  3. 查找app名称

    ls mnt/sdcard/Android/data | grep 'xiaomi'
  4. 备份app数据

    adb backup -f xm.ab com.xiaomi.hm.health
  5. 解包

    see: https://stackoverflow.com/questions/18533567/how-to-extract-or-unpack-an-ab-file-android-backup-file

    java -jar abe-all.jar unpack xm.ab xm.rar

但是发现获得的备份文件是空的,查了下资料发现国内一些应用禁止了备份操作,所以我选择了另一种方式。

方法二 - 用系统自带备份方案获取备份文件

我用的一加手机,系统自带一加搬家应用,可以用来获取备份文件。

解析获取数据

将备份文件解压后找到体重数据库文件data/data/com.xiaomi.hm.health/databases/origin_db_c958f7a915bd74127753f190bbd6adf6,体重数据存储在WEIGHT_INFOS表中。

#-*- coding:utf8 -*-
# Copyright (c) 2019 barriery
# Python release: 3.7.0
import sqlite3
import datetime
import matplotlib.pyplot as plt

def get_data(filename):
    data = [] # (date, weight, BMI)
    with sqlite3.connect(filename) as conn:
        c = conn.cursor()
        cursor = c.execute('SELECT * from WEIGHT_INFOS')
        for row in cursor:
            date = datetime.datetime.fromtimestamp(row[0]/1000)
            weight = row[1]
            BMI = row[10]
            data.append((date, weight, BMI))

    date_array, weight_array, BMI_array = [], [], []
    for date, weight, BMI in data:
        date_array.append(date)
        weight_array.append(weight)
        BMI_array.append(BMI)
    return date_array, weight_array, BMI_array

def get_idxes(data):
    rdate, rweight, rBMI = data
    rdate = [datetime.datetime.strptime(x.strftime('%Y-%m-%d'), '%Y-%m-%d') for x in rdate]
    idxes = []
    fdate, fweight, fBMI = [], [], []

    days, idx = 0, 0
    begin, end = rdate[0], rdate[-1]
    now = begin
    while now != end:
        while idx < len(rdate) and now > rdate[idx]:
            idx += 1
        if idx < len(rdate) and now == rdate[idx]:
            idxes.append(days)
            fdate.append(rdate[idx].strftime('%Y-%m-%d'))
            fweight.append(rweight[idx])
            fBMI.append(rBMI[idx])
        days += 1
        now = begin + datetime.timedelta(days=days)
    return idxes, (fdate, fweight, fBMI)

def draw(idxes, data):
    date, weight, BMI = data
    plt.plot(idxes, weight, '.:')
    interval = len(idxes) // 10
    plt.xticks(idxes[::interval], date[::interval], rotation=45)
    plt.xlabel("date")
    plt.ylabel("weight(kg)")
    plt.show()

if __name__ == '__main__':
    filename = 'origin_db_c958f7a915bd74127753f190bbd6adf6'
    data = get_data(filename)
    idxes, fdata = get_idxes(data)
    draw(idxes, fdata)

效果图

weight

关于Python的日期操作

struct_time

datetime

参考

https://www.twblogs.net/a/5d874d93bd9eee5327000b75/zh-cn

https://www.open-open.com/lib/view/open1479363382807.html

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×