<!--
title: "統計手機的簡訊資料"
summary: "疫情兩年期間，我們究竟發了多少實聯制簡訊呢？"
date: 2022-04-29T12:49:04+08:00
categories: "How I Work"
tags: ["android"]
-->

實聯制在4月27日走入歷史，與很多邊緣人一樣，
疫情期間，實聯制佔據了我手機中幾乎所有簡訊的份額。
不誇張地說，或許 1922 將會是我們此生中發過最多簡訊的號碼了！

在和它道別的同時，我也想知道疫情期間自己到底發送了多少簡訊？
那麼，是時候用 adb 這項工具來做點事了！

## Android 的簡訊政策

Android 中，每個可見的功能都由特定的 APP 所提供。
在查詢 Android Developer 手冊後，
可以知道所有簡訊 APP 均實作名為 [Telephony provider](https://developer.android.com/reference/android/provider/Telephony) 的 Content Provider ， 
因此可在名稱為 `com.android.providers.telephony` 的 APP 中找到手機簡訊的資料。

首先是第一步，備份 `com.android.providers.telephony` 的所有資料:
```bash
adb backup -apk com.android.providers.telephony -f telephony.ab
```

## 還原簡訊資料

這個備份出來的 `.ab` (Android Backup) 檔案嘛，雖然說是 Android 的備份用檔案，
不過平常它需要搭配 `adb restore` 等指令以還原在 Android 系統上。
就我所知在任何官方文件上都沒有提到其它處理方法。
不過既然我們要讀取它的內容，當然要直接暴力解開啦！

好在根據一些論壇大神的指引，這邊我了解到：`.ab` 實際上是個用 zlib 作成的 tar 壓縮檔。
另外一個重點是：
該壓縮檔還在開頭加了 24 byte 的前綴，用以標示自己是 Android 的備份檔案。

有了以上的資訊事情就好辦了，這邊直接使用一些基本的指令就可以還原資料：
```bash
# 用 tail 印出 24 byte 以後的檔案內容
# 交由 pigz 解壓縮 和 tar 解開
tail -c +25 telephony.ab | pigz -d | tar -xf -
```

## 處理原始資料

取得 APP 的原始資料後，接著就簡單了！
目錄下所有結尾為 `sms_backup` 的檔案都是簡訊資料，
把它們解壓縮即可得到像這樣的 JSON 物件：
```json
{
    "address": "0911510196",
    "body": "親愛的客戶您好:謝謝您使用郵政VISA金融卡於05/26 09:35 消費新臺幣290元,如有疑義,請撥打卡片背面客服電話.",
    "date": "1653528972961",
    "date_sent": "1653528971000",
    "status": "-1",
    "type": "1",
    "recipients": [ "0911510196" ],
    "read": "1"
}
```

可以見到，除了來源的電話號碼外，也有時間欄位。
有了這些資訊，就可以用 JSON 工具輕鬆處理資料啦！
這邊使用 jq 進行處理。

```bash
# 從所有名為 XXXsms_backup 的檔案中
# 取得收件者為 1922 的簡訊資料
# 每筆一行，存檔在 1922.sms
for sms in **/*sms_backup; do pigz -d <$sms; done | \
jq -c '.[]|select(.address=="1922")' >1922.sms
    
# Count how many SMS messages with address = 1922
wc -l 1922.sms

# Get the first and the last time of SMS messages
jq -r .date 1922.sms | sort | sed -n 's/...$//;1p;$p' | xargs -i date -d @{}
```

因為我上一支手機壞掉時沒有妥善轉移資料，所以最早有紀錄的簡訊是從去年開始。

從以上的指令可以知道：去年10月開始到昨天，4月27日，我總共發了1066則簡訊給 1922 ！
