9 czerwca 2015

Tasker - aktualizacja do wersji 4.7

Wczoraj, po długim okresie beta testów, pojawiła się nowa wersja Taskera 4.7. Zachęcam do aktualizacji.

Lista zmian

  • Prefs / Misc: Android Backup
  • action Tasker / Import Data
  • action Array Process: Sort Numeric Integer and Sort Numeric Floating-Point
  • action Send Intent: Extra fields: support for parcelable Java objects created with Java Function
  • action Send Intent: Extra fields: support for Uris via casting of value
  • action Send Intent: extra Extra field (also for JS function)
  • file selection: text box for specification
  • file selection for local data backup and restore
  • scene element WebView: Background tab
  • action Test System: added Android ID test type
  • action Test Display / Orientation: added landscape-reverse and portrait-reverse values
  • per-action log access in task edit screen after test runs
  • action Vibrate/Vibrate Pattern: Continue On Error param
  • action Zip: Target File parameter
  • action Media Control: option to send the command to a specific app
  • main screen profile/task/scene list: multi-select mode action: Move To Top (when items are user-sorted)
  • main screen profile/task/scene: sort by age
  • action Zip: Target File parameter
  • action Media Control: option to send the command to a specific app
  • scene element TextEdit: Focus event
  • action Element Text: parameter Selection (TextEdit elements only)
  • JS: function Say: parameters Respect Audio Focus and Use Network
  • scene element Web: Support Popups parameter for e.g. form selection elements
  • state Net / Auto Sync
  • action Launch App: parameter Always Start New Copy, default is now to use existing copy of app when possible
  • Music Play Dir: Audio Only: extra file extensions
  • display-off monitoring: use of significant motion sensor where available (no power usage when stationary,
  • Prefs / Monitor / Display Off / Motion Detection (enabled by default)
  • BODY_SENSORS permission for Heart Rate
  • State / Heart Rate (untested)
  • variable: %HEART (Heart Rate) (untested)
  • action Net / HTTP Head
  • events Variables / Variable Cleared/Set: parameter User Variables Only
  • event Tasker / Timer Change (when Task Timer status changes)
  • Tasker / Test Tasker: type Timer Widget Remaining
  • Prefs / UI / List Item Drag Margin / Disable option
  • variable %TNET: try using getprop as workaround when Android doesn't return a value
  • action Get Voice: parameter Language
  • actions File / GZip and File / GUnzip
  • state Power / Battery Temperature
  • state Power Save Mode (Android 5.0+)
  • task edit screen: test buttons: log display when action fails
  • Search Tasker: matches also against action parameters which have a set of strings to choose for the value

Pobieranie

Google Play
Strona Taskera

18 marca 2015

Energooszczędna lokalizacja w Taskerze

Dziś zajmę się tematem bardzo często poruszanym przez użytkowników Taskera. Mianowicie chodzi o lokalizację i zmianę ustawień/uruchamianie tasków w zależności od miejsca, w którym przebywa użytkownik wraz z urządzeniem. Lokalizacja bazująca na GPS i usługach lokalizacyjnych Google nie należy do zbyt energooszczędnych dlatego ja zaproponuję swoje rozwiązanie, które dopieszczam od wielu lat. Pewne aspekty tego projektu zapożyczone są z rozwiązań kolegi Mariusza Turka oraz użytkownika YouTube PolePosition.
Projekt bazuje na dwóch etapach lokalizacji. W pierwszym poszukiwana jest strefa WiFi (czyli obszar gdzie w urządzeniu jest włączana łączność WiFi) na podstawie działających w tej strefie nadajników GSM. Drugi etap to poszukiwanie sieci WiFi, która jednoznacznie identyfikuje dane miejsce (przykładowo połączenie z siecią domową Tasker interpretuje jako obecność użytkownika w domu). Dopełnieniem całości jest profil skanujący nadajniki w celu tworzenia danych dla poszukiwania strefy WiFi. W tym przypadku posłużę się aplikacją Power Toggles, która umożliwia tworzenie przycisków w panelu notyfikacji.

Wymagania

Opis wykonania

Zaczynamy od dodania do wcześniejszego profilu Połączone WiFi zmiennej %WIFIC, która będzie otrzymywać wartość 1 gdy urządzenie będzie miało połączenie z siecią WiFi oraz czyszczona, gdy tego połączenia nie będzie.

Kolejnym krokiem jest stworzenie profilu, który będzie zapisywał do zmiennej numery nadajników GSM. Wykorzystam do tego zmienną %CELLID, w której przechowywany jest numer nadajnika GSM. Profil opiera się o pętlę, która odczytuje zawartość zmiennej 6 razy co 30 sekund co pozwoli zebrać więcej danych. Obróbka danych wykonana będzie poprzez stworzenie z nich tablicy, w której usunięte zostaną duplikaty, puste elementy tablicy oraz na koniec elementy zostaną posortowane. Następnie elementy tablicy oddzielone znakiem końca linii zostają zapisane do zmiennej %NadajnikiStrefyWiFi.

Ze zmienną %CELLID wiąże się dziwna przypadłość. Zmienna ta zawiera wartość tylko wtedy gdy użyta jest w tasku uruchomionym poprzez profil. Z tego względu musiałem stworzyć dodatkowy profil PT Skanowanie nadajników, który uruchamia task skanowania gdy zmienna %SkanNadajników otrzyma wartość 1. Wartość tą nadaję taskiem PT Skan nadajników, który jest uruchamiany poprzez klawisz Power Toggles.

Poniżej instrukcja jak dodać za pomocą Power Toggles klawisz w panelu powiadomień uruchamiający task Taskera.

Teraz tworzymy profil Strefa WiFi, który odpowiada za pierwszy etap lokalizacji. Profil ten uaktywniać się ma poprzez kontekst Cell Near z podaną zmienną %NadajnikiStrefyWiFi gdy nieaktywny jest tryb samolotowy oraz zmienna %WIFIC jest różna od 1. W tasku wejściowym tego profilu jest tylko jedna akcja - włączenie WiFi.

Kolejnym profilem jest Poza strefą WiFi, którego kontekstami są Cell Near ze zmienną %NadajnikiStrefyWifi i zaznaczoną zmienną Invert, brak tryby samolotowego i zmienna %WIFIC różna od 1. W tasku wejściowym profilu następuje wyłączenie WiFi po 30 sekundach oczekiwania i sprawdzeniu czy zmienna %WIFIC jest różna od 1, a profil Strefa WiFi nie jest aktywny. Zapobiegnie to wyłączeniu WiFi jeśli użytkownik połączył się z jakąś inną siecią oraz włączaniu i wyłączaniu WiFi gdy jest się na na skraju strefy WiFi.

Ostatnim etapem jest stworzenie profili W domu, W pracy, itp. Dla przykładu dodałem do projektu profil W domu, w którym ustawiam głośność dzwonków i zmieniam ustawienia wibracji. Sposób wykorzystania tych profili każdy musi sam sobie oprogramować. Profile takie są aktywowane kontekstem WiFi Connected z wpisaną nazwą lub adresem MAC danej sieci WiFi.

Rozpisany projekt

Profile: Strefa WiFi (2)
Priority: 7 Restore: no Enforce: no
State: Cell Near [ Cell Tower / Last Signal:%NadajnikiStrefyWiFi Ignore Cells:* ]
State: Not Airplane Mode
State: Variable Value [ %WIFIC != 1 ]
Enter: Wejście do strefy WiFi (3)
A1: WiFi [ Set:On ]

Profile: Poza strefą WiFi (277)
Priority: 7 Restore: no Enforce: no
State: Not Cell Near [ Cell Tower / Last Signal:%NadajnikiStrefyWiFi Ignore Cells:* ]
State: Not Airplane Mode
State: Variable Value [ %WIFIC != 1 ]
Enter: Wyjście ze strefy WiFi (4)
A1: If [ %WIFIC = 1 ]
A2: Stop [ With Error:Off Task: ]
A3: Else
A4: Wait [ MS:0 Seconds:30 Minutes:0 Hours:0 Days:0 ]
A5: WiFi [ Set:Off ] If [ %WIFIC != 1 & %PACTIVE !~ *Strefa WiFi* ]
A6: End If

Profile: W domu (8)
Restore: no Enforce: no
State: Wifi Connected [ SSID:Dom MAC:* IP:* ]
Enter: Wewnątrz (9)
A1: Ringer Volume [ Level:5 Display:Off Sound:Off ]
A2: Notification Volume [ Level:5 Display:Off Sound:Off ]
A3: Vibrate On Ringer [ Set:Off ]
Exit: Na zewnątrz (10)
A1: Wait [ MS:0 Seconds:20 Minutes:0 Hours:0 Days:0 ]
A2: Stop [ With Error:Off Task: ] If [ %WIFIC = 1 ]
A3: Ringer Volume [ Level:7 Display:Off Sound:Off ]
A4: Notification Volume [ Level:7 Display:Off Sound:Off ]
A5: Vibrate On Ringer [ Set:On ]

Profile: Połączone WiFi (177)
State: Wifi Connected [ SSID:* MAC:* IP:* ]
Enter: Anon (178)
A1: Variable Set [ Name:%WIFIC To:1 Do Maths:Off Append:Off ]
A2: Variable Set [ Name:%wifiinfo To:%WIFII Do Maths:Off Append:Off ]
A3: Variable Search Replace [ Variable:%wifiinfo Search:(?<=(\n)).* Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo Replace Matches:Off Replace With: ]
A4: Variable Search Replace [ Variable:%wifiinfo2 Search:" Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo2 Replace Matches:On Replace With: ]
A5: If [ %SCREEN ~ on ]
A6: Variable Search Replace [ Variable:%wifiinfo5 Search:IP : Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo5 Replace Matches:On Replace With: ]
A7: Variable Search Replace [ Variable:%wifiinfo7 Search:Spd: Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo7 Replace Matches:On Replace With: ]
A8: Flash [ Text:Połączono z siecią %wifiinfo2
Adres IP: %wifiinfo5
Prędkość: %wifiinfo7 Long:On ]
A9: End If
Exit: Anon (258)
A1: Variable Clear [ Name:%WIFIC Pattern Matching:Off ]

Profile: PT Skanowanie nadajników (62)
Event: Variable Set [ Variable:%SkanNadajników Value:1 ]
Enter: Skanowanie nadajników (187)
A1: AutoNotification [ Configuration:Title: Skanowanie nadajników
Text: Trwa skanowanie nadajników GSM/3G strefy WiFi
Status Bar Icon: ic_action_signal
Id: Skan-Wifi
Persistent: true Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A2: Goto [ Type:Action Label Number:1 Label:koniec ] If [ %CELLID !Set ]
A3: Variable Set [ Name:%indeks To:1 Do Maths:Off Append:Off ]
A4: If [ %NadajnikiStrefyWiFi Set & %NadajnikiStrefyWiFi !~ *NadajnikiStrefyWiFi" ]
A5: Variable Search Replace [ Variable:%NadajnikiStrefyWiFi Search:.+ Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%array Replace Matches:Off Replace With: ]
A6: End If
<pętla>
A7: Array Push [ Name:%array Position:1 Value:%CELLID Fill Spaces:Off ]
A8: Wait [ MS:0 Seconds:30 Minutes:0 Hours:0 Days:0 ]
A9: Variable Add [ Name:%indeks Value:1 Wrap Around:0 ]
A10: Goto [ Type:Action Label Number:1 Label:pętla ] If [ %indeks < 7 ]
A11: Array Process [ Variable:%array Type:Remove Duplicates ]
A12: Array Process [ Variable:%array Type:Squash ]
A13: Array Process [ Variable:%array Type:Sort Numeric, Integer ]
A14: Variable Set [ Name:%enter To:
Do Maths:Off Append:Off ]
A15: Variable Join [ Name:%array Joiner:%enter Delete Parts:Off ]
A16: Variable Set [ Name:%NadajnikiStrefyWiFi To:%array Do Maths:Off Append:Off ]
<koniec>
A17: AutoNotification Cancel [ Configuration:Id: Skan-Wifi Package:com.joaomgcd.autonotification Name:AutoNotification Cancel Timeout (Seconds):0 ]
A18: Variable Clear [ Name:%SkanNadajników Pattern Matching:Off ]

PT Skan nadajników (69)
A1: Variable Set [ Name:%SkanNadajników To:1 Do Maths:Off Append:Off ]

Pobieranie projektu

Profil Energooszczędna lokalizacja [Tasker 4.7b4]

16 stycznia 2015

Diagnozowanie błędów w Taskerze

Im bardziej skomplikowane profile i taski się tworzy tym większa jest szansa na popełnienie błędu. Jak tego błędu szukać w Taskerze? Z osobistego doświadczenia wiem, że czasem można kilka dni patrzeć na błąd i go nie widzieć dlatego najlepiej od początku wyrobić w sobie nawyki, które pomogą go uniknąć. A jak już błąd się pojawi to trzeba znać sposoby na jego odnalezienie i zdiagnozowanie. Poniżej postaram się przedstawić sposoby jakie sam używam do tego, z lepszym bądź gorszym skutkiem.

Skokowe wykonywanie tasków

Począwszy od Taskera 4.6 jest możliwość skokowego wykonywania tasków. W dodatku kolorowymi kropkami aplikacja informuje czy dana akcja została wykonana bez błędów (kropka zielona) czy zakończyła się błędem (kropka czerwona). Znakiem "play" oznaczona jest akcja, która zostanie wykonana w następnym kroku.

W trakcie przerwy pomiędzy kolejnymi akcjami można wyjść z ekranu edycji tasku i na zakładce Zmienne podejrzeć wartości zmiennych na danym etapie wykonywania tasku.

Wyświetlanie błędów/ostrzeżeń Taskera

Prostą metodą na poszukiwanie błędów jest włączenie opcji Popup Errors/Warnings w Taskerze. Przy każdym wejściu do interfejsu Taskera, aplikacja wyświetli okno z błędami/ostrzeżeniami, które wydarzyły się od ostatniej wizyty w interfejsie. Fakt, że opis tych błędów i ostrzeżeń jest bardzo enigmatyczny i zazwyczaj nic nie mówi poza tym, że błędy są i należy je znaleźć.

Tosty podczas działania tasku

Najprostszym sposobem przeciwdziałania powstawania błędów oraz ich wyszukiwania jest używanie tostów umieszczonych na danym etapie wykonywania tasków. Tekst tostów może być bardzo różny. Ja czasem wstawiam do tostów numer akcji, w której są generowane dzięki czemu wiem jak daleko dotarło wykonywanie tasku. Czasem najlepiej sprawdza się tost z wartością zmiennej, która jest w danym tasku obrabiana. Wszystko zależy od tego co się tworzy i co chce się sprawdzić.

Własny log

Bardzo dobrym sposobem na kontrolę poprawności pracy profilów których działanie rozciągnięte jest w czasie jest stworzenie własnego loga tekstowego. Tworzy się go za pomocą akcji Write File z zaznaczonymi opcjami Add Newline (każdy zapis dodaje nową linię) oraz Append (zapis nie nadpisuje zawartości pliku). W polu Text należy podać takie dane jakie będą potrzebne do diagnozowania działania profilu. Najczęściej data i czas są bardzo pomocne. Samo miejsce umieszczenia zapisu do loga też należy dobrze przemyśleć. Zbyt duża ilość danych w logu utrudni jego interpretację zbyt mała nie dostarczy wystarczających danych.

Run Log

Ostatnią metodą, jaką używam, jest Run Log. Jest to funkcja wbudowana w Taskera. Uruchamia się ją z ekranu głównego naciskając menu / More / Run Log.

Run log po włączeniu pokazuje zmiany statusów profili oraz wykonywanych tasków i akcji. Dla łatwiejszej orientacji wpisy rozróżnione są kolorami:
  • fioletowy odpowiada za taski,
  • pomarańczowy za profile,
  • niebieski za akcje,
  • biały/czarny za monitor i usługę Taskera.
Po dłuższym przytrzymaniu danego elementu pokazuje się menu, które umożliwia przejście do odpowiedniego profilu/tasku/akcji lub filtrowanie loga.
Analizując log należy pamiętać, że taski oznaczone jako Anon to te, którym nie nadano nazw (właśnie dlatego opłaca się to robić) oraz, że wpisy, w których występuje zmienna pokazują jej wartość po zakończeniu tej akcji.

Kolumna ID tabeli loga

ID oznacza wewnętrzny numer identyfikacyjny profilu/tasku/akcji jaki nadaje im Tasker.
Po kropce w ID akcji umieszczany jest jej numer w tasku, przykładowo akcja o ID 20.3 to trzecia akcja tasku o ID 20.
Po dwukropku w ID tasku umieszczany jest numer kopii tasku równocześnie wykonywanego, przykładowo task o ID 6:2 to druga kopia tasku o ID 6 wykonywana równocześnie (dwie kopie tego tasku są wykonywane w tym momencie).

Kolumna Status tabeli loga

Status opisuje nowy status zdarzenia powodującego wpis w logu. Jeśli dany wpis zawiera błąd oznaczany jest kolorem czerwonym.

    Statusy usługi (Services)
  • Start usługa została uruchomiona. Niespodziewane uruchomienie usługi najczęściej jest powodowane przez zabicie jej przez system operacyjny gdy opcja Run In Foreground była wyłączona.
  • Stop usługa została zatrzymana.
  • Restart usługa została zrestartowana. Zazwyczaj ma to miejsce gdy nowe dane trzeba doczytać po zmianie konfiguracji przez użytkownika.

    Statusy profili
  • Active warunki profilu zostały spełnione i stał się on aktywny.
  • Inactive nie wszystkie warunki profilu były spełnione i przestał on być aktywny.
  • Instant profil typu instant był na moment aktywowany. Profil typu instant to nic innego jak profil z kontekstem typu Event, profil z kontekstem Time gdzie czas From i To jest ustawiony ten sam oraz profil z kontekstem Time z włączoną opcję Repeat.

    Statusy tasków
  • RejBad task został odrzucony np. nie miał zadeklarowanych akcji.
  • RejCopy task został odrzucony gdyż uruchomiona jest jego druga kopia z włączoną opcją Abort New Task.
  • RejMaxQ osiągnięto maksymalną długość kolejki tasków, którą można skonfigurować w opcjach.
  • Running task został dołączony do kolejki tasków i zaczyna być wykonywany.
  • ExitErr wykonywanie tasku zostało zatrzymane ze względu na pojawienie się błędu.
  • ExitOK wykonano wszystkie akcje tasku.
  • ExitRep task został zatrzymany gdyż uruchomiona została jego druga kopia z włączoną opcją Abort Existing Task.
  • ExitKill task został zatrzymany gdyż usługa Taskera została zatrzymana.

    Statusy akcji
  • Disabled akcja została wyłączona przez użytkownika i pominięta podczas wykonywania tasku.
  • Err podczas wykonywania akcji wystąpił błąd, który spowodował przerwanie wykonywania tasku.
  • ErrIgnore podczas wykonywania akcji wystąpił błąd ale wykonywanie tasku nie zostało przerwane, prawdopodobnie przez zaznaczoną opcję Continue On Error.
  • Exception wystąpił niespodziewany błąd, prawdopodobnie spowodowany przez system operacyjny lub Taskera, co spowodowało zatrzymanie wykonywania tasku.
  • OK akcja wykonana poprawnie.

To tyle na dziś. Jeśli będziesz miał pytania lub coś wyda Ci się niezrozumiałe to zapraszam do zadawania pytań w komentarzach. Postaram się pomóc.

19 grudnia 2014

Tasker - aktualizacja do wersji 4.6

Wczoraj pojawiła się nowa wersja Taskera 4.6, a kilka godzin później wersja poprawkowa 4.6u1. Zachęcam do aktualizacji.

Lista zmian

  • support for direct calling of Java functions integrated in normal task flow, see Java in the userguide
  • test tasks step-by-step and see status of each action as it completes
  • support for interrupt mode on Android 5.0+
  • added: action App / List Apps
  • added: action Script / Java Function, for calling Java functions
  • added: action Script / Java Object, for manipulation of Java objects
  • added: many long selection lists have a filter field
  • added: builtin local var %err (error in last enabled action if set)
  • added: task edit screen: currently executing action and status for past-actions displayed when testing
  • added: task edit screen: step-by-step task execution button
  • added: task tab double-click menu: Kill All option
  • added: monitor notification, set category to service (Lollipop+)
  • added: action Interrupt Mode (Lollipop+)
  • added: variable %UIMODE: watch (Lollipop+)
  • added: Italian translation (not userguide)
  • added: show in profile list whether a profile's tasks are locked or not
  • added: builtin action plugin list, added AutoInput
  • added: action Net / Test Net: support for bluetooth and ethernet
  • bugfix:action list: don't evaluate conditions for disabled actions
  • bugfix:test display res/DPI: was caching values and therefore reporting wrong ones after a display rotation
  • bugfix:%SILENT: report on when device interrupt mode is priority or none (Lollipop+)
  • bugfix:action Element Text with TextEdit element: couldn't set to zero-length
  • bugfix:element Button: labels were all uppercase (Lollipop+)
  • bugfix:task edit: rotation animation for opening/closing blocks was messed up (Lollipop+)
  • bugfix:action Beep: Amplitude parameter was being measured in ms instead of %
  • bugfix:action Show Scene / Continue Task Immediately: when deselected sometimes wasn't respected if scene was hidden
  • bugfix:action List Files: using root, if the dir wasn't reachable without root in pre-check would fail
  • bugfix:Userguide / Variables / Scene Local: behaviour was incorrectly documented
  • bugfix:swiping Tasker from recent apps list was closing the list (Lollipop+)
  • bugfix:when task was locked in UI, could be accessed via profile list without entering code if profile was locked
  • bugfix:Test Net: needed permission was missing in exported apps
  • bugfix:displayed scenes weren't generating accessibility events (e.g. for %WIN, Event / Button Widget)
  • change: action JavaScript(let): replace variables in Libraries parameter
  • change: action category Script -> Code
  • change: plugin actions/events/states are grouped per plugin app
  • change: action Run Shell: result code is stored in %err (if not 0) (and previously specified for backwards compatibility)
  • change: refreshed French, Spanish and Simplified Chinese translations
  • change: switched app detection to using an Accessibility Service please enable Tasker's service in Android Accessibility settings (Lollipop+)
  • removed: action Take Call: not available on Lollipop+ (Google not granting the needed permission)
  • removed: action Keyguard: apparently causing blackouts (Lollipop+)

Pobieranie

Google Play
Strona Taskera

11 grudnia 2014

Tasker i OpenVPN czyli dbamy o bezpieczeństwo

Jako, że od zawsze staram się dbać o bezpieczeństwo swoich danych i prywatności (przynajmniej na ile to możliwe w dzisiejszych czasach) unikam łączenia telefonu z nieszyfrowanymi sieciami WiFi. Niestety zdarzają się sytuacje, w których, trzeba z takich sieci skorzystać. Nie ma wtedy pewności czy hasła i loginy nie wpadną w łapy jakiegoś domorosłego "hakiera" bawiącego się w podszywanie pod punkt dostępowy. Rozwiązaniem tego problemu jest zastosowanie wirtualnych połączeń prywatnych czyli VPN, które tworzą szyfrowany tunel do serwera VPN i dane, które urządzenie przesyła są bezpieczne. Aby zdobyć dostęp do serwera VPN można wykupić sobie taką usługę, znaleźć darmowego dostawcę lub zrobić wszystko samemu, którą to opcję polecam. Coraz więcej nowoczesnych routerów posiada możliwość uruchomienia serwera OpenVPN w oprogramowaniu firmowym. Osobiście preferuję alternatywne oprogramowania dla routerów i praktycznie każdy z dostępnych (DD-WRT/Tomato/ OpenWRT/Gargoyle) udostępnia taką funkcjonalność. O konfiguracji usługi na routerze bądź wgrywaniu alternatywnego oprogramowania nie będę się tu rozpisywał ale jakby było zapotrzebowanie to chętnie pomogę. Należy tylko pamiętać, że konfigurując serwer należy wybrać opcję przesyłania pełnego ruchu sieciowego przez serwer.

Wymagania

Zakładam więc, że masz skonfigurowany serwer OpenVPN w routerze i utworzony profil dla telefonu. Co teraz? Potrzebny Ci będzie klient usługi OpenVPN, plugin do Taskera umożliwiający sterowanie połączeniem VPN oraz mój profil, który automatycznie będzie uruchamiał szyfrowany tunel w momencie połączenia z nieszyfrowaną siecią WiFi.
Jako klienta usługi stosuję OpenVPN for Android, a OpenVPN Tasker Plugin zapewnia mi współpracę z Taskerem. Konfiguracja OpenVPN for Android polega na imporcie pliku z rozszerzeniem ovpn po naciśnięciu klawisza Wczytaj.

OpenVPN Tasker Plugin nie wymaga konfiguracji. Po uruchomieniu wtyczka wyświetla status Aplikacji OpenVPN for Android i Taskera.

Opis wykonania

Jako, że połączenie z serwerem OpenVPN ma następować w momencie połączenia z niezabezpieczoną siecią WiFi do realizacji tego zadania wykorzystam profil Tost z danymi sieci WiFi po połączeniu.
Mam więc profil aktywowany poprzez WiFi Connected. W jego tasku wejściowym wartość zmiennej %WIFII przekazywana jest do zmiennej lokalnej %wifiinfo, za pomocą akcji Variable Search Replace z warunkiem RegEx (?<=(\n)).* wpisanym w pole Search i odznaczoną opcją Replace Matches zawartość zmiennej zostaje podzielona na poszczególne linie, które zostają zachowane w zmiennej %wifiinfo tworząc macierz. Użyte wyrażenie regularne wyszukuje tekst, po którym występuje znak \n czyli znak końca linii. Po tej operacji dostęp do poszczególnych linii jest możliwy poprzez podanie w parametrze numeru elementu macierzy np. %wifiinfo(3) lub %wifiinfo3. Następnie, znów za pomocą akcji Variable Search Replace, tym razem z zaznaczoną opcję Replace Matches i pustą zawartością pola Replace With czyszczę poszczególne linie z niepotrzebnych znaków " i tekstów by za moment wyświetlić tost z danymi sieci WiFi jeśli ekran jest włączony.

W kolejnym kroku sprawdzane jest czy sieć WiFi, do której właśnie podłączyło się urządzenie jest siecią domową (lub inną, dla której nie chcesz włączać połączenia VPN). Oczywiście możesz podać nazwy kilku sieci oddzielone znakiem / oraz podać maskę co zapewni omijanie wszystkich sieci, do których masz zaufanie.
Nastepnie za pomocą komend powłoki systemu umieszczonych w akcji Run Shell kopiowany jest plik wpa_supplicant.conf do tymczasowego katalogu Taskera. W pliku tym system przechowuje dane wszystkich znanych mu sieci. Dla akcji tej konieczne jest zaznaczenie opcji Use Root, a więc właściciele urządzeń bez dostępu do root nie skorzystają z tego profilu. Po wczytaniu zawartości pliku do zmiennej %wpa_supplicant za pomocą akcji Read File plik jest kasowany z katalogu tymczasowego za pomocą akcji Delete File.
Następnym zadaniem jest wyłuskanie z pliku listy nazw zapamiętanych sieci oraz sposobu ich zabezpieczenia. Wykonywane jest to za pomocą akcji Variable Search Replace bez zaznaczonej opcji Replace Matches. W pierwszym przypadku użyto wyrażenia regularnego (?<=(ssid=").*(?=("\n)), które wyszukuje teksty znajdujące się pomiędzy ssid=", a "\n i przekazuje je w formie macierzy do zmiennej %lista_ssid. W drugim przypadku wyrażenie regularne (?<=(key_mgmt=)).*(?=(\n)) wyszukuje teksty znajdujące się pomiędzy key_mgmt=, a znakiem końca linii i przekazuje je w formie macierzy do zmiennej %typy_kluczy.
Teraz można już za pomocą akcji Variable Set ustalić jaką pozycję na liście ma sieć, do której podłączone jest urządzenie. Wykonywane to jest za pomocą zapisu %lista_ssid(#?%wifiinfo2), który zwraca z macierzy %lista_ssid numer wartości odpowiadający %wifiinfo2 czyli nazwy aktualnie podłączonej sieci. Wartość ta zapisywana jest do zmiennej %indeks.

W tym momencie dostępne są już wszystkie dane niezbędne do sprawdzenia czy obecne połączenie jest szyfrowane. Warunkiem if sprawdzane jest czy %typy_kluczy(%indeks) jest różne od WPA-PSK czyli oznaczenia szyfrowania połączenia kluczem WPA. Jeśli tak task uruchamia połączenie OpenVPN za pomocą wtyczki ze skonfigurowaną siecią (w moim przypadku nazywa się ona Dom) oraz nadaje zmiennej %OpenVPN wartość 1.
Profil wymaga jeszcze tasku wyjściowego, w którym jeśli wartość %OpenVPN jest równa 1 wtyczka rozłącza połączenie z serwerem i następnie czyszczona jest zmienna %OpenVPN.
Cały profil wygląda następująco:

Rozpisany profil

Profile: Połączone WiFi (177)
State: Wifi Connected [ SSID:* MAC:* IP:* ]
Enter: Anon (178)
A1: Variable Set [ Name:%wifiinfo To:%WIFII Do Maths:Off Append:Off ]
A2: Variable Search Replace [ Variable:%wifiinfo Search:(?<=(\n)).* Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo Replace Matches:Off Replace With: ]
A3: Variable Search Replace [ Variable:%wifiinfo2 Search:" Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo2 Replace Matches:On Replace With: ]
A4: If [ %SCREEN ~ on ]
A5: Variable Search Replace [ Variable:%wifiinfo5 Search:IP : Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo5 Replace Matches:On Replace With: ]
A6: Variable Search Replace [ Variable:%wifiinfo7 Search:Spd: Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%wifiinfo7 Replace Matches:On Replace With: ]
A7: Flash [ Text:Połączono z siecią %wifiinfo2
Adres IP: %wifiinfo5
Prędkość: %wifiinfo7 Long:On ]
A8: End If
A9: If [ %wifiinfo2 !~ Siec_domowa ]
A10: Run Shell [ Command:mkdir -p /sdcard/Tasker/tmp
cp /data/misc/wifi/wpa_supplicant.conf /sdcard/Tasker/tmp Timeout (Seconds):0 Use Root:On Store Output In: Store Errors In: Store Result In: Continue Task After Error:On ]
A11: Read File [ File:/sdcard/Tasker/tmp/wpa_supplicant.conf To Var:%wpa_supplicant ]
A12: Delete File [ File:/sdcard/Tasker/tmp/wpa_supplicant.conf Shred Level:0 Use Root:Off ]
A13: Variable Search Replace [ Variable:%wpa_supplicant Search:(?<=(ssid=")).*(?=("\n)) Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%lista_ssid Replace Matches:Off Replace With: ]
A14: Variable Search Replace [ Variable:%wpa_supplicant Search:(?<=(key_mgmt=)).*(?=(\n)) Ignore Case:Off Multi-Line:Off One Match Only:Off Store Matches In:%typy_kluczy Replace Matches:Off Replace With: ]
A15: Variable Set [ Name:%indeks To:%lista_ssid(#?%wifiinfo2) Do Maths:Off Append:Off ]
A16: If [ %typy_kluczy(%indeks) !~ WPA-PSK ]
A17: OpenVPN [ Configuration:Connect (Dom) Package:com.ffrog8.openVpnTaskerPlugin Name:OpenVPN Timeout (Seconds):0 ]
A18: Variable Set [ Name:%OpenVPN To:1 Do Maths:Off Append:Off ]

Exit: Anon (258)
A1: If [ %OpenVPN = 1 ]
A2: OpenVPN [ Configuration:Disconnect Package:com.ffrog8.openVpnTaskerPlugin Name:OpenVPN Timeout (Seconds):0 ]
A3: Variable Clear [ Name:%OpenVPN Pattern Matching:Off ]

Pobieranie profilu

WiFi połączone / OpenVPN [Tasker 4.6b7]

Podziękowania

Dziękuję Mariuszowi "mrtur" Turkowi za pomoc przy testowaniu wykrywania przez Taskera niezabezpieczonych sieci WiFi.

27 listopada 2014

Właściwości profili i tasków

Gdy zaczynałem pisać ten wpis dotyczący właściwości profili i tasków wydawało mi się, że będzie on krótki, zajmie mi mało czasu i napiszę go bez zaglądania do pomocy Taskera. W trakcie pisania okazało się, że temat się rozrósł, a ja muszę przeczytać parę paragrafów pomocy i dowiedzieć się czegoś nowego. Zapraszam do lektury i komentowania.

Właściwości profili

Aby dostać się do właściwości profilu należy dłużej przytrzymać jego nazwę i w górnym pasku pojawią się dodatkowe klawisze, z których drugi od prawej strony prowadzi do właściwości danego profilu. Ekran właściwości prezentuje się następująco:

Priorytety tasków

Zanim przejdę do omawiania poszczególnych pozycji właściwości profilu muszę nieco przybliżyć sposób w jaki Takser traktuje taski oraz ich priorytety.
Gdy Tasker ma do wykonania jeden task to kolejno wykonuje jego wszystkie akcje. Jeśli jednak w kolejce do wykonania jest więcej tasków Tasker wykonuje je według następujących zasad:

  • nie może być wykonana więcej niż jedna akcja z danej grupy w tym samym czasie
  • task z wyższym priorytetem jest wykonywany przed taskiem z niższym priorytetem
  • taski o tych samych priorytetach wykonywane są kolejno (ich akcje mogą być wykonywane na przemian) zaczynając od tego, który został dodany do kolejki najwcześniej
  • wyjątek stanowi task będący potomkiem innego tasku, który zostanie wykonany przed pozostałymi taskami czekającymi w kolejce
Uważny czytelnik zapyta w tym miejscu o wspomniane w pierwszym punkcie grupy akcji. Akcje pod względem prędkości wykonywania i wpływu między sobą zostały podzielone na następujące grupy:
  • Speach: np. akcja Say
  • Javascript
  • Fix: wszelkie akcje związane z lokalizacją
  • Voice: akcja Get Voice
  • Proxy: akcje Display Brightness, Query Action, Photo, Photo Series, Photo Series Time
  • Proxy Scene: akcje Enter Key, Menu, Popup, Popup Task Buttons, Variable Query
  • Other Scenes: inne akcje wywołane przez scenę
  • Normal: wszystkie inne akcje
  • akcje Wait oraz Wait Until
Każdy uruchamiany task otrzymuje swój priorytet, który mówi o tym jak szybko będzie wykonany jeśli w kolejce czekają inne taski do wykonania. Im większa wartość priorytetu tym task będzie szybciej wykonany.
  • taski wejściowe profili ustawia się we właściwościach profilu w zakresie 1-10, domyślnie 5
  • taski wyjściowe profili mają priorytet ustawiony na wartość z właściwości profilu plus 11, domyślnie 16
  • taski skrótów i widżetów mają domyślnie ustawiony priorytet na 7, można go zmienić w ustawieniach Taskera
  • task uruchomiony przez klawisz Test na ekranie edycji tasku ma priorytet o wartości 10
  • task uruchomiony przez element sceny ma priorytet o jeden większy od priorytetu tasku, który wyświetlił scenę
Jeśli w kolejce czeka kilka tasków pochodzących od tego samego profilu (przykładowo task wejściowy i wyjściowy) to z domyślnymi ustawieniami mamy gwarancję, że task wyjściowy zacznie być wykonywany dopiero po całkowitym zakończeniu tasku wejściowego. Mimo, że task wyjściowy ma większy priorytet. Zachowanie to można zmienić o czym za chwilę.

Launched Task Priority

Ustawia wartość priorytetu tasku wejściowego profilu w zakresie 1-10. Domyślna wartość to 5. Od tej wartości zależy też wartość priorytetu tasku wyjściowego, który ustalany jest jako suma wartości ustawionej i 11. Domyślna wartość to 16.

Cooldown Time

Czas, po którym profil może stać się aktywny mierzony od momentu utraty aktywności przez ten profil. Restart systemu zeruje licznik czasu.
Ja używam tej funkcjonalności dla profilu, który uruchamia mi synchronizację danych z Dropboksem za pomocą aplikacji DropSync gdy telefon podłączony jest do ładowarki. Cooldown Time ustawiłem na 12 godzin i dzięki temu synchronizacja nie jest uruchamiana częściej niż 2 razy na dobę.

Limit Repeats

Ta opcja włącza limit powtórzeń aktywności profilu.

Remaining Repeats

W tym miejscu ustawia się limit ilości powtórzeń aktywności profilu.
Przykładowo jeśli ustawisz limit na 10, to za każdym razem gdy dany profil stanie się aktywny licznik ten zmniejszy się o 1, a gdy osiągnie 0, profil mimo spełnionych warunków kontekstów nie stanie się aktywny.

Delete On Zero Repeats

Zaznaczenie tej opcji spowoduje, że gdy limit ilości powtórzeń aktywności dojdzie do zera, Tasker usunie profil, którego tyczy się to ustawienie.

Restore Settings

Opcja ta decyduje czy przy dezaktywacji profilu będą przywracane wartości ustawień zmienionych za pomocą akcji typu ustawienie wykonanych w tasku wejściowym.

Enforce Task Order

Zaznaczenie tej opcji zapewnia zakończenie tasku wejściowego danego profilu przed rozpoczęciem tasku wyjściowego.
Przykładowo profil Test ma task wejściowy enter1, a w nim za pomocą akcji Perform Task uruchamiany jest task enter2, natomiast taskiem wyjściowym profilu jest exit1, w którym uruchamiany jest task exit2. Jeśli opcja Enforce Task Order jest zaznaczona to taski wyjściowe zaczną być wykonywane dopiero po zakończeniu tasków enter1 i enter2. Taski enter1 i enter2 będą wykonywane w zależności od nadanych im priorytetów.
Z wyłączoną opcją Enforce Task Order taski będą wykonywane w kolejności wynikającej z ich priorytetów, a skoro taski wyjściowe mają priorytety większe zostaną wykonane przed zakończeniem tasków wejściowych.

Show In Notification Pulldown

Opcja ta odpowiada za wyświetlanie nazwy profilu gdy jest on aktywny na powiadomieniu Taskera.

Właściwości tasków

Ekan właściwości tasku dostępny jest pod drugim klawiszem od prawej strony na dole ekranu edycji tasku i prezentuje się on tak:

Collision Handling

Czasami zdarzyć się może, że podczas wykonywania tasku jest on uruchamiany ponownie. Opcja ta decyduje jak Tasker ma postępować w takich sytuacjach. Możliwe są trzy warianty:

  • Abort New Task - Tasker zignoruje nową kopię tasku (to działanie jest domyślne)
  • Abort Existing Task - Tasker zatrzyma obecnie wykonywaną kopię tasku i zacznie wykonywanie nowej kopii
  • Run Both Together - Tasker będzie wykonywał obie kopie tasku równocześnie

Keep Device Awake

Domyślnie dla każdego tasku gwarantowany jest czas równy jednej minucie kiedy Tasker blokuje procesor urządzenia przed przejściem w stan uśpienia. W przypadku tasków, które mogą trwać dłużej zaznaczenie tej opcji zapewni utrzymanie aktywności procesora aż do pełnego wykonania tasku. Należy pamiętać, że w przypadku błędu w tasku, np. zapętlenia, może dojść do szybkiego rozładowania baterii jeśli ta opcja będzie zaznaczona.

Przełączanie Taskerem trybów transferu danych 2G/3G pod Androidem 5.0

Jako, że ostatnio przesiadłem się na Androida 5.0 musiałem stawić czoła dostosowaniu profilów Taskera do nowego systemu. Wcześniej używałem systemu bazującego na CM i AOSP więc możliwości współpracy z Taskerem były dużo większe.
Jedyną funkcją, której przez ostatnie dni nie udało mi się uzyskać było przełączanie trybów transferu danych 2G/3G. Jako, że dla Androida 5.0 nie ma jeszcze aplikacji Xposed i modów dla niej sprawa wydawała się przegrana.
Jednak przedwczoraj, niespodziewanie, trafiłem na aplikację Toggle Network Type 5.0. Okazało się, że świetnie ona sobie radzi z przełączeniem 2G/3G pod Lizakiem, ma ładny widżet, a w dodatku jest pluginem do Taskera. Po dwóch dniach testów stwierdzam, że działa bezbłędnie. Polecam.

Pobieranie

Aplikację można pobrać ze sklepu Google Play gdzie obecnie jest na nią promocja i kosztuje 4,15 zł lub z xda-developers gdzie rozdawana jest za darmo.

6 listopada 2014

Zaproszenia do Google Inbox

Jeśli ktoś szuka zaproszeń do Google Inbox to ja dysponuje trzema i chętnie się podzielę. Wystarczy poprzez Hangouts lub maila podesłać swój adres Gmail (proszę nie zostawiać adresów w komentarzach).

Aktualizacja

Obecnie mam 5 zaproszeń do rozdania. Ktoś chętny?

5 listopada 2014

Profil: Głosowe wysyłanie wiadomości SMS

Dziś przedstawię kolejny profil, w którym główne skrzypce odgrywa komunikacja głosowa z urządzeniem. Dokładnie chodzi o podyktowanie i wysłanie wiadomości SMS tylko za pomocą głosu.
Profil uruchamia się następującymi komendami głosowymi:

  • wyślij wiadomość do Jan Kowalski
  • wyślij sms do Jan Kowalski
  • wyślij smsa do Jan Kowalski
  • wiadomość do Jan Kowalski
  • sms do Jan Kowalski
przy założeniu, że wysłać ma wiadomość do kontaktu Jan Kowalski.
Po uruchomieniu profil sprawdza czy w kontaktach znajduje się kontakt o podanej nazwie oraz czy kontakt ten ma wpisany numer telefonu komórkowego następnie prosi użytkownika o podyktowanie treści wiadomości i jeśli użytkownik zatwierdzi jej poprawność wysyła ją do odbiorcy. W przypadku braku zatwierdzenia poprawności treści wiadomości profil proponuje ponowne jej podyktowanie.

Wymagania

  • wtyczka AutoVoice w wersji płatnej
  • wtyczka AutoContacts w wersji płatnej
  • generator głosu Text-To-Speech, przykładowo IVONA lub Google TTS
  • do poprawnego działania profilu niezbędny jest porządek w książce adresowej tzn. numery telefonów komórkowych muszą być opisane jako komórka

Opis wykonania

Profil uruchamiany jest za pomocą kontekstu AutoVoice Recognized z zaznaczoną opcją Event Behavior, Use Regex i filtrem komendy ustawionym na (?:wyślij )?(?:wiadomość|sms[a]?) do (?<contact>.*).

W tym miejscu spróbuję rozszyfrować ten zapis. Jest to wyrażenie regularne, które pozwala wywołać uruchomienie profilu kilkoma komendami głosowymi według powyższego schematu.
Wyrażenie (?:wyślij )? oznacza, że w komendzie może ale nie musi pojawić się słowo wyślij ze spacją po nim. Ostatni znak zapytania gwarantuje to, że słowo wyślij nie jest obligatoryjne. Dzięki temu profil można uruchomić komendą wyślij wiadomość do Jan Kowalski ale również wiadomość do Jan Kowalski.
Zestaw znaków (?: ) tworzy grupę, która w tym przypadku ma tylko jeden element czyli wyślij .
Następna część wyrażenia regularnego (?:wiadomość|sms[a]?) tworzy kolejną grupę, która ma dwa elementy oddzielone znakiem |. Zapis sms[a]? oznacza słowo sms oraz jeden znak a, który może ale nie musi wystąpić. Dzięki temu profil zostanie uruchomiony komendą wyślij sms do Jan Kowalski ale także wyślij smsa do Jan Kowalski.
W końcu wyrażenie (?<contact>.*) tworzy parametr, który zostanie przekazany do Taskera w postaci zmiennej %contact czyli w tym przypadku w tej zmiennej znajdzie się wartość Jan Kowalski.
Task zadania zaczyna się od akcji AutoContacts ze zmienną %contact wpisaną w pole Contact Name or Nickname. Dzięki temu wtyczka wyszukuje w kontaktach przykładowego Jana Kowalskiego i wypełnia zmienne danymi jego kontaktu.
Następnie sprawdzana jest zmienna %acnumber, która powinna otrzymać wartość pierwszego numeru telefonu kontaktu. Jeśli nie ma nadanej wartości oznacza task powiadamia głosowo użytkownika o nieznalezieniu kontaktu i zatrzymuje dalsze akcje.
Kolejnym krokiem jest ustalenie, który numer telefonu jest numerem komórkowym. Jeśli numer komórkowy nie zostanie odnaleziony generowana jest głosowa informacja o błędzie, a task zostaje zatrzymany.

Następnie task głosowo prosi o podyktowanie treści wiadomości i za pomocą akcji AutoVoice Recognize rejestruje co powiedział użytkownik. Kolejnym krokiem jest głosowe odczytanie podyktowanej treści i pytanie czy treść jest poprawna. Jeśli użytkownik potwierdzi poprawność, wiadomość jest wysyłana za pomocą akcji Send SMS, w której w polu Number należy podać zmienną %komórka, a w polu Message %sms. Jeśli użytkownik nie potwierdzi poprawności smsa, task proponuje ponowne podyktowanie wiadomości i wraca do prośby o podyktowanie jej treści.

Rozpisany profil

Profile: Wyślij SMS (193)

State: AutoVoice Recognized [ Configuration:Event Behaviour: true
Command: "(?:wyślij )?(?:wiadomość|sms[a]?) do (?<contact>.+) (regex)" ]
Enter: Anon (200)
A1: AutoContacts [ Configuration:Contact Name or Nickname: %contact Package:com.joaomgcd.autocontacts Name:AutoContacts Timeout (Seconds):1000 Continue Task After Error:On ]
A2: If [ %acnumber !Set ]
A3: Say [ Text:Nie znaleziono kontaktu %contact Engine:Voice:default:default Stream:3 Pitch:5 Speed:5 Respect Audio Focus:Off Network:Off Continue Task Immediately:Off ]
A4: Stop [ With Error:Off Task: ]
A5: End If
A6: Variable Split [ Name:%acallnumbers1 Splitter:, Delete Base:Off ]
A7: Variable Split [ Name:%acallnumbertypes1 Splitter:, Delete Base:Off ]
A8: Variable Set [ Name:%index To:%acallnumbertypes1(#?Komórka) Do Maths:Off Append:Off ]
A9: Variable Split [ Name:%index Splitter:, Delete Base:Off ] If [ %index !~ 0 ]
A10: Variable Set [ Name:%komórka To:%acallnumbers1(%index1) Do Maths:Off Append:Off ] If [ %index !~ 0 ]
A11: If [ %komórka !Set ]
A12: Say [ Text:Nie znaleziono numeru komórkowego kontaktu %acname Engine:Voice:default:default Stream:3 Pitch:5 Speed:5 Respect Audio Focus:Off Network:Off Continue Task Immediately:Off ]
A13: Stop [ With Error:Off Task: ]
A14: End If
<podyktuj>
A15: Say [ Text:Podyktuj wiadomość po sygnale. Engine:Voice:default:default Stream:3 Pitch:5 Speed:5 Respect Audio Focus:Off Network:Off Continue Task Immediately:Off ]
A16: Variable Clear [ Name:%avcomm Pattern Matching:Off ]
A17: AutoVoice Recognize [ Configuration:
Voice command without headset
Command: "all" Package:com.joaomgcd.autovoice Name:AutoVoice Recognize Timeout (Seconds):120 ]
A18: Goto [ Type:Action Label Number:1 Label:podyktuj ] If [ %avcomm !Set ]
A19: Variable Set [ Name:%sms To:%avcomm Do Maths:Off Append:Off ]
A20: Say [ Text:Czy chcesz wysłać wiadomość do %acname o treści: %sms? Engine:Voice:default:default Stream:3 Pitch:5 Speed:5 Respect Audio Focus:Off Network:Off Continue Task Immediately:Off ]
A21: AutoVoice Recognize [ Configuration:
Voice command without headset
Command: "all" Package:com.joaomgcd.autovoice Name:AutoVoice Recognize Timeout (Seconds):120 ]
A22: If [ %avcomm ~ tak ]
A23: Send SMS [ Number:%komórka Message:%sms Store In Messaging App:On ]
A24: Say [ Text:Wiadomość wysłana. Engine:Voice:default:default Stream:3 Pitch:5 Speed:5 Respect Audio Focus:Off Network:Off Continue Task Immediately:Off ]
A25: Else
A26: Say [ Text:Czy chcesz poprawić wiadomość? Engine:Voice:default:default Stream:3 Pitch:5 Speed:5 Respect Audio Focus:Off Network:Off Continue Task Immediately:Off ]
A27: AutoVoice Recognize [ Configuration:
Voice command without headset
Command: "all" Package:com.joaomgcd.autovoice Name:AutoVoice Recognize Timeout (Seconds):120 ]
A28: Goto [ Type:Action Label Number:9 Label:podyktuj ] If [ %avcomm ~ tak ]
A29: End If

Pobieranie profilu

Profil Głosowe wysyłanie wiadomości sms [Tasker 4.5u1]

18 października 2014

Tasker przypomni Ci o urodzinach, imieninach i rocznicach

Odkąd pamiętam mam problem z zapamiętywaniem dat. Z tego powodu zdarza mi się zapomnieć o urodzinach lub imieninach bliskich mi osób. Wpisanie dat do kalendarza częściowo rozwiązuje problem ale zawsze brakowało mi w telefonie przypominajki, którą trudno zignorować. W ten sposób powstał pomysł na projekt Taskera przypominający o urodzinach, imieninach i rocznicach osób z książki adresowej. Projekt codziennie rano i wieczorem wyszukuje w książce adresowej daty urodzin, imienin, rocznic ślubu i rocznic śmierci i jeśli takie występują dla danego dnia wyświetla powiadomienie umożliwiające wysłać wiadomość SMS, zadzwonić lub napisać wiadomość Hangouts do kontaktu. Prezentuje się to następująco.

Jest to trzecia wersja tego projektu. Poprzednie miały braki w funkcjonalności i nie umiały obejść niedoskonałości wtyczki AutoContacts. Ta wersja zdaje się być kompletna i nie zawierać błędów.
Jeśli coś z opisu lub samego projektu wyda Ci się niezrozumiałe to zachęcam do zadawania pytań. Postaram się na wszystkie odpowiedzieć.

Wymagania

Wtyczka AutoNotification

Wtyczka AutoNotification służy do generowania powiadomień. Oczywiście sam Tasker to potrafi za pomocą akcji Notify jednak wtyczka ma dużo większe możliwości konfiguracji tworzonego powiadomienia dlatego ja zdecydowanie wolę z niej korzystać. Poza generowaniem powiadomień wtyczka potrafi przechwytywać notyfikacje innych aplikacji co umożliwia np. zamykanie niechcianych powiadomień, przechwytywanie treści z powiadomień, uruchamianie profili w momencie pojawienia się notyfikacji z danego programu itp.

Instalacja i konfiguracja

Wtyczkę AutoNotification można pobrać ze sklepu Google Play. Po instalacji i wykupienia wersji Pro wtyczka jest gotowa do działania.

Konfiguracja

W dwóch pierwszych akcjach tasku AC Daty z kontaktów należy podać ścieżkę dostepu do plików graficznych oraz wybrany dxięk powiadomienia, który ma być odgrywany w momencie pojawienia się przypomnienia.

Opis wykonania

Projekt składa się z 6 profili. Dwa główne AN Przypomnienie o urodzinach [ranek] i AN Przypomnienie o urodzinach [wieczór] uruchamiają ten sam task AC Daty z kontaktów. Profil ranny uruchamiany jest o godzinie 10tej, wieczorny o 19tej pod warunkiem, że zmienna %BIRTHDAYR ma wartość 1. Zmienna ta ma wartość 1 jeśli użytkownik naciśnie poranne powiadomienie (nie odrzuci).

Task AC Daty z kontaktów zaczyna się od konfiguracji ścieżki dostępu do grafik oraz dźwięku powiadomienia, która użytkownik po imporcie projektu musi samemu dostosować do własnego systemu.
Następnie task sprawdza czy danego dnia są jakieś zdarzenia do obsłużenia (zmienna %daystoeventc) i jeśli tak odczytuje za pomocą akcji Run Shell i komend powłoki datę. Później w pętli pętla dane kontaktówporównując datę do listy dat jakie w zmiennej %acallevents otrzymuje od wtyczki AutoContacts task ustala ile dat należy obsłużyć danego dnia i dla tych dat odczytuje nazwiska, daty i typy dat i zapisuje je oddzielając przecinkami do zmiennych odpowiednio %nazwy_kontaktów, %daty_kontaktów i %typy_dat. Po tych operacjach wiadomo jest ile dat trzeba obsłużyć i otrzymuję zmienne macierzowe z wszystkimi niezbędnymi danymi.

Pętla powiadomienia odpowiedzialna jest za kolejno dla każdej daty ze zmiennej %daty_kontaktów wyciągnięcie z AutoContacts zdjęcia kontaktu i numerów telefonów i danych czatu Hangouts, przygotowanie tekstów dla powiadomienia i w końcu wyświetlenie powiadomienia. Przygotowanie tekstów i wyświetlanie powiadomień rozdzielone jest na cztery grupy, które kolejno obsługuję urodziny, imieniny, rocznice ślubów i rocznice śmierci. Oczywiście można stworzyć dodatkowe kategorie i obsłużyć je odpowiednimi powiadomieniami.

Do poprawnego działania projektu potrzebne są jeszcze profile odpowiedzialne za naciśnięcie powiadomienie przez użytkownika oraz obsługujące naciśnięcie klawiszy powiadomień.
Profil AN Przypomnij o urodzinach ma zadziałać w momencie naciśnięcie przez użytkownika powiadomienia. Dzięki kontekstowi AutoNotification oczekuje on na komendę o składni remind birthday=:=. Komendy takie są specyficzne dla wtyczek AutoNoticifation, AutoVoice, AutoRemote i innych tego samego autora. Zestaw znaków =:= rozdziela na części parametry komendy (może być ich więcej niż 2). W tym przypadku naciśniecie na notyfikacje wysyła komendę remind birthday=:=1, a parametr 1 komendy zostaje przekazany do zmiennej %ancomm dostępnej w tasku, dzięki temu możemy go przekazać do naszej zmiennej %BIRTHDAYR co zaowocuje ponownym przypomnieniem wieczorem (jeśli taka akcja miała miejsce rano).

Profil AN Wyślij wiadomość ma za zadanie przygotować wiadomość SMS do wysłania po naciśnięciu przycisku Wyślij wiadomość na powiadomieniu. W tym przypadku naciśnięcie przycisku przekazuje komendę composesms=:=%komórka gdzie %komórka zawiera numer telefonu komórkowego kontaktu.

Profil AN Zadzwoń ma za zadanie zadzwonić na numer kontaktu po naciśnięciu przycisku Zadzwoń na powiadomieniu. W tym przypadku naciśnięcie przycisku przekazuje komendę call=:=%komórka lub call=:=%dom (w zależności od dostępności numeru kontaktu).

Profil AN Hangouts ma za zadanie rozpocząć czat Hangouts z kontaktem po naciśnięciu przycisku Hangouts na powiadomieniu. W tym przypadku naciśnięcie przycisku przekazuje komendę browse=:=%achangouturi.

Rozpisany profil

Profile: AN Przypomnienie o urodzinach [wieczór] (45)
Time: 19:00
State: Variable Value [ %BIRTHDAYR = 1 ]
Enter: AC Daty z kontaktów (220)
<ścieżka do grafik>
A1: Variable Set [ Name:%scieżka_do_grafik To:/storage/emulated/0/Tasker/pictures Do Maths:Off Append:Off ]
<ścieżka do dźwięku>
A2: Variable Set [ Name:%scieżka_do_dźwięku To:content://media/internal/audio/media/246 Do Maths:Off Append:Off ]
A3: Variable Clear [ Name:%BIRTHDAYR Pattern Matching:Off ]
A4: AutoContacts [ Configuration:Order By: Next Event Date Package:com.joaomgcd.autocontacts Name:AutoContacts Timeout (Seconds):1000 ]
A5: Stop [ With Error:Off Task: ] If [ %acdaystoeventc != 0 ]
A6: Variable Set [ Name:%indeks To:1 Do Maths:Off Append:Off ]
A7: Run Shell [ Command:DATUM=$(date "+%m-%d")
echo $DATUM Timeout (Seconds):1 Use Root:Off Store Output In:%dzisiaj_md Store Errors In: Store Result In: ]
A8: Run Shell [ Command:DATUM=$(date "+%Y")
echo $DATUM Timeout (Seconds):1 Use Root:Off Store Output In:%dzisiaj_r Store Errors In: Store Result In: ]
<pętla dane kontaktów>
A9: If [ %acallevents(%indeks) ~ *%dzisiaj_md* ]
A10: If [ %acallevents(%indeks) ~ *,* ]
A11: Variable Set [ Name:%daty To:%acallevents(%indeks) Do Maths:Off Append:Off ]
A12: Variable Split [ Name:%daty Splitter:, Delete Base:Off ]
A13: Variable Set [ Name:%licznik To:%daty(#) Do Maths:Off Append:Off ]
<podwójna data>
A14: If [ %daty(%licznik) ~ *%dzisiaj_md* ]
A15: Variable Set [ Name:%nazwy_kontaktów To:%acnames(%indeks), Do Maths:Off Append:On ]
A16: Variable Set [ Name:%daty_kontaktów To:%daty(%licznik), Do Maths:Off Append:On ]
A17: Variable Set [ Name:%typy_dat_temp To:%acalleventtypes(%indeks) Do Maths:Off Append:Off ]
A18: Variable Split [ Name:%typy_dat_temp Splitter:, Delete Base:Off ]
A19: Variable Set [ Name:%typy_dat To:%typy_dat_temp(%licznik), Do Maths:Off Append:On ]
A20: Variable Add [ Name:%ile_dat Value:1 Wrap Around:0 ]
A21: Variable Subtract [ Name:%licznik Value:1 Wrap Around:0 ]
A22: Goto [ Type:Action Label Number:1 Label:podwójna data ] If [ %licznik > 0 ]
A23: Else
A24: Variable Subtract [ Name:%licznik Value:1 Wrap Around:0 ]
A25: Goto [ Type:Action Label Number:1 Label:podwójna data ] If [ %licznik > 0 ]
A26: End If
A27: Else
A28: Variable Set [ Name:%nazwy_kontaktów To:%acnames(%indeks), Do Maths:Off Append:On ]
A29: Variable Set [ Name:%daty_kontaktów To:%acallevents(%indeks), Do Maths:Off Append:On ]
A30: Variable Set [ Name:%typy_dat To:%acalleventtypes(%indeks), Do Maths:Off Append:On ]
A31: Variable Add [ Name:%ile_dat Value:1 Wrap Around:0 ]
A32: End If
A33: Variable Add [ Name:%indeks Value:1 Wrap Around:0 ]
A34: Goto [ Type:Action Label Number:1 Label:pętla dane kontaktów ]
A35: End If
A36: Variable Split [ Name:%daty_kontaktów Splitter:, Delete Base:Off ]
A37: Variable Split [ Name:%typy_dat Splitter:, Delete Base:Off ]
A38: Variable Split [ Name:%nazwy_kontaktów Splitter:, Delete Base:Off ]
<pętla powiadomienia>
A39: If [ %typy_dat(%ile_dat) ~ imieniny/urodziny/birthday/ślub/zgon ]
A40: Variable Clear [ Name:%dom Pattern Matching:Off ]
A41: Variable Clear [ Name:%komórka Pattern Matching:Off ]
A42: Variable Clear [ Name:%acpicturefile Pattern Matching:Off ]
A43: Variable Clear [ Name:%achangouturi Pattern Matching:Off ]
A44: AutoContacts [ Configuration:Contact Name or Nickname: %nazwy_kontaktów(%ile_dat) Package:com.joaomgcd.autocontacts Name:AutoContacts Timeout (Seconds):1000 ]
A45: AutoContacts Details [ Configuration:Contact Id: %acid
Get Picture: true
Full size: true Package:com.joaomgcd.autocontacts Name:AutoContacts Details Timeout (Seconds):1000 ]
A46: Variable Set [ Name:%telefony To:%acallnumbers(1) Do Maths:Off Append:Off ]
A47: Variable Set [ Name:%typy_telefonów To:%acallnumbertypes(1) Do Maths:Off Append:Off ]
A48: Variable Split [ Name:%telefony Splitter:, Delete Base:Off ]
A49: Variable Split [ Name:%typy_telefonów Splitter:, Delete Base:Off ]
<komórka>
A50: Variable Set [ Name:%licznik To:%typy_telefonów(#?Komórka) Do Maths:Off Append:Off ]
A51: Variable Split [ Name:%licznik Splitter:, Delete Base:Off ] If [ %licznik !~ 0 ]
A52: Variable Set [ Name:%komórka To:%telefony(%licznik1) Do Maths:Off Append:Off ] If [ %licznik !~ 0 ]
<dom>
A53: Variable Set [ Name:%licznik To:%typy_telefonów(#?Domowy) Do Maths:Off Append:Off ]
A54: Variable Split [ Name:%licznik Splitter:, Delete Base:Off ] If [ %licznik !~ 0 ]
A55: Variable Set [ Name:%dom To:%telefony(%licznik1) Do Maths:Off Append:Off ] If [ %licznik !~ 0 ]
<urodziny>
A56: If [ %typy_dat(%ile_dat) ~ urodziny/birthday ]
A57: Variable Set [ Name:%data To:%daty_kontaktów(%ile_dat) Do Maths:Off Append:Off ]
A58: Variable Split [ Name:%data Splitter:- Delete Base:Off ]
A59: Variable Set [ Name:%urodziny To:%dzisiaj_r-%data(1) Do Maths:On Append:Off ]
A60: Variable Set [ Name:%nottitle To:Urodziny %nazwy_kontaktów(%ile_dat) Do Maths:Off Append:Off ]
A61: Variable Set [ Name:%nottext To:%nazwy_kontaktów(%ile_dat) świętuje dziś %urodziny urodziny. Do Maths:Off Append:Off ]
A62: If [ %komórka Set & %achangouturi Set ]
A63: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/birthday.jpg
Text Expanded: %nottext
Button 1: call=:=%komórka
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: composesms=:=%komórka
Label 2: Wyślij wiadomość
Icon 2: ic_action_sms
Button 3: browse=:=%achangouturi
Label 3: Hangouts
Icon 3: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A64: Else If [ %dom Set & %achangouturi Set ]
A65: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/birthday.jpg
Text Expanded: %nottext
Button 1: call=:=%dom
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: browse=:=%achangouturi
Label 2: Hangouts
Icon 2: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A66: Else If [ %komórka Set ]
A67: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/birthday.jpg
Text Expanded: %nottext
Button 1: call=:=%komórka
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: composesms=:=%komórka
Label 2: Wyślij wiadomość
Icon 2: ic_action_sms
Icon 3: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A68: Else If [ %dom Set ]
A69: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/birthday.jpg
Text Expanded: %nottext
Button 1: call=:=%dom
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Icon 2: ic_action_phone_start Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A70: Else If [ %achangouturi Set ]
A71: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/birthday.jpg
Text Expanded: %nottext
Button 1: browse=:=%achangouturi
Label 1: Hangouts
Icon 1: ic_action_dialog
Icon 2: ic_action_phone_start Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A72: Else
A73: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/birthday.jpg
Text Expanded: %nottext Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A74: End If
A75: End If
<imieniny>
A76: If [ %typy_dat(%ile_dat) ~ imieniny ]
A77: Variable Set [ Name:%nottitle To:Imieniny %nazwy_kontaktów(%ile_dat) Do Maths:Off Append:Off ]
A78: Variable Set [ Name:%nottext To:Nie zapomnij złożyć życzeń. Do Maths:Off Append:Off ]
A79: If [ %komórka Set & %achangouturi Set ]
A80: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: imieniny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/imieniny.jpg
Text Expanded: %nottext
Button 1: call=:=%komórka
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: composesms=:=%komórka
Label 2: Wyślij wiadomość
Icon 2: ic_action_sms
Button 3: browse=:=%achangouturi
Label 3: Hangouts
Icon 3: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A81: Else If [ %dom Set & %achangouturi Set ]
A82: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: imieniny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/imieniny.jpg
Text Expanded: %nottext
Button 1: call=:=%dom
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: browse=:=%achangouturi
Label 2: Hangouts
Icon 2: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A83: Else If [ %komórka Set ]
A84: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: imieniny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/imieniny.jpg
Text Expanded: %nottext
Button 1: call=:=%komórka
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: composesms=:=%komórka
Label 2: Wyślij wiadomość
Icon 2: ic_action_sms
Icon 3: ic_launcher Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A85: Else If [ %dom Set ]
A86: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: imieniny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/imieniny.jpg
Text Expanded: %nottext
Button 1: call=:=%dom
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Icon 2: ic_action_phone_start Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A87: Else If [ %achangouturi Set ]
A88: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: imieniny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/imieniny.jpg
Text Expanded: %nottext
Button 1: browse=:=%achangouturi
Label 1: Hangouts
Icon 1: ic_action_dialog
Icon 2: ic_action_phone_start Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A89: Else
A90: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: imieniny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/imieniny.jpg
Text Expanded: %nottext Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A91: End If
A92: End If
<ślub>
A93: If [ %typy_dat(%ile_dat) ~ ślub ]
A94: Variable Set [ Name:%data To:%daty_kontaktów(%ile_dat) Do Maths:Off Append:Off ]
A95: Variable Split [ Name:%data Splitter:- Delete Base:Off ]
A96: Variable Set [ Name:%ślub To:%dzisiaj_r-%data(1) Do Maths:On Append:Off ]
A97: Variable Set [ Name:%nottitle To:Rocznica ślubu %nazwy_kontaktów(%ile_dat) Do Maths:Off Append:Off ]
A98: Variable Set [ Name:%nottext To:%nazwy_kontaktów(%ile_dat) świętuje dziś %ślub rocznicę ślubu. Do Maths:Off Append:Off ]
A99: If [ %komórka Set & %achangouturi Set ]
A100: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/wedding.jpg
Text Expanded: %nottext
Button 1: call=:=%komórka
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: composesms=:=%komórka
Label 2: Wyślij wiadomość
Icon 2: ic_action_sms
Button 3: browse=:=%achangouturi
Label 3: Hangouts
Icon 3: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A101: Else If [ %dom Set & %achangouturi Set ]
A102: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/wedding.jpg
Text Expanded: %nottext
Button 1: call=:=%dom
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: browse=:=%achangouturi
Label 2: Hangouts
Icon 2: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A103: Else If [ %komórka Set ]
A104: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/wedding.jpg
Text Expanded: %nottext
Button 1: call=:=%komórka
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Button 2: composesms=:=%komórka
Label 2: Wyślij wiadomość
Icon 2: ic_action_sms
Icon 3: ic_action_dialog Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A105: Else If [ %dom Set ]
A106: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/wedding.jpg
Text Expanded: %nottext
Button 1: call=:=%dom
Label 1: Zadzwoń
Icon 1: ic_action_phone_start
Icon 2: ic_action_phone_start Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A107: Else If [ %achangouturi Set ]
A108: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/wedding.jpg
Text Expanded: %nottext
Button 1: browse=:=%achangouturi
Label 1: Hangouts
Icon 1: ic_action_dialog
Icon 2: ic_action_phone_start Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A109: Else
A110: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_balloon
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik/wedding.jpg
Text Expanded: %nottext Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A111: End If
A112: End If
<zgon>
A113: If [ %typy_dat(%ile_dat) ~ zgon ]
A114: Variable Set [ Name:%data To:%daty_kontaktów(%ile_dat) Do Maths:Off Append:Off ]
A115: Variable Split [ Name:%data Splitter:- Delete Base:Off ]
A116: Variable Set [ Name:%zgon To:%dzisiaj_r-%data(1) Do Maths:On Append:Off ]
A117: Variable Set [ Name:%nottitle To:Rocznica śmierci %nazwy_kontaktów(%ile_dat) Do Maths:Off Append:Off ]
A118: Variable Set [ Name:%nottext To:Dziś jest %zgon rocznica śmierci %nazwy_kontaktów(%ile_dat). Do Maths:Off Append:Off ]
A119: AutoNotification [ Configuration:Title: %nottitle
Text: %nottext
Ticker: %nottitle
Action on Touch: cancel=:=birthday
Action on Dismiss: remind birthday=:=1
Icon: %acpicturefile
Status Bar Icon: ic_action_basket
Id: urodziny_%acid
Dismiss on Touch: true
Priority: 1
Sound: %scieżka_do_dźwięku
Picture: %scieżka_do_grafik

/rip.jpg
Text Expanded: %nottext Package:com.joaomgcd.autonotification Name:AutoNotification Timeout (Seconds):0 ]
A120: End If
A121: Variable Subtract [ Name:%ile_dat Value:1 Wrap Around:0 ]
A122: Goto [ Type:Action Label Number:1 Label:pętla powiadomienia ] If [ %ile_dat > 0 ]
A123: End If

Profile: AN Przypomnij o urodzinach (42)
State: AutoNotification [ Configuration:Event Behaviour
Filter: remind birthday=:= ]
Enter: Anon (43)
A1: AutoNotification Cancel [ Configuration:Id: %anpar2 Package:com.joaomgcd.autonotification Name:AutoNotification Cancel Timeout (Seconds):0 ]
A2: Variable Set [ Name:%BIRTHDAYR To:%ancomm Do Maths:Off Append:Off ]

Profile: AN Wyślij wiadomość (27)
State: AutoNotification [ Configuration:Event Behaviour
Filter: composesms=:= ]
Enter: Anon (39)
A1: Status Bar [ Set:Collapsed ]
A2: Compose SMS [ Recipient(s):%ancomm Message: ]
A3: AutoNotification Cancel [ Configuration:Id: %anpar2 Package:com.joaomgcd.autonotification Name:AutoNotification Cancel Timeout (Seconds):0 ]

Profile: AN Zadzwoń (40)
State: AutoNotification [ Configuration:Event Behaviour
Filter: call=:= ]
Enter: Anon (41)
A1: Status Bar [ Set:Collapsed ]
A2: Call [ Number:%ancomm Auto Dial:On ]
A3: AutoNotification Cancel [ Configuration:Id: %anpar2 Package:com.joaomgcd.autonotification Name:AutoNotification Cancel Timeout (Seconds):0 ]

Profile: AN Hangouts (192)
State: AutoNotification [ Configuration:Event Behaviour
Filter: browse=:= ]
Enter: Anon (201)
A1: Status Bar [ Set:Collapsed ]
A2: Browse URL [ URL:%ancomm ]
A3: AutoNotification Cancel [ Configuration:Id: %anpar2 Package:com.joaomgcd.autonotification Name:AutoNotification Cancel Timeout (Seconds):0 ]

Pobieranie profilu

Projekt Urodziny [Tasker 4.5u1]
Pliki JPG należy umieścić w folderze /sdcard/Tasker/pictures/.