I'm writing a GPS aircraft navigation app in Kivy. It runs well on all the devices I have tested it on including various phones and the Samsung Galaxy Tab 4 10.1" but fails on the Samsung Galaxy Tab 4 8". Assuming a faulty device I sent it back and got another one. Same problem.
Using Tito's GPSdemo app and trapping the exception,
at the self.gps.start() line it throws:
File "jnius_utils.pxi", line 43, in jnius.jnius.check_exception
(jnius/jnius.c3316) JavaException: JVM exception occured.
The 8" tab is a good size device for my app so I'd like to use it. Other GPS apps work fine on it including GPS Arrow Pro and Sky Demon for example.
Any ideas how I can fix this?
The code is:
from kivy.lang import Builder
from plyer import gps
from kivy.app import App
from kivy.properties import StringProperty
from kivy.clock import Clock
kv = '''
BoxLayout:
orientation: 'vertical'
Label:
text: app.gps_location
Label:
text: app.gps_status
BoxLayout:
size_hint_y: None
height: '48dp'
padding: '4dp'
ToggleButton:
text: 'Start' if self.state == 'normal' else 'Stop'
on_state: app.gps.start() if self.state == 'down' else app.gps.stop()
'''
class GpsTest(App):
gps_location = StringProperty()
gps_status = StringProperty('')
def build(self):
self.gps = gps
try:
self.gps.configure(on_location=self.on_location, on_status=self.on_status)
self.gps.start() #exception occurs here
except:
import traceback;
import sys;
formatted_lines = traceback.format_exc().splitlines()
self.gps_status = formatted_lines[-2]+'\n'+formatted_lines[-1]
print self.gps_status
return Builder.load_string(kv)
def on_location(self, **kwargs):
self.gps_location = '\n'.join(['{}={}'.format(k, v) for k, v in kwargs.items()])
def on_status(self, stype, status):
self.gps_status = 'type={}\n{}'.format(stype, status)
if __name__ == '__main__':
GpsTest().run()
Related
i'm working on a qr code scanner using kivy zbarcam, I managed to make it work but the problem is the camera initializes right away and does not release the camera after leaving the screen. I tried zbarcam.stop() and root.ids.zbarcam_id.ids.xcamera.play=False but what it does is just unscheduling and doesn't really release the use of camera. I tried to build this in buildozer but it's so slow since the camera is using a lot of memory even when not in use.
Can somebody know what is the workaround on this?
This is my code:
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen
from kivy.clock import Clock
from kivymd.app import MDApp
class QRScreen(Screen):
pass
class LoginScreen(Screen):
pass
class ScannerScreen(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self._after_init)
# self.ids.zbarcam_id.ids.xcamera.play=True
def _after_init(self, dt):
"""
Binds `ZBarCam.on_symbols()` event.
"""
zbarcam = self.ids.zbarcam_id
zbarcam.bind(symbols=self.on_symbols)
def on_symbols(self, zbarcam, symbols):
"""
Loads the first symbol data to the `QRFoundScreen.data_property`.
"""
# going from symbols found to no symbols found state would also
# trigger `on_symbols`
if not symbols:
return
symbol = symbols[0]
data = symbol.data.decode('utf8')
print(data)
self.manager.get_screen('qr').ids.data.text= data
self.manager.transition.direction = 'left'
self.manager.current = 'qr'
def on_leave(self):
zbarcam = self.ids.zbarcam_id
zbarcam.stop()
class DemoApp(MDApp):
def build(self):
# screen =Screen()
self.title='Demeter'
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "DeepPurple"
self.help = Builder.load_file('main.kv')
return self.help
DemoApp().run()
kv file:
#:import ZBarCam kivy_garden.zbarcam.ZBarCam
ScreenManager:
LoginScreen:
ScannerScreen:
QRScreen:
<LoginScreen>:
name: "login"
MDFlatButton:
text:'release'
on_press:
root.manager.current = 'scanner'
root.manager.transition.direction = "right"
<ScannerScreen>:
name: 'scanner'
ZBarCam:
id: zbarcam_id
play: False
MDFlatButton:
id: iyu
text:'release'
on_press:
root.ids.zbarcam_id.ids.xcamera.play=False
MDFlatButton:
id: ads
text:'replay'
pos_hint: {"center_x": 0.5, "center_y": 0.95}
on_press:
root.ids.zbarcam_id.ids.xcamera.play=True
<QRScreen>:
name: 'qr'
MDIconButton:
icon:'arrow-left'
pos_hint: {'center_x':0.1,'center_y':0.95}
on_press:
root.manager.current = 'scanner'
root.manager.transition.direction = "right"
MDLabel:
id:data
text: "asdgasda"
pos_hint: {'center_y':0.5}
theme_text_color: "Custom"
text_color: 0, 1, 0, 1
I was having the same problem and finally found the solution (based on this)
In my case I initate ZBarCam in the .py file instead of .kv (see example).
To actually close the camera, you can call the following:zbarcam.ids['xcamera']._camera._device.release() in your on_leave() function.
If you initiate/manage ZBarCam in the .kv, I think that the equivalent would be something like: root.ids.zbarcam.ids.xcamera._camera._device.release()
If compiled with buildzoner for Android, I have to use self.zbarcam.ids['xcamera']._camera = None instead
I have the same error, I already install garden, kivy-garden, kivy, kivymd, pyzbar, and all the requriments in the buildozer.spec file, but when I run it, the log said ModuleNotFoundError: No module named 'kivy_garden.zbarcam', I have being trying a lot of solutions in other requriments, but any of that works.
the code from this site is not working for me: https://kivy.org/doc/stable/examples/gen__camera__main__py.html
It works perfectly on my pc. However, when I push it to my android phone with
buildozer -v android debug deploy run
The camera opens up normally and when I press 'Capture', it acts as if it takes a picture. However, when I look into the phone's gallery, I can't find any new picture. Is the picture saved somewhere that's not in the gallery? My app has a few more steps to upload that pic to google firebase. And it can never find the recently taken pic in the root directory. Again, it's working perfectly on PC. My buildozer spec is:
Permissionsandroid.permissions = INTERNET,CAMERA,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE
I tried WRITE_INTERNAL_STORAGE and it didn't like it. So I guess writing to internal storage permission is given by default.
Another minor issue: the screen on the app is flipped sideways. It's showing the correct live pic but it's a bit weird. I tried switching between 'vertical' and 'horizontal' in the Builder.load_string but nothing changes.
Please assist. I appreciate any input.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
import time
Builder.load_string('''
<CameraClick>:
orientation: 'vertical'
Camera:
id: camera
resolution: (640, 480)
play: False
ToggleButton:
text: 'Play'
on_press: camera.play = not camera.play
size_hint_y: None
height: '48dp'
Button:
text: 'Capture'
size_hint_y: None
height: '48dp'
on_press: root.capture()
''')
class CameraClick(BoxLayout):
def capture(self):
'''
Function to capture the images and give them the names
according to their captured time and date.
'''
camera = self.ids['camera']
timestr = time.strftime("%Y%m%d_%H%M%S")
camera.export_to_png("IMG_{}.png".format(timestr))
print("Captured")
class TestCamera(App):
def build(self):
return CameraClick()
TestCamera().run()````
I have figured it out. Somehow the root directory doesn't work. To make it work, simply change
camera.export_to_png("IMG_{}.png".format(timestr))
to
camera.export_to_png("/sdcard/IMG_{}.png".format(timestr))
Every android app I build on kivy with buildozer restarts itself after being in the background. Even if I slide down the notifications when on the app the app restarts.
I tried finding documentation about this issue but didn't find anything.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
import time
Builder.load_string('''
<CameraClick>:
orientation: 'vertical'
Camera:
id: camera
resolution: (640, 480)
play: False
ToggleButton:
text: 'Play'
on_press: camera.play = not camera.play
size_hint_y: None
height: '48dp'
Button:
text: 'Capture'
size_hint_y: None
height: '48dp'
on_press: root.capture()
''')
class CameraClick(BoxLayout):
def capture(self):
'''
Function to capture the images and give them the names
according to their captured time and date.
'''
camera = self.ids['camera']
timestr = time.strftime("%Y%m%d_%H%M%S")
camera.export_to_png("IMG_{}.png".format(timestr))
print("Captured")
class TestCamera(App):
def build(self):
return CameraClick()
TestCamera().run()
This is the app I'm trying to run, with a default buildozer.spec only adding opencv for the camera.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
import time
Builder.load_string('''
<CameraClick>:
orientation: 'vertical'
Camera:
id: camera
resolution: (640, 480)
play: False
ToggleButton:
text: 'Play'
on_press: camera.play = not camera.play
size_hint_y: None
height: '48dp'
Button:
text: 'Capture'
size_hint_y: None
height: '48dp'
on_press: root.capture()
''')
class CameraClick(BoxLayout):
def capture(self):
'''
Function to capture the images and give them the names
according to their captured time and date.
'''
camera = self.ids['camera']
timestr = time.strftime("%Y%m%d_%H%M%S")
camera.export_to_png("IMG_{}.png".format(timestr))
print("Captured")
class TestCamera(App):
def build(self):
return CameraClick()
def on_pause(self):
return True
TestCamera().run()
Changing the on_pause method solves it.
Simply put, I would like to use a small USB keypad/numpad to type into a text input field on a kivy app running on android via the kivy launcher.
I am using an OTG USB connector to connect a small keypad to my tablet. The connector works in general on the tablet (I can type in numbers in the browser and other apps). In a kivy app however, when I use the touchscreen to select a text input field, it focuses awaiting input, then if I try to type in with the numpad, nothing happens. After doing some testing with a normal sized USB keyboard, it works (but the numpad on it doesn't).
Here is the basic kivy app I used to test this out with:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
KV = """
<MyScreenManager>:
KeyboardInput:
name: 'KeyInput'
<KeyboardInput>:
GridLayout:
rows: 3
TextInput:
id: input1
text:''
multiline: False
Widget:
TextInput:
id: input2
text:''
multiline: False
"""
class KeyboardInput(Screen):
pass
class MyScreenManager(ScreenManager):
def changescreen(self, value):
try:
if value!='Go To...':
self.current = value
except:
print('No screen named ' + value)
#Main application
class packagingDiscardmentApp(App):
def build(self):
Builder.load_string(KV)
self.sm = MyScreenManager()
return self.sm
if __name__ == '__main__':
packagingDiscardmentApp().run()
My guess is that there is some issue with the ascii characters on the numpad and Kivy. Any help would be greatly appreciated.
I wrote an small kivy program, because I wanted to learn how to save values using .json files.
I checked out the documetation and found this:http://kivy.org/docs/api-kivy.storage.html#module-kivy.storage
I tried to to it similar,but I got the error:ImportError: No module named storage.jsonstore
Why doesn't it work?
Here is my code:
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.storage.jsonstore import JsonStore
from kivy.properties import StringProperty
from kivy.properties import NumericProperty
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
class Layout(BoxLayout):
def save(self, vinput):
store = JsonStore('hello.json')
store.put('tito', inpud=vinput)
ROOT = Builder.load_string('''
BoxLayout:
orientation: 'vertical'
TextInput:
id:my_textinput
Button:
text: 'save'
Button:
text: 'acsess'
''')
class Caption(App):
def build(self):
Window.clearcolor = (0, 0, 1, 1)
return ROOT
if __name__ == '__main__':
Caption().run()
I have never used JsonStore before, I will have a look at it, then will update the answer, but for now, you could do it this way.
import json
#If you want to write in your JSON file.
out_file = open("your_file.json","w")
json.dump(result,out_file, indent=4)
# result ^ contains your data.
# indent = 4 is to make your file more readable.
out_file.close()
#If you want to read your JSON file.
in_file = open("your_file.json","r")
result = json.load(in_file)
in_file.close()
EDIT: 1
It actually works perfectly fine.
Try this improved code.
Your .py file
from kivy.app import App
from kivy.storage.jsonstore import JsonStore
from kivy.uix.boxlayout import BoxLayout
class Lay_out(BoxLayout):
def save(self, vinput):
store = JsonStore('hello.json')
store.put('tito', inpud=vinput)
class CaptionApp(App):
def build(self):
return Lay_out()
if __name__ == '__main__':
CaptionApp().run()
Your .kv file
<Lay_out>:
orientation: 'vertical'
TextInput:
id:my_textinput
Button:
text: 'save'
on_release: root.save(my_textinput.text)
Button:
text: 'acsess'