Jak dużo powiadomień generuje Android?
Dzisiaj dość proste zadanie, ale może być interesujące.
Od kilku lat jestem użytkownikiem i fanem serwisu If This The That który pozwala na automatyzację wielu zadań. W skrócie polega to na tym, że podpinamy do IFTTT.com swoje konta, aplikacje, urządzenia (żarówki, samochody – bo czemu nie?) i budujemy przepisy (applets). Każdy przepis to zawsze dwa elementy: wyzwalacz i akcja. Na przykład: jeśli temperatura spadnie poniżej 5 stopni (wyzwalacz) to wyślij maila (akcja). Możemy łączyć ze sobą kilka serwisów (jeśli dodam nowe zdjęcie na Instagramie to zapisz je w Dropboxie), informować o czymś mailem (wyślij maila jeśli prognoza według Weather Underground przewiduje deszcz), zapisywać historię zdarzeń (wszystkie moje twitty zapisz do arkusza Google) czy też zarządzać telefonem (włącz wi-fi jeśli jestem w rejonie oznaczonym jako dom).
I właśnie z połączenia informacji z telefonu zapisywanymi do arkusza Google Sheets skorzystamy. Odpowiedni przepis IFTTT: jeśli Notification received to add row to Google Drive spreadsheet.
Po kilku dniach na Dysku Google dostaniemy arkusz, w którym kolejne wiersze to kolejne zdarzenia. Teraz tylko wystarczy dobrać się do tego pliku (ciekawostka – po przekroczeniu 5000 wierszy powstaje nowy plik) i przeanalizować jego zawartość. W wydobyciu plików z Google Drive pomocny będzie pakiet R googledrive. Zatem do dzieła!
1 2 3 4 5 6 7 |
# install.packages("googledrive") library(googledrive) library(tidyverse) library(lubridate) library(readxl) library(fs) |
Co się wydarzy poniżej?
Najpierw wyszukamy w Google Drive wszystkie pliki z notification w nazwie (tak skonfigurowałem applet w IFTTT). Następnie dla każdego znalezionego pliku:
- pobierzemy go na dysk lokalny (zapisze się w formacie Excela)
- wczytamy ten plik do tymczasowej tabelki
- zamienimy datę z ciągu tekstowego na typ wygodny do późniejszej manipulacji
- usuniemy duplikaty (bo z rożnych powodów pojawiają się takowe)
- wszystkie takie tymczasowe tabeli złączymy w jedną
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# pobranie listy plików z Google Drive lista <- drive_find(pattern = "notification*") %>% # zostawiamy tylko te, które zaczynają się od odpowiedniego ciagu filter(str_sub(name, 1, 13) == "notifications") # funkcja kopiuje plik z Google Drive lokalnie get_file <- function(id, filename) { if(file_exists(paste0("notifications/notification", i, ".xlsx"))) file_delete(paste0("notifications/notification", i, ".xlsx")) as_id(id) %>% drive_get() %>% drive_download(path = filename) # domyślnie plik Google Sheets będzie zapisany jako plik Excela } # folderek na sciagane pliki dir_create("notifications") # tabelka na pełne dane (z wielu plików) dane <- tibble() # dla wszystkich znalezionych plików for(i in 1:nrow(lista)) { # kopiujemy plik lokalnie get_file(lista[[i, "id"]], paste0("notifications/notification", i)) # wczytujemy dane z pliku lokalnego dane_tmp <- read_excel(paste0("notifications/notification", i, ".xlsx"), col_names = c("Data", "Aplikacja", "Komunikat", "KomunikatFull")) # poprawiamy daty dane_tmp <- dane_tmp %>% mutate(Data_ok = mdy_hm(Data)) %>% distinct() # łączymy w jedna wielką tabelę dane <- bind_rows(dane, dane_tmp) } # poprawiamy datę i usuwamy niechciane aplikacje ;) dane <- dane %>% mutate(Godzina = hour(Data_ok), Dzien_tyg = wday(Data_ok, week_start = 1)) %>% filter(!Aplikacja %in% removed_apps) |
To tyle, jeśli chodzi o najciekawszą część tego wpisu. Reszta to już zwykłe EDA.
Zacznijmy od tego jak dużo powiadomień obsługuje mój telefon każdego dnia.
1 2 3 4 5 6 |
dane %>% mutate(Data = as_date(Data_ok)) %>% count(Data) %>% ggplot() + geom_col(aes(Data, n), fill = "lightgreen")+ geom_smooth(aes(Data, n)) |
Widzimy, że rozkład jest mniej więcej równomierny. Nie wiem skąd wynika dziura w połowie marca – być może z jakiegoś powodu dane nie zapisywały się?
Jak wygląda statystyka dzienna tych powiadomień?
1 2 3 4 5 6 7 8 |
dane %>% mutate(Data = as_date(Data_ok)) %>% count(Data) %>% pull(n) %>% summary() ## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 22.0 111.8 147.0 148.5 183.2 300.0 |
Średnio prawie 150 powiadomień dziennie! To jest jakiś dramat… Na szczęście spora część z nich nie jest widoczna – pojawiają się i za chwilę znikają, nie trzeba ich nawet usuwać z paska.
Zobaczmy jak wygląda torcik dla 20 aplikacji, które wysyłają najwięcej powiadomień:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
dane %>% count(Aplikacja, sort = T) %>% ungroup() %>% mutate(rn = row_number()) %>% mutate(Aplikacja = if_else(rn <= 20, Aplikacja, "Inne")) %>% mutate(p = n/sum(n)) %>% group_by(Aplikacja) %>% summarise(p = sum(p)) %>% ungroup() %>% arrange(desc(p)) %>% mutate(Aplikacja = fct_inorder(sprintf("%s %.1f%%", Aplikacja, 100*p))) %>% ggplot() + geom_col(aes(1, p, fill = Aplikacja), color = "gray10") + coord_polar(theta = "y", direction = -1) + theme_void() |
Wykresy kołowe są kiepskie z założenia. Jedyny powód dla którego jest tutaj wykres kołowy to… pokazanie Wam ja się go robi w ggplot (coord_polar() połączone ze słupkiem z geom_col() gdzie ważna jest jedynka dla X!). Dodanie opisów poszczególnych kawałków wykresu to droga przez mękę, dlatego dodałem wartości w legendzie.
W każdym razie jedna trzecia to powiadomienia systemowe, jedna szósta to VLC. Do tego o czym są te powiadomienia jeszcze dojdziemy.
W jakich godzinach aplikacje puszczają notyfikacje? Czy jest to podczas jakiejś interakcji użytkownika z telefonem czy też dzieje się cały czas?
1 2 3 4 5 |
dane %>% count(Godzina, Aplikacja) %>% ggplot() + geom_col(aes(Godzina, n, fill = Aplikacja), color = "gray50", show.legend = FALSE) + facet_wrap(~Aplikacja, scales = "free_y", ncol = 4) |
Jak zwykle: to zależy. Niektóre aplikacje o czymś informują całą dobę. A inne wtedy kiedy są jakieś interakcje (na przykład w serwisach społecznościowych).
Jak to wygląda dodatkowo w podziale na dni tygodnia?
1 2 3 4 5 6 7 8 9 |
dane %>% count(Aplikacja, Godzina, Dzien_tyg) %>% mutate(Dzien_tyg = factor(Dzien_tyg, levels = 1:7, labels = c("pn", "wt", "śr", "cz", "pt", "sb", "nd"))) %>% mutate(Dzien_tyg = fct_rev(Dzien_tyg)) %>% ggplot() + geom_tile(aes(Godzina, Dzien_tyg, fill = n), color = "gray50") + scale_fill_distiller(palette = "YlOrRd") + facet_wrap(~Aplikacja, ncol = 4) + theme(legend.position = "bottom") |
Co tutaj mamy?
- ACR – aplikacja odpowiedzialna za nagrywanie rozmów, co mniej więcej godzinę chce wysyłać pliki do chmury (bez sensu – powinna robić to tylko po nagraniu)
- Chrome Beta – powiadomienia związane z pobieraniem plików ze stron (na przykład PDFy). Oczywiście wtedy, kiedy korzystam z telefonu do przeglądania sieci.
- Dropbox – komunikat “Wstrzymano przesyłanie z aparatu” przy niskim poziomie naładowania baterii
- ES Eksplorator plików – czasem potrzebuję coś skąś przekopiować telefonem
- Facebook – oczywiste powiadomienia o komentarzach i tym podobnych
- Gazeta.pl – informacje push z najważniejszymi wiadomościami
- Gmail – powiadomienia o nowej poczcie, niżej trochę więcej o tym – skąd biorą się maile w nocy?
- Hangouts – wiadomo; widać że z komunikatora korzystam (tutaj: dostaję wiadomości, wysłanych nie ma w powiadomieniach) w ciągu dnia
- Instagram – prawie nie używam, co widać :)
- Interfejs – to ciekawa kategoria, niżej wyjaśnienie i szczegóły
- JuiceSSH – najlepszy wg mnie klient SSH na telefon, pokazuje w powiadomieniu z jakim serwerem jest połączony (trochę czasem przez shella trzeba zrobi na serwerku)
- Kalendarz – nie mam synchronizacji z korpo-kalendarzem, stąd mało powiadomień
- LinkedIn – standardowe powiadomienia o komentarzach, polubieniach i zaproszeniach do znajomych
- Listonic – lista zakupów, najczęściej powiadomienia o tym, że żona coś do niej dodała ;) Najczęściej w sobotę przed około-południowymi zakupami
- Mapy – powiadomienia podczas nawigacji – wygląda na to, że najwięcej podróżuję z nawigacją w weekendy. W tygodniu chodzi głównie o korki
- mBank – powiadomienia z aplikacji o przelewach i płatnościach kartą (widać kiedy płacę)
- Menedżer pobierania – update’y z Google Play
- Menedżer stron – aplikacja do obsługi fanpage’a Dane i Analizy – powiadomienia o komentarzach
- Messenger – facebookowy komunikator, z którego nie korzystam za wiele
- OneDrive – co kilkanaście minut pisze, że “Trwa przygotowanie…” nie wiadomo czego i do czego
- Reddit – prawie nie udzielam się, prawie nie mam powiadomień
- Sklep Google Play – informacje o aktualizacjach aplikacji (po co dublowane w Menedżerze Pobierania?)
- Spotify – wiadomo – aktualnie grany utwór, muzyki słucham głównie w weekendy lub popołudniami korzystając z Chromecasta
- System Android – działa całą dobę, ale w ciągu dnia bardziej – dlaczego? Będzie niżej.
- Telefon – informacje o połączeniach
- TrueCaller – raz na dobę (lub częściej) pokazuje coś w stylu “Caller ID is active” – po co? A aplikacja znakomita do rozpoznawania spamu telemarketingowego
- Twitter – wiadomo
- Usługi Google Play – głównie “Urządzenie w sieci Wi-Fi przesyła multimedia” przy okazji streamingu do Chromecasta z Spotify lub YouTube
- VLC – odtwarzacz wideo (od co najmniej pół roku niczego nie oglądałem w ten sposób…), aplikacja skanuje media na telefonie i dodaje je do biblioteki. Przy okazji przygotowania tej analizy po prostu to wyłączyłem
- Wiadomości – SMSy, będzie niżej o tym kto je śle.
- Zarządzanie połączeniami – informacje o nieodebranych połączeniach (dlaczego nie w Telefon?)
- Zegar – budzik; korzystam z Zegarka od Google, jak widać powiadomienie włącza się 2 godziny przed budzikiem (i z tego poziomu daje możliwość wyłączenia budzika – zwykle wyłączam go zanim zadzwoni, co widać po odcieniach z godziny 5 i 7 rano)
Przejdźmy do analizy kilku aplikacji. Kto pisze tyle maili? I przede wszystkim kto robi to w nocy?
1 2 3 4 5 6 7 8 |
dane %>% filter(Aplikacja == "Gmail") %>% count(Komunikat, Godzina) %>% filter(n >= 7) %>% # tylko nadawcy, którzy wysłali więcej niż 7 maili o tej samej godzinie ggplot() + geom_tile(aes(Godzina, Komunikat, fill = n), color = "gray50") + scale_fill_distiller(palette = "YlOrRd") + theme(legend.position = "bottom") |
Jak widać główniej jest to mailing. Powiadomienia z Pracuj.pl zostały z dawnych czasów, ostatnio je wyłączyłem. Ale to głównie one przychodziły nocą. Normalne maile przychodzą w ciągu normalnego dnia.
Zobaczmy najczęstsze komunikaty z poszczególnych aplikacji
1 2 3 4 5 6 7 |
dane %>% filter(Aplikacja %in% c("System Android", "VLC", "Sklep Google Play", "Menedżer pobierania", "ACR", "Facebook", "mBank")) %>% count(Aplikacja, Komunikat) %>% group_by(Aplikacja) %>% filter(n >= mean(n) + sd(n)) %>% # ot takie sitko ungroup() %>% arrange(Aplikacja, desc(n)) |
Aplikacja | Komunikat | n |
---|---|---|
277 | ||
mBank | Nowa operacja kartą | 122 |
Menedżer pobierania | 16 | |
Menedżer pobierania | Mapy | 16 |
Menedżer pobierania | 15 | |
Menedżer pobierania | IFTTT | 13 |
Menedżer pobierania | Chrome Beta | 12 |
Menedżer pobierania | 12 | |
Menedżer pobierania | Messenger | 12 |
Menedżer pobierania | Google Play | 11 |
Menedżer pobierania | 11 | |
Menedżer pobierania | Smart AudioBook Player | 11 |
Menedżer pobierania | YouTube | 11 |
Menedżer pobierania | Google Duo | 10 |
Menedżer pobierania | Spotify Music | 10 |
Menedżer pobierania | SwiftKey Beta | 10 |
Menedżer pobierania | Truecaller – ID dzwoniącego | 10 |
Menedżer pobierania | Google+ | 9 |
Menedżer pobierania | Reddit: Top News, Trending Memes & Crypto Updates | 9 |
Menedżer pobierania | Zdjęcia Google | 9 |
Sklep Google Play | Zaktualizowano 1 aplikację | 79 |
Sklep Google Play | Nie można zaktualizować aplikacji | 69 |
Sklep Google Play | Zaktualizowano 1 aplikację | 52 |
System Android | Zmień klawiaturę | 2245 |
System Android | Aplikacja Mi Band Tools działa w tle | 1699 |
Widzimy tutaj które aplikacje (ich nazwa znajduje się w kolumnie Komunikat) są często aktualizowane (Menedżer pobierania w kolumnie Aplikacja). To dane z 90 dni – wynikałoby z tego, że np. Facebook był aktualizowany mniej więcej co tydzień.
Skąd biorą się powiadomienia z aplikacji System Android?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
dane %>% filter(Aplikacja == "System Android") %>% group_by(Komunikat) %>% mutate(n = n()) %>% ungroup() %>% filter(n >= 1000) %>% mutate(Data = as_date(Data_ok)) %>% count(Data, Godzina, Komunikat) %>% ggplot() + geom_tile(aes(Data, Godzina, fill = nn), color = "gray30") + scale_fill_distiller(palette = "YlOrRd") + scale_y_reverse() + facet_wrap(~Komunikat) + theme(legend.position = "bottom") |
Używam opaski Mi Band 2, stąd powiadomienie Aplikacja Mi Band Tools działa w tle. Ale same powiadomienia z aktywnością fizyczną (z Mi Fit, Stravy czy googlowego Fit) wyciąłem z danych tutaj publikowanych. Pokazuję dużo, ale nie przesadzajmy! Poza tym niewiele ciekawego wnosiły.
Mamy też rozwiązanie zagadki zwiększonej liczby powiadomień systemowych w ciągu dnia. Normalnie co godzinę (czy jakoś podobnie) system informuje o współpracy z Mi Band Tools, a podczas pisania – proponuje zmianę klawiatury.
Od kogo przychodzą SMSy i kiedy? Znowu – wybieram tylko najpopularniejsze:
1 2 3 4 5 6 7 8 9 10 |
dane %>% filter(Aplikacja == "Wiadomości") %>% group_by(Komunikat) %>% mutate(n = n()) %>% ungroup() %>% filter(n > 5) %>% count(Godzina, Komunikat) %>% ggplot() + geom_col(aes(Godzina, nn, fill = Komunikat), show.legend = FALSE) + facet_wrap(~Komunikat, ncol = 1) |
Wyjaśnienie jest proste:
- mBank to potwierdzenia przelewów (pamiętajcie że to suma z 3 miesięcy)
- Orange to reklamy i komunikaty sieci
- PlayFinanse to powiadomienia o fakturach (wystawionych lub opłaconych)
A że zmieniam operatora stąd własnie Play i Orange.
Co to jest za aplikacja Interfejs i… kiedy rozładowuje się mój telefon? Informacja o stopniu naładowania baterii poniżej 15% pochodzi właśnie z aplikacji Interfejs. Zobaczmy w jakich godzinach pojawiają się kolejne komunikaty:
1 2 3 4 5 6 7 8 9 10 11 |
dane %>% filter(Aplikacja == "Interfejs", Komunikat == "Niski poziom baterii") %>% count(Godzina, KomunikatFull) %>% mutate(KomunikatFull = gsub("Pozostało |%", "", KomunikatFull) %>% as.numeric()) %>% arrange(KomunikatFull) %>% mutate(KomunikatFull = sprintf("Pozostało %d%%", KomunikatFull)) %>% mutate(KomunikatFull = fct_inorder(KomunikatFull)) %>% ggplot(aes(Godzina, KomunikatFull, fill = n)) + geom_tile(color = "gray30") + scale_fill_distiller(palette = "YlOrRd") + theme(legend.position = "bottom") |
Zazwyczaj telefon wpinam do ładowarki wieczorem. Co da się zapewne wywnioskować z powyższego wykresu.
To tylko przykład na wykorzystanie danych zapisanych w arkuszach Google. A także sposób na pozyskanie interesujących nas danych do dalszej pracy.
Najlepiej znamy dane o sobie – wiemy na przykład do kogo piszemy SMSy, a za pomocą IFTTT możemy zapisywać treść wszystkich (przychodzących i wychodzących) do arkusza. Dzięki zgromadzonym takim sposobem danym możemy przeprowadzić samodzielnie analizę (do lub od kogo, w jakich porach, jakich słów używając) treści tych SMSów. To świetna szkoła, bo wynik analiz jest z grubsza znany – trzeba tylko znaleźć metodę dojścia do niego.