From 5752d5e8176f0bb64ead00cfa1b44e93e23e0a91 Mon Sep 17 00:00:00 2001 From: Nik Klever Date: Thu, 6 Sep 2012 17:20:07 +0200 Subject: [PATCH 1/3] Added a compass demo using the magnetic field sensor of an android device - developed for demonstrating purposes of pyjnius --- examples/demo/compass/500px-Windrose.svg.png | Bin 0 -> 35182 bytes examples/demo/compass/README.txt | 11 ++ examples/demo/compass/android.txt | 3 + examples/demo/compass/main.py | 171 +++++++++++++++++++ examples/demo/compass/public.version | 1 + 5 files changed, 186 insertions(+) create mode 100644 examples/demo/compass/500px-Windrose.svg.png create mode 100644 examples/demo/compass/README.txt create mode 100644 examples/demo/compass/android.txt create mode 100644 examples/demo/compass/main.py create mode 100644 examples/demo/compass/public.version diff --git a/examples/demo/compass/500px-Windrose.svg.png b/examples/demo/compass/500px-Windrose.svg.png new file mode 100644 index 0000000000000000000000000000000000000000..f3f5f0db73315b87af2ba55baa4e98a4cd57ebd8 GIT binary patch literal 35182 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 gloWA2IcxHN`|^vmdKI;Vst0Dz38J^%m! literal 0 HcmV?d00001 diff --git a/examples/demo/compass/README.txt b/examples/demo/compass/README.txt new file mode 100644 index 000000000..7b05b556c --- /dev/null +++ b/examples/demo/compass/README.txt @@ -0,0 +1,11 @@ +Compass +======= + +Demonstrate the combination of the Android Magnetic Field Sensor and the Kivy functionality viewing a Compass. + +Android +------- + +You can copy/paste this directory into /sdcard/kivy/compass in your +android device. + diff --git a/examples/demo/compass/android.txt b/examples/demo/compass/android.txt new file mode 100644 index 000000000..813307fd6 --- /dev/null +++ b/examples/demo/compass/android.txt @@ -0,0 +1,3 @@ +title=Compass +author=Nik Klever +orientation=portrait diff --git a/examples/demo/compass/main.py b/examples/demo/compass/main.py new file mode 100644 index 000000000..29b9f2a9d --- /dev/null +++ b/examples/demo/compass/main.py @@ -0,0 +1,171 @@ +import kivy +kivy.require('1.3.0') + +import math +import time + +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.button import Button +from kivy.uix.scatter import Scatter +from kivy.clock import Clock +from kivy.vector import Vector +from kivy.core.window import Window +from kivy.graphics import Color, Ellipse, Rectangle, Triangle +from kivy.logger import Logger + +#from android import orientation_enable,orientation_reading +from jnius import autoclass + +Logger.info('COMPASS: STARTED') + +def LoggerCompleteObj(text,obj): + import types + Logger.info('COMPASS: ----- [%s] ----- ----- %s -----'%(text,str(obj))) + for k in dir(obj): + if not isinstance(getattr(obj,k), (types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType, types.MethodType, types.UnboundMethodType)) and \ + not k.startswith('__'): + Logger.info('COMPASS: %s = %s'%(str(k),str(getattr(obj,k)))) + +def LoggerSizeObj(text,obj): + import types + for k in ['pos','size','width','height','center','pos_hint','size_hint','rotation']: + try: + Logger.info('COMPASS: - [%s] - %s = %s'%(text,k,str(getattr(obj,k)))) + except: + pass + +def LoggerDisplayMetrics(metrics): + display = {'Default':metrics.DENSITY_DEFAULT, + 'Device':metrics.DENSITY_DEVICE, + 'High':metrics.DENSITY_HIGH, + 'Low':metrics.DENSITY_LOW, + 'Medium':metrics.DENSITY_MEDIUM, + #'TV':metrics.DENSITY_TV, + 'XHIGH':metrics.DENSITY_XHIGH, + 'density':metrics.density, + 'densityDpi':metrics.densityDpi, + 'heightPixels':metrics.heightPixels, + 'scaledDensity':metrics.scaledDensity, + 'widthPixels':metrics.widthPixels, + 'xdpi':metrics.xdpi, + 'ydpi':metrics.ydpi} + #Logger.info('COMPASS: DisplayMetrics display %r'%(display)) + for (k,v) in display.items(): + Logger.info('COMPASS: display %s = %s'%(k,v)) + +class CompassWidget(FloatLayout): + + def __init__(self, **kwargs): + super(CompassWidget, self).__init__(**kwargs) + + def build(self,pos,size): + with self.canvas: + self.pos = pos + self.size = size + self.windrose = Ellipse(source="500px-Windrose.svg.png", pos=pos, size=size) + #LoggerCompleteObj('CompassWidget build self',self) + +class NeedleWidget(Scatter): + + def __init__(self, **kwargs): + super(NeedleWidget, self).__init__(**kwargs) + + self.do_rotation = False + self.do_translation = False + self.do_scale = False + self.auto_bring_to_front = True + + def rotateNeedle(self,angle): + self.rotation = angle - 90 + #Logger.info('COMPASS: rotateNeedle angle=%s rotation=%s '%(str(angle),str(self.rotation))) + #LoggerSizeObj('NeedleWidget rotateNeedle',self) + + def build(self,center,needleSize): + self.pos = center - needleSize/2. + self.size = needleSize + self.size_hint = [None, None] + #LoggerSizeObj('NeedleWidget build',self) + with self.canvas: + Color(1., 0, 0) + needleTP1 = Vector(needleSize[0]/2.,needleSize[1]) + needleTP2 = Vector(needleSize[0]/2.,0) + needleTP3 = Vector(-needleSize[0],needleSize[1]/2.) + needlePoints = (needleTP1[0],needleTP1[1], + needleTP2[0],needleTP2[1], + needleTP3[0],needleTP3[1]) + self.needleT1 = Triangle(points=needlePoints) + Color(0.5, 0.5, 0.5) + needleTP3 = Vector(2*needleSize[0],needleSize[1]/2.) + needlePoints = (needleTP1[0],needleTP1[1], + needleTP2[0],needleTP2[1], + needleTP3[0],needleTP3[1]) + self.needleT2 = Triangle(points=needlePoints) + #LoggerCompleteObj('NeedleWidget init self',self) + +class CompassApp(App): + + def __init__(self, **kwargs): + super(CompassApp, self).__init__(**kwargs) + DisplayMetrics = autoclass('android.util.DisplayMetrics') + metrics = DisplayMetrics() + metrics.setToDefaults() + LoggerDisplayMetrics(metrics) + self.densityDpi = metrics.densityDpi + + Hardware = autoclass('org.renpy.android.Hardware') + self.hw = Hardware() + Logger.info('COMPASS: Hardware dir %s'%(str(dir(self.hw)))) + + def viewCompass(self, *largs): + (x, y, z) = self.hw.magneticFieldSensorReading() + declination = Vector(x,y).angle((0,1)) + #Logger.info('COMPASS: viewCompass x=%s y=%s z=%s declination=%s'%(x,y,z,declination)) + self.needle.rotateNeedle(declination) + + def stopApp(self,*largs): + self.hw.magneticFieldSensorEnable(False) + Logger.info('COMPASS: stop largs '+str(largs)) + self.stop() + + def build(self): + parent = FloatLayout(size=(500,500)) + Window.clearcolor = (1, 1, 1, 1) + + self.Compass = CompassWidget() + parent.add_widget(self.Compass) + if self.densityDpi == 240: + CompassPos = Vector(50., 200.) + CompassSize = Vector(400., 400.) + needleSize = Vector(100., 60.) + stopButtonHeight = 60 + elif self.densityDpi == 320: + CompassPos = Vector(75., 300.) + CompassSize = Vector(600., 600.) + needleSize = Vector(150., 90.) + stopButtonHeight = 80 + else: + Logger.info('COMPASS: widget size should be adopted - minimum used for densityDpi=%s'%(str(self.densityDpi))) + CompassPos = Vector(50., 200.) + CompassSize = Vector(400., 400.) + needleSize = Vector(100., 60.) + stopButtonHeight = 60 + self.Compass.build(pos=CompassPos,size=CompassSize) + + self.needle = NeedleWidget() + parent.add_widget(self.needle) + self.needle.build(center=CompassPos+CompassSize/2.,needleSize=needleSize) + + self.stopButton = Button(text='Stop', pos_hint={'right':1}, size_hint=(None,None), height=stopButtonHeight) + parent.add_widget(self.stopButton) + self.stopButton.bind(on_press=self.stopApp) + + LoggerCompleteObj('CompassApp build parent',parent) + self.hw.magneticFieldSensorEnable(True) + Clock.schedule_interval(self.viewCompass, 1.) + return parent + +if __name__ in ('__main__', '__android__'): + CompassApp().run() + + diff --git a/examples/demo/compass/public.version b/examples/demo/compass/public.version new file mode 100644 index 000000000..7dbe9c441 --- /dev/null +++ b/examples/demo/compass/public.version @@ -0,0 +1 @@ +1323529642.46 \ No newline at end of file From b403b9d8dd3d29f589fc0ef085d8319135ea9a5f Mon Sep 17 00:00:00 2001 From: Nik Klever Date: Fri, 7 Sep 2012 09:16:53 +0200 Subject: [PATCH 2/3] moved compass app from examples/demo to examples/android --- .../compass/500px-Windrose.svg.png | Bin examples/{demo => android}/compass/README.txt | 0 examples/{demo => android}/compass/android.txt | 0 examples/{demo => android}/compass/main.py | 0 examples/{demo => android}/compass/public.version | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename examples/{demo => android}/compass/500px-Windrose.svg.png (100%) rename examples/{demo => android}/compass/README.txt (100%) rename examples/{demo => android}/compass/android.txt (100%) rename examples/{demo => android}/compass/main.py (100%) rename examples/{demo => android}/compass/public.version (100%) diff --git a/examples/demo/compass/500px-Windrose.svg.png b/examples/android/compass/500px-Windrose.svg.png similarity index 100% rename from examples/demo/compass/500px-Windrose.svg.png rename to examples/android/compass/500px-Windrose.svg.png diff --git a/examples/demo/compass/README.txt b/examples/android/compass/README.txt similarity index 100% rename from examples/demo/compass/README.txt rename to examples/android/compass/README.txt diff --git a/examples/demo/compass/android.txt b/examples/android/compass/android.txt similarity index 100% rename from examples/demo/compass/android.txt rename to examples/android/compass/android.txt diff --git a/examples/demo/compass/main.py b/examples/android/compass/main.py similarity index 100% rename from examples/demo/compass/main.py rename to examples/android/compass/main.py diff --git a/examples/demo/compass/public.version b/examples/android/compass/public.version similarity index 100% rename from examples/demo/compass/public.version rename to examples/android/compass/public.version From 86bc437fcfabfeedd3efa241ff5e44026b664237 Mon Sep 17 00:00:00 2001 From: Nik Klever Date: Sat, 8 Sep 2012 21:51:32 +0200 Subject: [PATCH 3/3] compass app example adopted to a tidy new Hardware.java --- examples/android/compass/README.txt | 21 ++++- examples/android/compass/main.py | 116 ++++++++++++++++++++-------- 2 files changed, 101 insertions(+), 36 deletions(-) diff --git a/examples/android/compass/README.txt b/examples/android/compass/README.txt index 7b05b556c..ed331c014 100644 --- a/examples/android/compass/README.txt +++ b/examples/android/compass/README.txt @@ -3,9 +3,22 @@ Compass Demonstrate the combination of the Android Magnetic Field Sensor and the Kivy functionality viewing a Compass. -Android -------- +Kivy Python-For-Android +----------------------- -You can copy/paste this directory into /sdcard/kivy/compass in your -android device. +Please look at the lastest docs of the +`Kivy Python-For-Android Project `__ + +Building an APK +--------------- + +:: + + ./distribute.sh -m "pyjnius kivy" + + +:: + + ./build.py --package org.test.compass --name compass \ + --version 1.0 --dir ~/code/kivy/examples/android/compass debug diff --git a/examples/android/compass/main.py b/examples/android/compass/main.py index 29b9f2a9d..59b329c80 100644 --- a/examples/android/compass/main.py +++ b/examples/android/compass/main.py @@ -14,34 +14,20 @@ from kivy.core.window import Window from kivy.graphics import Color, Ellipse, Rectangle, Triangle from kivy.logger import Logger -#from android import orientation_enable,orientation_reading from jnius import autoclass Logger.info('COMPASS: STARTED') -def LoggerCompleteObj(text,obj): - import types - Logger.info('COMPASS: ----- [%s] ----- ----- %s -----'%(text,str(obj))) - for k in dir(obj): - if not isinstance(getattr(obj,k), (types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType, types.MethodType, types.UnboundMethodType)) and \ - not k.startswith('__'): - Logger.info('COMPASS: %s = %s'%(str(k),str(getattr(obj,k)))) - -def LoggerSizeObj(text,obj): - import types - for k in ['pos','size','width','height','center','pos_hint','size_hint','rotation']: - try: - Logger.info('COMPASS: - [%s] - %s = %s'%(text,k,str(getattr(obj,k)))) - except: - pass - def LoggerDisplayMetrics(metrics): + """ + Logging all values of the Java Android DisplayMetrics class + to get some more information about the metrics of Android devices + """ display = {'Default':metrics.DENSITY_DEFAULT, 'Device':metrics.DENSITY_DEVICE, 'High':metrics.DENSITY_HIGH, 'Low':metrics.DENSITY_LOW, 'Medium':metrics.DENSITY_MEDIUM, - #'TV':metrics.DENSITY_TV, 'XHIGH':metrics.DENSITY_XHIGH, 'density':metrics.density, 'densityDpi':metrics.densityDpi, @@ -50,25 +36,38 @@ def LoggerDisplayMetrics(metrics): 'widthPixels':metrics.widthPixels, 'xdpi':metrics.xdpi, 'ydpi':metrics.ydpi} - #Logger.info('COMPASS: DisplayMetrics display %r'%(display)) for (k,v) in display.items(): Logger.info('COMPASS: display %s = %s'%(k,v)) class CompassWidget(FloatLayout): def __init__(self, **kwargs): + """ + Constructor of the CompassWidget class + """ super(CompassWidget, self).__init__(**kwargs) def build(self,pos,size): + """ + building the background of the CompassWidget with a circle of a + compass windrose image + (Source of this image: Wikipedia - http://en.wikipedia.org/wiki/Compass_rose) + """ with self.canvas: self.pos = pos self.size = size self.windrose = Ellipse(source="500px-Windrose.svg.png", pos=pos, size=size) - #LoggerCompleteObj('CompassWidget build self',self) class NeedleWidget(Scatter): def __init__(self, **kwargs): + """ + Constructor of the NeedleWidget class + + do_rotation, do_translation, do_scale are all set to False + to indicate that the scatter widget can onlybe updated from the + app and not by an interaction with your fingers + """ super(NeedleWidget, self).__init__(**kwargs) self.do_rotation = False @@ -77,15 +76,20 @@ class NeedleWidget(Scatter): self.auto_bring_to_front = True def rotateNeedle(self,angle): + """ + rotate the NeedleWidget with the parameter angle + 90 is subtracted because North of the windrose is at 90 degrees + of the device + """ self.rotation = angle - 90 - #Logger.info('COMPASS: rotateNeedle angle=%s rotation=%s '%(str(angle),str(self.rotation))) - #LoggerSizeObj('NeedleWidget rotateNeedle',self) def build(self,center,needleSize): + """ + building the needle with two Triangles of different color + """ self.pos = center - needleSize/2. self.size = needleSize self.size_hint = [None, None] - #LoggerSizeObj('NeedleWidget build',self) with self.canvas: Color(1., 0, 0) needleTP1 = Vector(needleSize[0]/2.,needleSize[1]) @@ -101,11 +105,20 @@ class NeedleWidget(Scatter): needleTP2[0],needleTP2[1], needleTP3[0],needleTP3[1]) self.needleT2 = Triangle(points=needlePoints) - #LoggerCompleteObj('NeedleWidget init self',self) class CompassApp(App): def __init__(self, **kwargs): + """ + Constructor of the Compass App + + 1) The Java Android API DisplayMetrics is called to get + information about the densityDpi factor of the Android device + + 2) The Kivy Python-For-Android Android API is called to + get access to the hardware sensors of the Android device + + """ super(CompassApp, self).__init__(**kwargs) DisplayMetrics = autoclass('android.util.DisplayMetrics') metrics = DisplayMetrics() @@ -115,25 +128,62 @@ class CompassApp(App): Hardware = autoclass('org.renpy.android.Hardware') self.hw = Hardware() - Logger.info('COMPASS: Hardware dir %s'%(str(dir(self.hw)))) + Logger.info('COMPASS: Hardware Objects: %s'%(str(dir(self.hw)))) + Logger.info('COMPASS: Hardware Sensors\n%s\n'%(self.hw.getHardwareSensors())) def viewCompass(self, *largs): - (x, y, z) = self.hw.magneticFieldSensorReading() + """ + viewCompass calls the readSensor method of the + magneticFieldSensor instance of the generic3AxisSensor, it reads the + 3-tuple value of the magnetic field + + the declination angle is computed as the angle of the magnetic field + vector in the x,y-plane and the unity-vector of the y-axis. + + afterwards the rotateNeedle function rotates the needle as given + by the declination angle parameter + """ + (x, y, z) = self.hw.magneticFieldSensor.readSensor() declination = Vector(x,y).angle((0,1)) #Logger.info('COMPASS: viewCompass x=%s y=%s z=%s declination=%s'%(x,y,z,declination)) self.needle.rotateNeedle(declination) def stopApp(self,*largs): - self.hw.magneticFieldSensorEnable(False) + """ + this function is called when pushed the stopButton, disables + the magneticFieldSensor and stops the app + """ + self.hw.magneticFieldSensor.changeStatus(False) Logger.info('COMPASS: stop largs '+str(largs)) self.stop() def build(self): + """ + Building all together: + + 1) Creating the parent widget and clearing it to white background color + + 2) Defining a suitable position and size of the CompassWidget, the + needleSize and the stopButtonHeight depending on the densityDpi value + given by DisplayMetrics + + 3) Creating an instance of the CompassWidget and adding it to the + parent widget and calling the appropriate build function + + 4) Creating an instance of the NeedleWidget and adding it also to the + parent widget and calling the appropriate build function + + 5) Creating an instance of a Button widget and adding it as stopButton + also to the parent widget and bind it with the stopApp function + + 6) Calling the instance method changeStatus of the magneticFieldSensor + instance with parameter True to enable the magnetic field sensor + and additionally calling the function schedule_interval of the Clock + class for a repeated call of the function viewCompass every second. + """ parent = FloatLayout(size=(500,500)) Window.clearcolor = (1, 1, 1, 1) - self.Compass = CompassWidget() - parent.add_widget(self.Compass) if self.densityDpi == 240: CompassPos = Vector(50., 200.) CompassSize = Vector(400., 400.) @@ -143,13 +193,16 @@ class CompassApp(App): CompassPos = Vector(75., 300.) CompassSize = Vector(600., 600.) needleSize = Vector(150., 90.) - stopButtonHeight = 80 + stopButtonHeight = 90 else: Logger.info('COMPASS: widget size should be adopted - minimum used for densityDpi=%s'%(str(self.densityDpi))) CompassPos = Vector(50., 200.) CompassSize = Vector(400., 400.) needleSize = Vector(100., 60.) stopButtonHeight = 60 + + self.Compass = CompassWidget() + parent.add_widget(self.Compass) self.Compass.build(pos=CompassPos,size=CompassSize) self.needle = NeedleWidget() @@ -160,8 +213,7 @@ class CompassApp(App): parent.add_widget(self.stopButton) self.stopButton.bind(on_press=self.stopApp) - LoggerCompleteObj('CompassApp build parent',parent) - self.hw.magneticFieldSensorEnable(True) + self.hw.magneticFieldSensor.changeStatus(True) Clock.schedule_interval(self.viewCompass, 1.) return parent