You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hey gentlemen, I am developing a cross-platform controller of an IOT device which it's GUI is done using kivy. It works fine on python 3.0+ on linux and windows. I just finished the android build on a fresh Ubuntu 18.04 vmware virtual machine with a windows host using kivy android packaging guide. Well the problem started from a kivy filechooser which seems like it cant access /storage/emulated/0 or any other symlinks to it(e.g. /mnt/sdcard). The android device which I'm testing my app on is a Samsung Galaxy Note 5 running Android 7.0 with no sdcard. The other problem that I have which im not sure about it yet, is that seems like my app cannot access network but I need to look more for that. The problem is that I have set INTERNET, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE in my buildozer.spec file as the permissions but yet nothing changed. So as a summary my app seems to have these problems:
Cannot access device storage. (Internal)
Cannot access internet.
Though Both permissions are acquired in buildozer.spec.
Thanks in advance.
edit This is my main.py:
"""PTController GUI for Android"""importtimeimportthreadingfromkivy.appimportAppfromkivy.uix.widgetimportWidgetfromkivy.uix.dropdownimportDropDownfromkivy.uix.buttonimportButtonfromkivy.uix.popupimportPopupfromkivy.uix.labelimportLabelfromkivy.uix.relativelayoutimportRelativeLayoutfromkivy.configimportConfigfromkivy.propertiesimportObjectPropertyfromkivy.clockimportClockfromCore.API.CoreimportPTNodefromCore.interfaceimportget, set, scan_network, logConfig.set('graphics', 'resizable', True)
classFileChooser(Popup):
"""To choose log file in PTAddition processs. """# Result is stored here.result=""# Defines wether if popup is submitted or not.submitted=Falsedefselect(self, *args):
try:
self.result=args[1][0]
self.submitted=Trueexcept: passclassPTAddition(Popup):
"""A dialogbox that gets an PT's infortmation to add it in the PT selection dropdown. """error_msg=ObjectProperty(None)
ip_TI=ObjectProperty(None) # IP text inputlogpath_TI=ObjectProperty(None) # Logpath text input# Result dictionary is for getting user inputs out of popup.result= {
"IP": "",
"LogPath": ""
}
# This boolean specifies if user did succesfully Fill out the form# or not.submitted=False# This boolean specifies if the popup is dismissed or not.dismissed=Falsedefchoose_file(self, popup):
"""Finalises file choosing process. """ifnotpopup.submitted:
returnself.logpath_TI.text=popup.resultdefBrowseFile(self):
"""Opens FileChooser popup """filepopup=FileChooser()
filepopup.bind(on_dismiss=self.choose_file)
filepopup.open()
defsubmit(self):
"""Get values from inputs and submit them into result dictionary """self.error_msg.text=""ip_input=self.ip_TI.text.replace("\n", "") \
.replace("\r", "") \
.replace(" ", "")
ifip_input:
self.result["IP"] =ip_inputelse:
self.error_msg.text="Error: Please specify all inputs.(IP)"returnlogpath_input=self.logpath_TI.text.replace("\n", "") \
.replace("\r", "") \
.replace(" ", "")
iflogpath_input:
self.result["LogPath"] =logpath_inputelse:
self.error_msg.text="Error: Please specify all inputs.(Log Path)"returnself.submitted=Trueself.dismiss()
classPTController(RelativeLayout):
"""Root widget. """# This variable contains the PTNode object to work with.working_pt=Nonecurrent_temp=ObjectProperty(None)
pt_selection=DropDown()
# The button to attach dropdown to.pt_selection_btn=ObjectProperty(None)
# This dictionary contains all PTs that were scanned/manually connected.pts= {}
# This defines wether user has selected to log data or not.log_state=Falsedef__init__(self):
super().__init__()
# Setup dropdown main button and two default buttons for PT selection.self.pt_selection_btn.bind(on_release=self.pt_selection.open)
self.pt_selection.add_widget(
Button(text="Scan Network", size_hint_y=None, height=80,on_press=self.scan, font_size=22)
)
self.pt_selection.add_widget(
Button(text="Add PT", size_hint_y=None, height=80,on_press=self.add_pt, font_size=22)
)
def_change_pt(self, name):
"""This function changes PT in the dropdownlist """# First change the text of main buttonself.pt_selection_btn.text=name# Now apply the valuestry:
self.working_pt=self.pts[name]
exceptKeyError:
return# Suppress# Refresh dataself.get(schedule=False)
def_create_pt(self, popup):
"""This function gets the popup invoked in add_pt method and validates it's data to finally create a PT. It's usually binded to on_dismiss method of the popup """ifnotpopup.submitted:
# User canceled the processreturn# Create PT.result=popup.resultpt=PTNode(result["IP"], result["LogPath"])
self.working_pt=ptself.pts[pt.name] =pt# Now add the pt into the dropdown listself.pt_selection.add_widget(
Button(text=pt.name,
size_hint_y=None,
height=44,
on_release=lambdabtn: self._change_pt(btn.text))
)
defadd_pt(self, button):
"""Opens a dialog that prompts user to manually add a new PT. """popup=PTAddition()
popup.open()
popup.bind(on_dismiss=self._create_pt)
deflog_toggle(self, checkbox, value):
"""Handles log checkbox check event. """self.log_state=valuedefscan(self, button):
"""Scan for PTs in the network. """ScanResult=scan_network()
print(ScanResult)
ifnotlen(ScanResult):
Popup(title="Error",
content=Label(text="Did not find any PT in network!", font_size=20),
size_hint=[0.4, 0.2]
).open()
returnforPTinScanResult:
self.pts[PT.name] =PTself.pt_selection.add_widget(
Button(text=PT.name,
height=44,
size_hint_y=None,
on_release=lambdabtn: self._change_pt(btn.text)
)
)
def_find_pt_ip(self, ip):
"""Finds a PT in the pts dictionary with the given ip. Returns false if nothing found, the key of the pt if found. """key=""foriteminself.pts.items():
ifitem[1].ip==ip:
key=item[0]
breakreturnkeydefset(self):
"""Set data on the PT. Gathers values from all inputs and sends them to PT. """ifself.working_pt==None:
Popup(title="Error",
content=Label(text="Please select a PT first!", font_size=20),
size_hint=[0.4, 0.2]
).open()
return# Get values from inputscalibration=self.ids.calibration.textsetpoint=self.ids.setpoint.textname=self.ids.pt_name.textifset(self.working_pt, setpoint, calibration, name):
# Do a get so data would be freshself.get(schedule=False)
self.working_pt.name=nameelse:
Popup(title="Error",
content=Label(text="Could not communicate with PT!", font_size=20),
size_hint=[0.4, 0.2]
).open()
return# Change the name in dropdownself.pt_selection_btn.text=self.working_pt.nameold_name=self._find_pt_ip(self.working_pt.ip)
forwidgetinself.pt_selection.walk():
iftype(widget) ==Button:
ifwidget.text==old_name:
widget.text=self.working_pt.namedefget(self, delta=0, schedule=True):
"""Get data from the PT. Gathers values from PT and updates them in the output. If schedule is set to False the method will not schedule itself to be invoked in 10 seconds """ifself.working_pt==None:
Popup(title="Error",
content=Label(text="Please select a PT first!", font_size=20),
size_hint=[0.4, 0.2]
).open()
returnjson_response=get(self.working_pt, True, True, True, True, True)
ifnotjson_response:
# Logging should be consistentifscheduleandself.log_state:
Clock.schedule_once(self.get, 10)
returnPopup(title="Error",
content=Label(text="Could not communicate with PT!", font_size=20),
size_hint=[0.4, 0.2]
).open()
returnself.current_temp.text=json_response["current_temp"]
ifint(json_response["alarm"]):
self.current_temp.color= [1,0,0,1]
else:
self.current_temp.color= [1,1,1,1]
self.ids.setpoint.text=json_response["setpoint"]
self.ids.calibration.text=json_response["calibration"]
self.ids.pt_name.text=json_response["pt_name"]
# Log if saidifself.log_state:
log(self.working_pt, json_response)
# Schedule this function to run each 10 secondsifschedule:
Clock.schedule_once(self.get, 10)
# Setters and Gettersdefset_temp(self, value):
self.current_temp.text=str(value)
defget_temp(self):
returnself.current_temp.textdefset_name(self, value):
self.root.ids.pt_name.text=valuedefget_name(self):
returnself.root.ids.pt_name.textdefset_setpoint(self, value):
self.root.ids.setpoint.text=str(value)
defget_setpoint(self):
returnself.root.ids.setpoint.textdefset_calibration(self, value):
self.root.ids.calibration.text=str(value)
defget_calibration(self):
returnself.root.ids.calibration.textclassRaymondPTControllerApp(App):
defbuild(self):
controller=PTController()
# controller.set_temp(89.0)returncontrollerdefmain():
RaymondPTControllerApp().run()
if__name__=="__main__":
main()
Feels more like a support request than a bug right? Maybe try to ask on Discord.
I do have both storage and internet working on my apps. It's not clear to me what's your error is.
Also, people are willing to help, but are just too busy with other things, so making their lives easier would max your chances of getting helped. Which means minimal reproducing example and straightforward description. For example you should narrow your issue down as much as possible to reduce all possible noise. Side effect of that is you may be finding/fixing the issue yourself.
See you on Discord support channels 👍
Versions
Description
Hey gentlemen, I am developing a cross-platform controller of an IOT device which it's GUI is done using kivy. It works fine on python 3.0+ on linux and windows. I just finished the android build on a fresh Ubuntu 18.04 vmware virtual machine with a windows host using kivy android packaging guide. Well the problem started from a kivy filechooser which seems like it cant access /storage/emulated/0 or any other symlinks to it(e.g. /mnt/sdcard). The android device which I'm testing my app on is a Samsung Galaxy Note 5 running Android 7.0 with no sdcard. The other problem that I have which im not sure about it yet, is that seems like my app cannot access network but I need to look more for that. The problem is that I have set
INTERNET
,READ_EXTERNAL_STORAGE
,WRITE_EXTERNAL_STORAGE
in my buildozer.spec file as the permissions but yet nothing changed. So as a summary my app seems to have these problems:Though Both permissions are acquired in buildozer.spec.
Thanks in advance.
edit This is my main.py:
buildozer.spec
Command:
Spec file:
Logs
log.txt
The text was updated successfully, but these errors were encountered: