Skip to content

Instantly share code, notes, and snippets.

@telent
Last active May 23, 2021 12:59
Show Gist options
  • Select an option

  • Save telent/6409c94ff9a4f448ecbd6b5859718669 to your computer and use it in GitHub Desktop.

Select an option

Save telent/6409c94ff9a4f448ecbd6b5859718669 to your computer and use it in GitHub Desktop.
"""
My first application
"""
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
from rubicon.java import JavaClass, JavaInterface
from rubicon.java.jni import java
LocationListener = JavaInterface("android/location/LocationListener")
class LocListener(LocationListener):
def onFlushComplete(self, code):
print(f"{code} flush")
def onProviderDisabled(self, provider):
print(f"{provider} disabled")
def onProviderEnabled(self, provider):
print(f"{provider} enabled")
def onStatusChanged(self, status, extras):
print(f"status {status} {extras}")
def onLocationChanged(self, location):
print(f"location {location}")
if location != None:
# self.locationHolder.latitude = location.getLatitude()
# self.locationHolder.longitude = location.getLongitude()
print(location)
class Gadgetbee(toga.App):
LocationManager = JavaClass("android/location/LocationManager")
def ensureLocationPermission(self, activity, code):
ContextCompat = JavaClass('androidx/core/content/ContextCompat')
ActivityCompat = JavaClass('androidx/core/app/ActivityCompat')
Helpers = JavaClass('org/beeware/android/HelpersKt')
Manifest = JavaClass('android/Manifest')
permission = JavaClass('android/Manifest$permission')
GRANTED = JavaClass('android/content/pm/PackageManager').PERMISSION_GRANTED
if ContextCompat.checkSelfPermission(activity, "android.permission.ACCESS_FINE_LOCATION") != GRANTED:
perms = permission.ACCESS_FINE_LOCATION
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
permission.ACCESS_FINE_LOCATION)):
Helpers.requestPermission(activity, perms, code)
else:
Helpers.requestPermission(activity, perms, code)
def pollLocation(self):
location = self.locationManager.getLastKnownLocation(self.LocationManager.GPS_PROVIDER)
if location != None:
self.latitude = location.getLatitude()
self.longitude = location.getLongitude()
print(location)
def startLocationReporting(self, context):
print("service", JavaClass("android/app/Service"))
loc_service = JavaClass("android/content/Context").LOCATION_SERVICE
print("loc constant",loc_service)
t = context.getSystemService(loc_service)
self.locationManager = self.LocationManager(__jni__=java.NewGlobalRef(t))
loclistener = LocListener()
self.pollLocation()
self.locationManager.requestLocationUpdates(self.LocationManager.GPS_PROVIDER,
1000, 1.0,
loclistener)
def startup(self):
"""
Construct and show the Toga application.
Usually, you would add your application to a main content box.
We then create a main window (with a name matching the app), and
show the main window.
"""
main_box = toga.Box(style=Pack(direction=COLUMN))
Intent = JavaClass('android/content/Intent')
Uri = JavaClass('android/net/Uri')
activity = JavaClass('org/beeware/android/MainActivity').singletonThis
name_label = toga.Label("HI", style=Pack(padding=(0, 5)))
name_box = toga.Box(style=Pack(direction=ROW, padding=5))
name_box.add(name_label)
button = toga.Button(
'Where am I?',
on_press=self.say_hello,
style=Pack(padding=5)
)
main_box.add(name_box)
main_box.add(button)
self.ensureLocationPermission(activity, 1)
self.startLocationReporting(activity)
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
def say_hello(self, widget):
self.pollLocation()
self.main_window.info_dialog(
'Hi there!',
f"lat {self.latitude} lon {self.longitude}"
)
def main():
return Gadgetbee()
"""
My first application
"""
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
from rubicon.java import JavaClass, JavaInterface, JavaProxy
from rubicon.java.jni import java
LocationListener = JavaInterface("android/location/LocationListener")
class LocListener(LocationListener):
def __init__(self):
super().__init__()
def onFlushComplete(self, code):
print(f"{code} flush")
return 0
def onProviderDisabled(self, provider):
print(f"{provider} disabled")
return 0
def onProviderEnabled(self, provider):
print(f"{provider} enabled")
return 0
def onStatusChanged(self, status, extras):
print(f"status {status} {extras}")
return 0
def onLocationChanged(self, location):
print(f"location {location}")
if location is not None:
# self.locationHolder.latitude = location.getLatitude()
# self.locationHolder.longitude = location.getLongitude()
print(location)
return 0
def hashCode(self):
print("hash")
return 1
class Gadgetbee(toga.App):
LocationManager = JavaClass("android/location/LocationManager")
def ensureLocationPermission(self, activity, code):
ContextCompat = JavaClass('androidx/core/content/ContextCompat')
ActivityCompat = JavaClass('androidx/core/app/ActivityCompat')
Helpers = JavaClass('org/beeware/android/HelpersKt')
Manifest = JavaClass('android/Manifest')
permission = JavaClass('android/Manifest$permission')
GRANTED = JavaClass('android/content/pm/PackageManager').PERMISSION_GRANTED
if ContextCompat.checkSelfPermission(activity, "android.permission.ACCESS_FINE_LOCATION") != GRANTED:
perms = permission.ACCESS_FINE_LOCATION
if ActivityCompat.shouldShowRequestPermissionRationale(activity,
permission.ACCESS_FINE_LOCATION):
Helpers.requestPermission(activity, perms, code)
else:
Helpers.requestPermission(activity, perms, code)
def pollLocation(self):
location = self.locationManager.getLastKnownLocation(self.LocationManager.GPS_PROVIDER)
if location is not None:
self.latitude = location.getLatitude()
self.longitude = location.getLongitude()
print(location)
def startLocationReporting(self, context):
global loclistener
print("service", JavaClass("android/app/Service"))
loc_service = JavaClass("android/content/Context").LOCATION_SERVICE
print("loc constant", loc_service)
t = context.getSystemService(loc_service)
# NewGlobalRef used here to cast the Object to a LocationManager
self.locationManager = self.LocationManager(__jni__=java.NewGlobalRef(t))
locl = LocListener()
self.locListener = locl
print(locl._methods)
self.pollLocation()
self.locationManager.requestLocationUpdates(self.LocationManager.GPS_PROVIDER,
1000, 1.0,
locl)
def startup(self):
"""
Construct and show the Toga application.
Usually, you would add your application to a main content box.
We then create a main window (with a name matching the app), and
show the main window.
"""
main_box = toga.Box(style=Pack(direction=COLUMN))
Intent = JavaClass('android/content/Intent')
Uri = JavaClass('android/net/Uri')
activity = JavaClass('org/beeware/android/MainActivity').singletonThis
name_label = toga.Label("HI", style=Pack(padding=(0, 5)))
name_box = toga.Box(style=Pack(direction=ROW, padding=5))
name_box.add(name_label)
button = toga.Button(
'Where am I?',
on_press=self.say_hello,
style=Pack(padding=5)
)
main_box.add(name_box)
main_box.add(button)
self.ensureLocationPermission(activity, 1)
self.startLocationReporting(activity)
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
def say_hello(self, widget):
self.pollLocation()
print(self.locListener._methods)
self.main_window.info_dialog(
'Hi there!',
f"lat {self.latitude} lon {self.longitude}"
)
def main():
return Gadgetbee()
@telent
Copy link
Copy Markdown
Author

