Создание службы android Python для запуска в состоянии приостановки

Здесь мой Python script написан с использованием 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 замораживает script (и, следовательно, цикл while)? Обратите внимание, что я действительно запускаю этот script как услугу (долго нажмите и нажмите "Начать как сервис" ).

Есть ли способ сделать этот script работать все время независимо от состояния приостановки телефона?

Обновление 1: я иногда слышу вибрацию, а не каждую минуту.. но скорее как каждые 5-10 минут в случайном порядке.

Обновление 2. Эти проблемы возникают, если я обычно запускаю script (а не как сервис). Кажется, что "time.sleep" не спит в течение указанного времени.

Ответ 1

Сценарий, безусловно, является гражданином второго сорта. То, что вы хотите, называется AlarmManager, используя ELAPSED_REALTIME. Если это не доступно для среды сценариев, вы застряли.

Среда сценариев, по крайней мере, в настоящее время не предназначена для полной замены среды разработки, где вы можете создавать полные приложения. Это означало, что вы можете выполнять некоторые простые задачи сценариев, ценой неспособности выполнять более сложные вещи. К сожалению.

Ответ 2

Я столкнулся с такой же проблемой.

time.sleep() не является надежным, когда ваше устройство Android находится в режиме "заблокирован":

Вот несколько вещей, которые я пробовал на SL4A release4 + pythonForAndroid_r5 + android 2.3.3 на галактике Samsung S

  • заверните цикл time.sleep(интервал) внутри droid.wakeLockAcquirePartial() и droid.wakeLockRelease(). Это предотвратит замедление CPU.
  • используйте событие 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)

Ответ 3

Маловероятно, что это будет работать в ASE без поддержки AlertManager. Лучше всего подать заявку на функцию и подождать. Или, если вы чувствуете амбициозность, продлите ASE самостоятельно и отправьте патч!

Ответ 4

Я не очень разбираюсь в связывании с Python, поэтому я собираюсь ответить как общая проблема с Android. См. Управление питанием.

PARTIAL_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();

Ответ 5

Возможное решение: используйте некоторое программное обеспечение планировщика и регулярно запускайте свой script. Таким образом вам не нужно будет вызывать time.sleep().

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