Пишем список дел на Python 3 для Android через QPython3 и SL4A

Пишем список дел на Python 3 для Android через QPython3 и SL4A

Движок QPython (и QPython 3) для Android – вещь по-прежнему плохо изученная, и особенно что касается его встроенной библиотеки Scripting Layer For Android (SL4A), она же androidhelper. Эту библиотеку написали несколько сотрудников Google по принципу 20% свободного времени, снабдили ее спартанской документацией, которую почти невозможно найти, и отправили в свободное плавание. Я искал информацию об SL4A по крупицам, но со временем нашел практически все, что мне нужно.

SL4A позволяет задействовать практически все возможности консольного Python 3 вплоть до библиотек типа matplotlib, при этом используются стандартные диалоги Android: ввод текста, списки, вопросы, радиокнопки, выбор даты и т.д. Программа не будет поражать красотой, но многие задачи решать сможет. Самое главное, что мы получим доступ к различным функциям устройства. Например, можно:

  • делать телефонные звонки
  • посылать SMS
  • менять громкость
  • включать Wi-Fi и Bluetooth
  • открывать веб-страницы
  • открывать сторонние приложения
  • делать фото- и видеосъемку камерой
  • извлекать контакты из контактной книги
  • посылать системные оповещения
  • определять GPS-координаты устройства
  • определять заряд батареи
  • считывать данные SIM-карты
  • воспроизводить медиафайлы
  • работать с буфером обмена
  • генерировать голосовые сообщения
  • экспортировать данные на внешние активности (share)
  • открывать локальные html-страницы
  • и др.

В нашем примере мы напишем простейший список задач. Мы сможем создавать и удалять задачи, а также экспортировать их. Программа будет вибрировать и разговаривать. Мы будем пользоваться тремя видами диалогов: список, текстовый ввод и вопрос «да/нет». На все про все нам хватит менее 100 строк кода. Интерфейс сделаем английским ради универсальности (и GitHub).

Вот весь код и комментарии к наиболее существенным моментам.

Создаем объект droid класса Android(), который будет отвечать за взаимодействие с SL4A.

Переменная path будет содержать абсолютное имя файла, в котором хранятся задачи. Почему так длинно? Дело в том, что SL4A не может работать с локальным путем, поэтому приходится определять абсолютный, а абсолютный может отличаться на разных Android-устройствах. Мы обойдем эту проблему путем определения местоположения папки Download с помощью метода droid.environment() . Затем мы отсекаем Download и добавляем путь Qpython/Scripts3 (он всегда одинаков) плюс имя файла.

Определяем функцию, отвечающую за вывод списка задач. Это делается с помощью метода droid.dialogCreateAlert() . Затем ряд вспомогательных методов выводят собственно пункты, создают кнопки и получают результат от пользователя. Названиями двух кнопок служат Unicode-символы (об этом чуть ниже). Для упрощения мы упакуем все эти методы в одну простую функцию, которой будем передавать список задач. В более сложных скриптах можно передавать больше аргументов: заголовок, названия кнопок и т.д.

Определяем функцию, отвечающую за создание новой задачи. Принцип аналогичен. В аргументе default мы передаем ей текст, который по умолчанию появляется в строке ввода (пустой при ""). В более сложных программах можно передавать различные подписи и кнопки.

Эта функция будет задавать вопрос пользователю, чтобы получить ответ да или нет. Мы передаем ей текст вопроса.

Создаем цикл (чтобы скрипт не вышел после первого же действия) и первым делом читаем файл задач и загружаем его в список tasks . Если файла нет, создаем пустой список.

Выводим список задач. Когда пользователь делает какой-то выбор, метод dialog_list() возвращает это действие в виде значения, которое мы присваиваем переменной response .

Начинаем обрабатывать действие пользователя. Поскольку метод droid.dialogGetResponse() , который мы используем в функции списка, выдает довольно сложную структуру в виде словаря, его придется препарировать не самым очевидным способом. В данном случае по простому клику на пункт списка он удаляется – мы выполнили дело. Сообщим об этом во всплывающем сообщении и одновременно сделаем (чисто забавы ради) виброзвонок на 200 миллисекунд и сгенерируем голосовую фразу Дело сделано! .

По нажатию на среднюю (нейтральную) кнопку с ножницами можно разом удалить все дела. При этом будет выведен подтверждающий вопрос.

Здесь мы создаем новую задачу. Обратим внимание на переменную cancel – ее выдает droid.dialogGetResponse() в случае клика вне диалога (на пустую область экрана). Чтобы корректно обработать такую ситуацию, мы ввели дополнительное условие. По средней кнопке ( neutral ) поле ввода будет очищаться. При positive мы создаем новый пункт списка и выходим из цикла. Если нажать на самую правую кнопку, сработает else и мы просто выйдем из цикла, ничего не сохранив (хотя формально это будет значение negative в input["which"] ). Последняя строка означает, что пользователь нажал на Exit . Тогда мы устанавливаем флаг exit в True .

После каждой обработки списка сохраняем список задач в файл.

Если пользователь решил выйти, мы выходим из главного цикла while .

В самом конце мы спрашиваем у пользователя, надо ли экспортировать все задачи куда-нибудь – на почту, в облако, в мессенджер и т.д. При положительном ответе список задач преобразуется в строку и экспортируется.

На этом всё. Программа будет выглядеть, как на скриншоте выше.

Полный листинг

Окончательный полный листинг (с комментариями на английском):

Пара замечаний. SL4A не позволяет использовать никакую графику, однако можно использовать довольно большое количество всевозможных смайлов и эмодзи как Unicode-символы. Это могут быть хоть домики, хоть собачки, хоть кошечки. В нашем примере мы использовали знак плюс ( \u2795 ), ножницы ( \u2702 ) и листок бумаги ( \ud83d\udcc3 ). C каждой новой версией Unicode их становится все больше, но этим не стоит злоупотреблять – новые смайлы не будут отображаться на более старых версиях Android.

Для запуска скриптов QPython нужно заходить в собственно QPython, но существует интересный плагин для приложения Tasker, позволяющий проделывать довольно мощные вещи с QPython-скриптами, например выводя их на рабочий стол в виде иконок или запуская по различным условиям.

📎📎📎📎📎📎📎📎📎📎