telent commented May 22, 2021

05-22 23:30:45.126 28875 28875 I Python : service <JavaClass: b'android/app/Service'>
05-22 23:30:45.127 28875 28875 I Python : loc constant location
05-22 23:30:45.155 28875 28875 I Python : Location[gps 51.595463,-0.030617 hAcc=15 et=+7h56m48s756ms alt=72.0 vel=0.0 vAcc=16 sAcc=0 bAcc=??? {Bundle[mParcelledData.dataSize=96]}]
05-22 23:30:45.163 28875 28875 D Python : Native invocation 484538061264 :: hashCode
05-22 23:30:45.163 28875 28875 E Python : Error invoking callback
05-22 23:30:45.163 28875 28875 E Python : Traceback (most recent call last):
05-22 23:30:45.163 28875 28875 E Python : File "/data/user/0/net.telent.gadgetbee/files/python/user_code/app_packages/rubicon/java/api.py", line 36, in dispatch
05-22 23:30:45.164 28875 28875 E Python : if len(signatures) == 1:
05-22 23:30:45.164 28875 28875 E Python : TypeError: object of type 'NoneType' has no len()
05-22 23:30:45.164 28875 28875 D Python : Native invocation done.
05-22 23:30:45.281 28900 28900 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

@telent
Copy link
Copy Markdown
Author

telent commented May 22, 2021

also got a java backtrace in logcat, but it seems to be consequent to the python error, not antecedent

-22 23:37:58.057 29211 29211 F zygote64: runtime.cc:523]   (no managed stack frames)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at android.app.ActivityThread.-wrap11(ActivityThread.java:-1)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at android.os.Looper.loop(Looper.java:164)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at java.lang.reflect.Method.invoke(Native method)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at int java.lang.Object.hashCode() ((null):-1)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at android.location.LocationManager$ListenerTransport android.location.LocationManager.wrapListener(android.location.LocationListener, android.os.Looper) (LocationManager.java:870)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at int org.beeware.rubicon.Python.run(java.lang.String, java.lang.String[]) (Python.java:-2)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at void org.beeware.android.MainActivity.startPython(java.util.Map) (MainActivity.java:225)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1214)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2856)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:106)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at void android.os.Looper.loop() (Looper.java:164)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run() (RuntimeInit.java:438)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:523]   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:807)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:531] JNI DETECTED ERROR IN APPLICATION: JNI NewStringUTF called with pending exception java.lang.NullPointerException: Expected to unbox a 'int' primitive type but was returned null
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:531]   at int java.lang.Object.hashCode() ((null):-1)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:531]   at int java.util.HashMap.hash(java.lang.Object) (HashMap.java:338)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:531]   at java.lang.Object java.util.HashMap.get(java.lang.Object) (HashMap.java:556)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:531]   at void android.location.LocationManager.requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper, android.app.PendingIntent) (LocationManager.java:885)
05-22 23:37:58.058 29211 29211 F zygote64: runtime.cc:531]   at void org.beeware.android.MainActivity.startPython(java.util.Map) (MainActivity.java:225)

@telent
Copy link
Copy Markdown
Author

telent commented May 22, 2021

looking at the logcat line Native invocation 484536464400 :: hashCode and the code that produces it, I realise that it is trying to call the hashCode method. However, adding

class LocListener(LocationListener):
    def hashCode(self):
        print("hash")
        return 42

seems to have no effect (and the print statement is not executed either, as far as I can tell)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment