简体   繁体   English

如何使任何应用程序在 kivy python 的后台运行

[英]How to make any app run in background in kivy python

I am building a small simple app using kivy python and it involves some calculations which displays some notification when some condition is satisfied, consider it an app which hit an API every 30 seconds and displays the notification, it works until this point but when I close the app, the notification doesn't appear in my android device.我正在使用 kivy python 构建一个简单的小型应用程序,它涉及一些计算,当满足某些条件时会显示一些通知,将其视为一个应用程序,该应用程序命中 API,但每隔 30 秒显示通知并显示此通知,直到我关闭该应用程序,通知不会出现在我的 android 设备中。 So basically I want to run it in background too so that I keep receiving the notifications .所以基本上我也想在后台运行它,以便我不断收到通知 I have tried the following but it is not working:-我尝试了以下方法,但它不起作用:-

This is main.py这是 main.py

** Edit: I was able to solve it by changing the package-name and package-domain mentioned in my buildozer.spec file, but now it requires ssl so I imported and added the mentioned 2 ssl statements in the code but Now I get the following error: ** 编辑:我可以通过更改我的 buildozer.spec 文件中提到的包名和包域来解决它,但现在它需要 ssl 所以我在代码中导入并添加了提到的 2 个 ssl 语句,但现在我得到了以下错误:

ERROR: Could not find a version that satisfies the requirement ssl (from versions: 1.15, 1.16)
ERROR: No matching distribution found for ssl
Exception information:
Traceback (most recent call last):
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 341, in resolve
    name, crit = self._merge_into_criterion(r, parent=None)
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 173, in _merge_into_criterion
    raise RequirementsConflicted(criterion)
