Создание Android-службы Python для запуска в состоянии ожидания
Вот мой Python-скрипт, написанный с использованием android-scripting:
import android, time
droid = android.Android()
interval = 1 # every 1 minute
while True:
# define your own vibrate pattern here
droid.vibrate(200)
time.sleep(0.3)
droid.vibrate(300)
time.sleep(60*interval)
Он в основном вибрирует каждую минуту (как мотиватор). Однако, когда телефон заблокирован с отключенным экраном, я не чувствую никакой вибрации. Возможно, Android замораживает скрипт (и, следовательно, цикл while)? Обратите внимание, что я действительно запускаю этот сценарий как службу (нажмите и удерживайте кнопку "Запуск от имени службы").
Есть ли способ заставить этот скрипт работать постоянно, независимо от состояния приостановки телефона?
Обновление 1: Я слышу вибрации время от времени, не каждую минуту... а, скорее, каждые 5-10 минут в случайном порядке.
Обновление 2: эта проблема возникает, если я запускаю скрипт нормально (не как сервис). Похоже, "time.sleep" не спит в течение указанного времени.
5 ответов
Среда сценариев определенно является второсортным гражданином. То, что вы хотите, называется AlarmManager, используя ELAPSED_REALTIME. Если это не доступно для скриптовой среды, вы застряли.
Среда сценариев, по крайней мере в настоящее время, не предназначена для полной замены среды комплекта разработки, где вы можете создавать полные приложения. Он предназначен для того, чтобы позволить вам выполнять некоторые простые задачи сценариев за счет невозможности делать более сложные вещи. Сожалею.
Я сталкиваюсь с такой же проблемой.
time.sleep () не является надежным, когда ваше устройство Android находится в "заблокированном" режиме:
Вот несколько вещей, которые я пробовал на SL4A release4 + pythonForAndroid_r5 + android 2.3.3 на samsung galaxy S
- оберните цикл time.sleep (interval) внутри droid.wakeLockAcquirePartial() и droid.wakeLockRelease(). Это предотвратит замедление процессора.
- используйте вызов eventWaitFor(eventName, timeOutInMilliSeconds):
droid.eventWaitFor ("ThisEventCannotHappen", интервал *60000)
- После нескольких тестов на моем устройстве объект threading.Timer() также работает должным образом (требуется подтверждение...)
Я не уверен, но вы должны иметь в виду, что эти уловки могут потреблять больше энергии, чем ожидалось в истинном "заблокированном / спящем" режиме, и, следовательно, сократить время работы вашего устройства.
Обновление: eventWaitFor () также не является надежным для длительных интервалов. Вот фрагмент, показывающий, как работает Timer ():
import android
import threading
import logging
def doStuff():
logging.info("testTimer.py: Stuff DONE")
droid.notify('testTimer.py',"doStuff() has been called")
droid.vibrate(500)
def createLog(path):
logging.basicConfig(filename=path,
level=logging.INFO,
format='%(asctime)s %(message)s')
DELAY=600
droid=android.Android()
logpath="/mnt/sdcard/testTimer.py.log"
createLog(logpath)
timer=threading.Timer(DELAY,doStuff)
logging.info("timer starting now")
timer.start()
logging.info("doStuff() will be called by timer...Delay=%d" % DELAY)
Вряд ли это будет работать в ASE без поддержки AlertManager. Лучше всего подать запрос на функцию и дождаться этого. Или, если вы чувствуете себя амбициозным, расширьте ASE и отправьте патч!
Я не очень разбираюсь в связывании с Python, поэтому собираюсь ответить на него как на проблему с Android. См. Управление питанием.
PARTIAL_WAKE_LOCK
звучит интересно: "Wake Lock, который гарантирует, что процессор работает. Экран может быть не включен".
Изучение примера Wake Lock
Все вызовы управления питанием имеют одинаковый базовый формат:
- Получить дескриптор службы PowerManager.
- Создайте пробуждение от блокировки и укажите флаги управления питанием для экрана, времени ожидания и т. Д.
- Получить замок от пробуждения.
- Выполнить операцию (воспроизвести MP3, открыть страницу HTML и т. Д.).
- Отпустите кнопку пробуждения. Фрагмент ниже иллюстрирует этот процесс.
PowerManager pm = (PowerManager)mContext.getSystemService(
Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.SCREEN_DIM_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE,
TAG);
wl.acquire();
// ...
wl.release();
Возможное решение: использовать программное обеспечение планировщика и регулярно запускать сценарий. Таким образом, вам не нужно вызывать time.sleep().
Возможно, сценарии не лучшее решение для таких периодических задач. Вы не столкнетесь с этой проблемой, если напишите простое Java-приложение.