====== Kivy: Android Service ====== **{{tagpage>kivy|Toutes les pages Kivy}}** **[[http://translate.google.com/translate?hl=&sl=auto&tl=en&u=https%3A%2F%2Fressources.labomedia.org%2Fkivy_android_service|English Version]]** **[[les_pages_kivy_en_details|Les pages Kivy en détails]]** =====Pourquoi utiliser un service android ?===== Les applications Android se mettent en pause, lors du verrouillage de l'écran, ou de la réduction de la fenêtre de l'application.\\ Pour avoir un script qui tourne en arrière plan, il faut utiliser un service. ===== Ressources ===== * https://python-for-android.readthedocs.io/en/latest/services/ * https://developer.android.com/guide/topics/manifest/service-element Extrait: python-for-android supports the use of Android Services, background tasks running in separate processes. These are the closest Android equivalent to multiprocessing on e.g. desktop platforms, and it is not possible to use normal multiprocessing on Android. Services are also the only way to run code when your app is not currently opened by the user. Services must be declared when building your APK. Each one will have its own main.py file with the Python script to be run. Please note that python-for-android explicitly runs services as separated processes by having a colon “:” in the beginning of the name assigned to the android:process attribute of the AndroidManifest.xml file. This is not the default behavior, see Android service documentation. **You can communicate with the service process from your app using e.g. osc** or (a heavier option) twisted. ====Exemple d'un développeur kivy==== * **https://github.com/tshirtman/kivy_service_osc** Comme l'exemple utilise **osc**, je vais faire une infidélité à twisted. Je veux un truc qui marche vite, tant pis pour l'élégance.\\ Cet exemple utilise un Tread pour tester le code sur les autres platformes que Android. Sauf que ce Thread est stoppé avec un Tread.stop(), méthode qui n'existe pas: l'application plante! Il faudait communiquer avec le service en envoyant un message osc "stop" qui finirait la boucle while.\\ **La seule façon de terminer un thread est de basculer à 0 un self.loop de:** while self.loop: pass =====Kivy Accelerometer Service OSC===== ====Sources sur GitHub==== * **[[https://github.com/sergeLabo/accelerometer_service_osc|accelerometer_service_osc]]** ===*.apk=== Dans le dossier bin ===TODO=== Si il n'y a pas d'accelerometer sur Android, ça va sans doute mal marcher. ====Extrait du code pour le service==== La communication entre main.py et service.py se fait en OSC, c'est très rapide, il n'y a aucune latence. Il n'est pas possible de lancer service.py avec des arguments, ni d'accéder aux attributs de AccelerometerService() depuis main.py, d'où l'OSC. Pour l'OSC, voir [[kivy_oscpy|Kivy: oscpy]] === buildozer.spec === [[https://github.com/sergeLabo/accelerometer_service_osc/blob/main/buildozer.spec|buildozer.spec]] [app] title = Accelerometer package.name = accelerometer package.domain = org.kivy source.dir = . source.include_exts = py,png,jpg,kv,atlas requirements = python3,kivy,plyer,numpy,oscpy,jnius android.permissions = INTERNET, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE services = Pong:service.py ===main.py=== [[https://github.com/sergeLabo/accelerometer_service_osc/blob/main/main.py|main.py]] from jnius import autoclass """ Dans buildozer.spec package.name = accelerometer package.domain = org.kivy services = Pong:service.py SERVICE_NAME = u'{packagename}.Service{servicename}'.format( packagename=u'org.kivy.accelerometer', servicename=u'ServicePong') Structure = package.domain.package.name.ServiceToto package.domain = org.kivy package.name = accelerometer soit org.kivy.accelerometer.ServicePong """ SERVICE_NAME = 'org.kivy.accelerometer.ServicePong' print("SERVICE_NAME:", SERVICE_NAME) ..... class AccelerometerApp(App): ... def start_service(self): if ANDROID: self.service = autoclass(SERVICE_NAME) self.m_activity = autoclass(u'org.kivy.android.PythonActivity').mActivity argument = '' self.service.start(self.m_activity, argument) ... def do_quit(self): if ANDROID: self.service.stop(self.m_activity) self.service = None else: self.client.send_message(b'/stop', [1]) sleep(1) AccelerometerApp.get_running_app().stop() ===service.py=== [[https://github.com/sergeLabo/accelerometer_service_osc/blob/main/service.py|service.py]] class AccelerometerService: def __init__(self): ... self.init_osc() self.sensor_init() ... def init_osc(self): """Le serveur peut envoyer mais impossible d'avoir 2 serveurs sur le même port de la même machine, donc il faut un client. """ self.server = OSCThreadServer() self.server.listen('localhost', port=3001, default=True) # Les callbacks du serveur self.server.bind(b'/activity', self.on_activity) self.server.bind(b'/stop', self.on_stop) self.server.bind(b'/sensor_enable', self.on_sensor_enable) # Un simple client self.client = OSCClient(b'localhost', 3003) ... def run(self): while self.loop: self.get_acceleration() sleep(0.02) if __name__ == '__main__': ACCELEROMETER = AccelerometerService() ACCELEROMETER.run() =====Un projet plus complet===== * **[[https://github.com/sergeLabo/roulez_bourrez|Roulez Bourrez]]** {{tag> kivy python sb }}