pip._vendor.resolvelib.resolvers.RequirementsConflicted: Requirements conflict: SpecifierRequirement('ssl')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 127, in resolve
    result = self._result = resolver.resolve(
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 473, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_vendor/resolvelib/resolvers.py", line 343, in resolve
    raise ResolutionImpossible(e.criterion.information)
pip._vendor.resolvelib.resolvers.ResolutionImpossible: [RequirementInformation(requirement=SpecifierRequirement('ssl'), parent=None)]

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_internal/cli/base_command.py", line 180, in _main
    status = self.run(options, args)
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_internal/cli/req_command.py", line 204, in wrapper
    return func(self, options, args)
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_internal/commands/install.py", line 318, in run
    requirement_set = resolver.resolve(
  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/venv/lib/python3.8/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 136, in resolve
    raise error from e
pip._internal.exceptions.DistributionNotFound: No matching distribution found for ssl
Removed ssl from https://files.pythonhosted.org/packages/3a/c2/846a19d1572ec6cb8ac438d58a898de8926d32e13f0355cdf4ab00864b5f/ssl-1.15.tar.gz#sha256=1266302ce62c4b60c7ca0e1d3d104ba11d2749e5881d8ac4f006cf9a0446d589 (from -r requirements.txt (line 1)) from build tracker '/tmp/pip-req-tracker-y6xm5k7e'
Removed ssl from https://files.pythonhosted.org/packages/83/21/f469c9923235f8c36d5fd5334ed11e2681abad7e0032c5aba964dcaf9bbb/ssl-1.16.tar.gz#sha256=ac21156fee6aee9eb8d765bbb16f5f49492d81ff4b22f7b8fc001d2251120930 (from -r requirements.txt (line 1)) from build tracker '/tmp/pip-req-tracker-y6xm5k7e'
Removed build tracker: '/tmp/pip-req-tracker-y6xm5k7e'

from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.screen import Screen
from kivymd.uix.button import MDFlatButton, MDRectangleFlatButton
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.core.window import Window
from kivy.lang.builder import Builder
from kivy.clock import Clock
from kivy.uix.screenmanager import Screen, ScreenManager
from plyer import notification
from jnius import autoclass

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

###################### background service ########################
SERVICE_NAME = u'{packagename}.Service{servicename}'.format(
    packagename=u'org.test.myapp',
    servicename=u'Myservice'
)

service = autoclass(SERVICE_NAME)
mActivity = autoclass(u'org.kivy.android.PythonActivity').mActivity
argument = ''
service.start(mActivity, argument)
###################################################################

screen_helper = """
Screen:
 My screen - just ignore this. Assume it anything.
"""

class MyApp(MDApp):
    
    def show_notification(self, message):
        notification.notify(title='test', message=message)

    def runMyStrat(self):
        Clock.schedule_interval(self.strategy, 5)

    def stopMyStrat(self):
        Clock.unschedule(self.strategy)

    def navigation_draw(self):
        print("Drawer open or closed !")

    def display_help(self):
        print("Asked for Help !")

    def strategy(self, obj):
        ''' 
        get some data from an API and displays a notification every 5 seconds if some statement becomes true.
        This function works and send notification when app is running, but when I close it or switch between apps, it doesn't, is something wrong with my service.py script, I'm new to kivy
        '''

    def build(self):
        screen = Builder.load_string(screen_helper)
        return screen

if __name__ == '__main__':
    MyApp().run()

This is service.py这是服务.py

'p4a example service using oscpy to communicate with main application.'
from random import sample, randint
from string import ascii_letters
from time import localtime, asctime, sleep

from oscpy.server import OSCThreadServer
from oscpy.client import OSCClient

CLIENT = OSCClient('localhost', 3002)

def ping(*_):
    'answer to ping messages'
    CLIENT.send_message(
        b'/message',
        [
            ''.join(sample(ascii_letters, randint(10, 20)))
            .encode('utf8'),
        ],
    )


def send_date():
    'send date to the application'
    CLIENT.send_message(
        b'/date',
        [asctime(localtime()).encode('utf8'), ],
    )


if __name__ == '__main__':
    SERVER = OSCThreadServer()
    SERVER.listen('localhost', port=3000, default=True)
    SERVER.bind(b'/ping', ping)
    while True:
        sleep(1)
        send_date()

Builder.spec file: Builder.spec 文件:

[app]

# (str) Title of your application
title = AlgoGuru

# (str) Package name
package.name = myapp

# (str) Package domain (needed for android/ios packaging)
package.domain = org.test

# (str) Source code where the main.py live
source.dir = .

# (list) Source files to include (let empty to include all the files)
source.include_exts = py,png,jpg,kv,atlas

# (list) List of inclusions using pattern matching
#source.include_patterns = assets/*,images/*.png

# (list) Source files to exclude (let empty to not exclude anything)
#source.exclude_exts = spec

# (list) List of directory to exclude (let empty to not exclude anything)
#source.exclude_dirs = tests, bin

# (list) List of exclusions using pattern matching
#source.exclude_patterns = license,images/*/*.jpg

# (str) Application versioning (method 1)
version = 0.1

# (str) Application versioning (method 2)
# version.regex = __version__ = ['"](.*)['"]
# version.filename = %(source.dir)s/main.py

# (list) Application requirements
# comma separated e.g. requirements = sqlite3,kivy
requirements = python3,kivy,kivymd,plyer,nsetools,dateutil,jnius,ssl,pyjnius

# (str) Custom source folders for requirements
# Sets custom source for any requirements with recipes
# requirements.source.kivy = ../../kivy

# (list) Garden requirements
#garden_requirements =

# (str) Presplash of the application
#presplash.filename = %(source.dir)s/data/presplash.png

# (str) Icon of the application
#icon.filename = %(source.dir)s/data/icon.png

# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
orientation = portrait

# (list) List of service to declare
#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
services = Myservice:service.py
#
# OSX Specific
#

#
# author = © Copyright Info

# change the major version of python used by the app
osx.python_version = 3

# Kivy version to use
osx.kivy_version = 1.9.1

#
# Android specific
#

# (bool) Indicate if the application should be fullscreen or not
fullscreen = 0

# (string) Presplash background color (for new android toolchain)
# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
# red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
# darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
# olive, purple, silver, teal.
#android.presplash_color = #FFFFFF

# (list) Permissions
android.permissions = INTERNET

# (int) Target Android API, should be as high as possible.
#android.api = 27

# (int) Minimum API your APK will support.
#android.minapi = 21

# (int) Android SDK version to use
#android.sdk = 20

# (str) Android NDK version to use
#android.ndk = 19b

# (int) Android NDK API to use. This is the minimum API your app will support, it should usually match android.minapi.
#android.ndk_api = 21

# (bool) Use --private data storage (True) or --dir public storage (False)
#android.private_storage = True

# (str) Android NDK directory (if empty, it will be automatically downloaded.)
#android.ndk_path =

# (str) Android SDK directory (if empty, it will be automatically downloaded.)
#android.sdk_path =

# (str) ANT directory (if empty, it will be automatically downloaded.)
#android.ant_path =

# (bool) If True, then skip trying to update the Android sdk
# This can be useful to avoid excess Internet downloads or save time
# when an update is due and you just want to test/build your package
# android.skip_update = False

# (bool) If True, then automatically accept SDK license
# agreements. This is intended for automation only. If set to False,
# the default, you will be shown the license when first running
# buildozer.
# android.accept_sdk_license = False

# (str) Android entry point, default is ok for Kivy-based app
#android.entrypoint = org.renpy.android.PythonActivity

# (str) Android app theme, default is ok for Kivy-based app
# android.apptheme = "@android:style/Theme.NoTitleBar"

# (list) Pattern to whitelist for the whole project
#android.whitelist =

# (str) Path to a custom whitelist file
#android.whitelist_src =

# (str) Path to a custom blacklist file
#android.blacklist_src =

# (list) List of Java .jar files to add to the libs so that pyjnius can access
# their classes. Don't add jars that you do not need, since extra jars can slow
# down the build process. Allows wildcards matching, for example:
# OUYA-ODK/libs/*.jar
#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar

# (list) List of Java files to add to the android project (can be java or a
# directory containing the files)
#android.add_src =

# (list) Android AAR archives to add (currently works only with sdl2_gradle
# bootstrap)
#android.add_aars =

# (list) Gradle dependencies to add (currently works only with sdl2_gradle
# bootstrap)
#android.gradle_dependencies =

# (list) add java compile options
# this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option
# see https://developer.android.com/studio/write/java8-support for further information
# android.add_compile_options = "sourceCompatibility = 1.8", "targetCompatibility = 1.8"

# (list) Gradle repositories to add {can be necessary for some android.gradle_dependencies}
# please enclose in double quotes 
# e.g. android.gradle_repositories = "maven { url 'https://kotlin.bintray.com/ktor' }"
#android.add_gradle_repositories =

# (list) packaging options to add 
# see https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html
# can be necessary to solve conflicts in gradle_dependencies
# please enclose in double quotes 
# e.g. android.add_packaging_options = "exclude 'META-INF/common.kotlin_module'", "exclude 'META-INF/*.kotlin_module'"
#android.add_gradle_repositories =

# (list) Java classes to add as activities to the manifest.
#android.add_activities = com.example.ExampleActivity

# (str) OUYA Console category. Should be one of GAME or APP
# If you leave this blank, OUYA support will not be enabled
#android.ouya.category = GAME

# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png

# (str) XML file to include as an intent filters in <activity> tag
#android.manifest.intent_filters =

# (str) launchMode to set for the main activity
#android.manifest.launch_mode = standard

# (list) Android additional libraries to copy into libs/armeabi
#android.add_libs_armeabi = libs/android/*.so
#android.add_libs_armeabi_v7a = libs/android-v7/*.so
#android.add_libs_arm64_v8a = libs/android-v8/*.so
#android.add_libs_x86 = libs/android-x86/*.so
#android.add_libs_mips = libs/android-mips/*.so

# (bool) Indicate whether the screen should stay on
# Don't forget to add the WAKE_LOCK permission if you set this to True
#android.wakelock = False

# (list) Android application meta-data to set (key=value format)
#android.meta_data =

# (list) Android library project to add (will be added in the
# project.properties automatically.)
#android.library_references =

# (list) Android shared libraries which will be added to AndroidManifest.xml using <uses-library> tag
#android.uses_library =

# (str) Android logcat filters to use
android.logcat_filters = *:S python:D

# (bool) Copy library instead of making a libpymodules.so
#android.copy_libs = 1

# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
android.arch = armeabi-v7a

# (int) overrides automatic versionCode computation (used in build.gradle)
# this is not the same as app version and should only be edited if you know what you're doing
# android.numeric_version = 1

#
# Python for android (p4a) specific
#

# (str) python-for-android fork to use, defaults to upstream (kivy)
#p4a.fork = kivy

# (str) python-for-android branch to use, defaults to master
#p4a.branch = master

# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
#p4a.source_dir =

# (str) The directory in which python-for-android should look for your own build recipes (if any)
#p4a.local_recipes =

# (str) Filename to the hook for p4a
#p4a.hook =

# (str) Bootstrap to use for android builds
# p4a.bootstrap = sdl2

# (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
#p4a.port =


#
# iOS specific
#

# (str) Path to a custom kivy-ios folder
#ios.kivy_ios_dir = ../kivy-ios
# Alternately, specify the URL and branch of a git checkout:
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
ios.kivy_ios_branch = master

# Another platform dependency: ios-deploy
# Uncomment to use a custom checkout
#ios.ios_deploy_dir = ../ios_deploy
# Or specify URL and branch
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
ios.ios_deploy_branch = 1.7.0

# (str) Name of the certificate to use for signing the debug version
# Get a list of available identities: buildozer ios list_identities
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"

# (str) Name of the certificate to use for signing the release version
#ios.codesign.release = %(ios.codesign.debug)s


[buildozer]

# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
log_level = 2

# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
warn_on_root = 1

# (str) Path to build artifact storage, absolute or relative to spec file
# build_dir = ./.buildozer

# (str) Path to build output (i.e. .apk, .ipa) storage
# bin_dir = ./bin

#    -----------------------------------------------------------------------------
#    List as sections
#
#    You can define all the "list" as [section:key].
#    Each line will be considered as a option to the list.
#    Let's take [app] / source.exclude_patterns.
#    Instead of doing:
#
#[app]
#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
#
#    This can be translated into:
#
#[app:source.exclude_patterns]
#license
#data/audio/*.wav
#data/images/original/*
#


#    -----------------------------------------------------------------------------
#    Profiles
#
#    You can extend section / key with a profile
#    For example, you want to deploy a demo version of your application without
#    HD content. You could first change the title to add "(demo)" in the name
#    and extend the excluded directories to remove the HD content.
#
#[app@demo]
#title = My Application (demo)
#
#[app:source.exclude_patterns@demo]
#images/hd/*
#
#    Then, invoke the command line with the "demo" profile:
#
#buildozer --profile demo android debug

As I said, my app keeps crashing after adding this logic to my app, the following is the error when I use logcat-color:正如我所说,我的应用程序在将此逻辑添加到我的应用程序后不断崩溃,以下是我使用 logcat-color 时的错误:

 python  I  Traceback (most recent call last):
05-08 18:38:45.284   5207     5233                 python  I  File "/content/.buildozer/android/app/main.py", line 25, in <module>
05-08 18:38:45.284   5207     5233                 python  I  File "/content/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/
                                                            myapp/jnius/reflect.py", line 208, in autoclass
05-08 18:38:45.285   5207     5233                 python  I  File "jnius/jnius_export_func.pxi", line 28, in jnius.jnius.find_javaclass
05-08 18:38:45.285   5207     5233                 python  I  jnius.jnius.JavaException: Class not found b'org/kivy/myapp/ServiceMyservice'
05-08 18:38:45.285   5207     5233                 python  I  Python for android ended.

My app was running before but now I want an additional feature which is to run it in background too.我的应用程序之前正在运行,但现在我想要一个附加功能,即在后台运行它。 If someone could help, I would really appreciate it!如果有人可以提供帮助,我将不胜感激!

Thanks in advance!提前致谢!

I think it comes from the fact you didn't update the package name in the service declaration in main.py, should be我认为这是因为您没有在 main.py 的服务声明中更新 package 名称,应该是

SERVICE_NAME = u'{packagename}.Service{servicename}'.format(
    packagename=u'org.test.myapp',
    servicename=u'Myservice'
)

because you declared the app domain to be org.test in buildozer.spec.因为您在 buildozer.spec 中将应用程序域声明为org.test

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM