Thrasherop
Thrasherop

Reputation: 81

Kivy app keeps crashing with logcat: "ReferenceError: weakly-referenced object no longer exists"

I am trying to make a GPS app via Kivy in Python3. The app works fine, but then randomly crashes and gives the following logcat error:

refreshed screen
I/python  (10601): inside onLocation
I/python  (10601): trying to print kwargs inside onLocation():
I/python  (10601): {'lat': 40.55075864, 'lon': -111.83829566, 'speed': 0.30016663670539856, 'bearing': 56.900001525878906, 'altitude': 1447.0, 'accuracy': 3.0}
I/python  (10601): trying to assign lat from kwargs...
I/python  (10601): trying to assign lng from kwargs...
I/python  (10601): inside onLocation(): got lat:  40.55075864
I/python  (10601): Inside onlocation(): trying to update gpsCycle...
I/python  (10601): Inside class.onLocation(): trying to refresh Screen...
I/python  (10601): Refreshing Screen
I/python  (10601): refreshed screen
I/python  (10601): [INFO   ] [Base        ] Leaving application in progress...
I/python  (10601):  Traceback (most recent call last):
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/app/main.py", line 217, in <module>
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/gpsApp/kivy/app.py", line 855, in run
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/gpsApp/kivy/base.py", line 504, in runTouchApp
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/gpsApp/kivy/core/window/window_sdl2.py", line 747, in mainloop
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/gpsApp/kivy/core/window/window_sdl2.py", line 479, in _mainloop
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/gpsApp/kivy/base.py", line 339, in idle
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/gpsApp/kivy/clock.py", line 591, in tick
I/python  (10601):    File "kivy/_clock.pyx", line 384, in kivy._clock.CyClockBase._process_events
I/python  (10601):    File "kivy/_clock.pyx", line 414, in kivy._clock.CyClockBase._process_events
I/python  (10601):    File "kivy/_clock.pyx", line 412, in kivy._clock.CyClockBase._process_events
I/python  (10601):    File "kivy/_clock.pyx", line 154, in kivy._clock.ClockEvent.tick
I/python  (10601):    File "kivy/_clock.pyx", line 86, in kivy._clock.ClockEvent.get_callback
I/python  (10601):    File "/home/joshua/GPSapp/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/gpsApp/kivy/weakmethod.py", line 56, in is_dead
I/python  (10601):  ReferenceError: weakly-referenced object no longer exists
I/python  (10601): Python for android ended.

Here is my full code:

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.image import Image, AsyncImage
from kivy.utils import platform
from kivy.graphics import Rectangle, Color

from random import randint as rando
import time
import socket
import certifi
import os
#import urllib.request

from plyer import gps

try:
    from android.permissions import request_permissions, Permission, check_permission
except Exception as e:
    print('couldnt import android.permissions: ', e)

lat = "foo"
lng = "foo"
gpsData = "foo"
locationAble = True

class MyGrid(GridLayout):

    def __init__(self, **kwargs):

        global lat
        global lng
        global locationAble
        global gpsData


        super(MyGrid, self).__init__(**kwargs)
        self.cols = 1

        self.inside = GridLayout()
        self.inside.cols = 2

        #Starts GPS monitoring
        try:
            
            request_permissions([Permission.ACCESS_COARSE_LOCATION,
                                    Permission.ACCESS_FINE_LOCATION])
            
            try:
                while not check_permission('android.permission.ACCESS_COARSE_LOCATION'):

                    print('Inside getLocationData(): Permissions have not been granted yet. Waiting .5 seconds')
                    time.sleep(.5)

                    pass

            except Exception as e:
                print('Couldnt loop waiting for permissions: ',e)

            try:
                gps.configure(on_location=self.onLocation)#, on_status=self.onStatus)
                print('gps.configure worked')

            except Exception as e:

                print('gps.configure failed: ', e)

            try:
                gps.start(minTime=1000,minDistance=1)
            except Exception as e:
                print("gps.start failed: ", e)

        except Exception as e:
            print("GPS monitering failed: ", e)
            locationAble = False

        if locationAble:

            self.add_widget(Label(text="Waiting for GPS data..."))

            pass

        else:

            self.add_widget(Label(text="Couldn't get GPS data"))

            pass


    def refreshScreen(self):
        global gpsData

        print("Refreshing Screen")

        finalStr = '[color=#000000][size=26]This app crashes from time to time. \nIf this happens you can open the app again.[/size] \n\n\n\n\n\n' + gpsData + '[/color]'

        with self.canvas:
            Color(1,1,1)
            Rectangle(size = (1000,1000))

        self.clear_widgets()
        self.add_widget(Label(text=finalStr, halign = 'center', markup = True))

    def onStatus(stype,status):
        global lat
        global lng

        print('inside onStatus')
        try:

            gps_status = 'type={}\n{}'.format(stype, status)
            print('finishing onStatus with gps_status as: ', str(gps_status))

        except Exception as e:

            print('failed inside onStatus: ', e)


    def onLocation(self, **kwargs):

        global lat
        global lng
        global gpsData

        print('inside onLocation')
        try:

            gpsCycles = 0
            if gpsCycles == 0:

                try:
                    print('trying to print kwargs inside onLocation():')
                    print(kwargs)
                except exception as e:

                    print('failed to print kwargs: ',e)

                try:
                    gpsData = '\n'.join([
                            '{}={}'.format(k, v) for k, v in kwargs.items()])

                except Exception as e:
                    print('Failed to get gps data inside onLocation: ', e)

                #Formats the data into the string to display
                try:

                    lat = kwargs['lat']
                    lng = kwargs['lon']
                    speed = kwargs['speed']
                    bearing = kwargs['bearing']
                    altitude = kwargs['altitude']
                    acc = kwargs['accuracy']

                    latStr = 'Latitude: ' + str(lat) + '\N{DEGREE SIGN}N'
                    lngStr = 'Longitude: ' + str(lng) + '\N{DEGREE SIGN}W'
                    speedStr = 'Speed: ' + str(speed) + 'm/s'
                    bearingStr = 'Bearing: ' + str(bearing) + '\N{DEGREE SIGN}'
                    altitudeStr = 'Altitude: ' + str(altitude) + 'meters'
                    accStr = 'Accurate within ' + str(acc) + ' meters'

                    gpsData = latStr + '\n' + lngStr + '\n' + speedStr + '\n' + bearingStr + '\n' + altitudeStr + '\n\n\n\n\n\n[size=30][u]' + str(accStr) + '[/u][/size]'

                    pass

                except Exception as e:
                    print("failed to format data: ", e)

                try:
                    print('trying to assign lat from kwargs...')
                    #lat = kwargs['lat']
                    #print('inside onLocation(): got lat: ',str(lat))
                except Exception as e:
                    print('inside onLocation(): failed to assign lat: ',e)

                try:
                    print('trying to assign lng from kwargs...')
                    #lng = kwargs['lon']
                    print('inside onLocation(): got lat: ',str(lat))
                except Exception as e:
                    print('inside onLocation(): failed to assign lng: ',e)


                try:
                    print('Inside onlocation(): trying to update gpsCycle...')
                    gpsCycles = gpsCycles + 1

                except Exception as e:
                    print('Inside onLocation(): Couldnt update gpsCycles: ',e)


            else:
                print('Inside onLocation(): this is an exccess call')

        except Exception as e:

            print('Inside onLocation(): Main try failed: ',e)

        try:
            print("Inside class.onLocation(): trying to refresh Screen...")
            self.refreshScreen()
            print("refreshed screen")
        except Exception as e:
            print("Failed to refresh Screen: ", e)



class MyApp(App):
    def build(self):
        return MyGrid()


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

Anyone know why this is happening? I don't have the deepest understanding on python so please be patient with me. Is this Kivy crashing? or a logic error?

Upvotes: 1

Views: 271

Answers (1)

Ankit Sangwan
Ankit Sangwan

Reputation: 1247

A variable defined inside a class is considered as a temporary variable and can be called for a limited number of times usually 4-5. If you try to access that variable more than that (usually happens in kivy when you are using any variable to do something on the screen and arriving at that same screen again and again) so you get the error, "weakly-referenced object no longer exists". Check on which screen you are getting that error. To remove this error you basically have to make that variable an instance variable (by adding 'self.' in front). In your case, I guess lat, long, etc are giving errors. So instead of using lat, long use self.lat, self.long, and so on

Also, there's a bug in older version of kivy which result in this error. In your buildozer.spec file change the version of kivy. In requirements instead of Python,kivy write Python,kivy=2.2.0rc4 Then delete the .buildozer directory and pack the application again using buildozer android debug deploy run

Upvotes: 1

Related Questions