Simple Camera With Kivy
FleetingThe simple pwa offline camera works well, but has one issue: it reloads when scrolling down.
Let’s try building a simple camera with kivy, using the camera example as basis.
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
from jnius import autoclass
import time
import os
from android.runnable import run_on_ui_thread
from kivy.animation import Animation
from kivy import platform
import plyer
Builder.load_string('''
<CameraClick>:
Camera:
id: camera
resolution: (640, 480)
# resolution: (-1, -1) # best
play: True
allow_stretch: True
Button:
id: button
pos: ((self.parent.width - self.width), (self.parent.height - self.height) / 2)
size_hint: (None, None)
size: (200, 200)
on_press: root.capture()
background_color: (1, 1, 1, 0) # transparent
Image:
id: img
allow_stretch: True
keep_ratio: True
# center in the parent button
y: self.parent.y + self.parent.height / 2 - self.height / 2
x: self.parent.x + self.parent.width / 2 - self.width / 2
# fit to the parent button (keep_ratio will prevent it from being distorded)
size: (self.parent.width, self.parent.height)
''')
class CameraClick(FloatLayout):
def __init__(self, *args, **kwargs):
super(CameraClick, self).__init__(*args, **kwargs)
self.doing = False
print("camera click")
Environment = autoclass('android.os.Environment')
self.download_folder = os.path.join(Environment.getExternalStorageDirectory().absolutePath, "Download")
if not os.path.exists(self.download_folder):
os.mkdir(self.download_folder)
self.ids.img.source = os.path.join(__file__, "..", "icon.png")
def done(self, *args):
self.doing = False
def shoot(self, *args):
timestr = time.strftime("%Y%m%d_%H%M%S")
camera = self.ids['camera']
camera.export_to_png(os.path.join(self.download_folder, "IMG_{}.png".format(timestr)))
button = self.ids['button']
self.anim2 = Animation(background_color=(0, 0, 0, 1), duration=0.5)
self.anim2 &= Animation(size=(200, 200), duration=0.3)
self.anim2 &= Animation(pos=((self.width - 200), (self.height - 200) / 2), duration=0.5)
self.anim2.bind(on_complete=self.done)
self.anim2.start(button)
def capture(self):
if self.doing:
return
self.doing = True
button = self.ids['button']
self.anim = Animation(background_color=(1, 1, 1, 1), duration=0.2)
self.anim &= Animation(size=(self.height, self.height), duration=0.2)
self.anim &= Animation(pos=((self.width - self.height) / 2, 0), duration=0.2)
self.anim.bind(on_complete=self.shoot)
self.anim.start(button)
class TestCamera(App):
def build(self):
Window.bind(on_keyboard=self.hook_keyboard)
#plyer.orientation.set_landscape()
self.enter_fullscreen()
self.keep_screen_awake()
return CameraClick()
def enter_fullscreen(self):
nil
def keep_screen_awake(self):
nil
def hook_keyboard(self, window, key, *args):
if key == 27:
exit(0)
return False
def run():
TestCamera().run()
Let’s create a full application, based on from the python android runtime to a custom app.
apktool d app.apk
ipfs get https://konubinix.eu/ipfs/bafkreib4imx2wyoiy5i6xik47kddxqho7iqescorb3zcijxmsyecyxtmfm -o app/assets/icon.png
Saving file(s) to app/assets/icon.png
I changed the main.py to call TestCamera().run() out of run()
pushd "app/assets/" > /dev/null
{
rm private.tar
tar -c --gzip -f private.tar .
mv private.tar /tmp/private.tar && rm * && mv /tmp/private.tar ./
}
popd > /dev/null
magick https://konubinix.eu/ipfs/bafkreib4imx2wyoiy5i6xik47kddxqho7iqescorb3zcijxmsyecyxtmfm ./app/res/drawable/presplash.jpg
magick https://konubinix.eu/ipfs/bafkreib4imx2wyoiy5i6xik47kddxqho7iqescorb3zcijxmsyecyxtmfm -resize 128x128 -background white -gravity center -extent 128x128 ./app/res/mipmap/icon.png
grep -rl '\bproofofconcept\b' | while read line
do
echo "Editing ${line}"
sed -i -r 's/proofofconcept/simplecamera/' "${line}"
done
find -path "*eu/konix/poc"
./app/smali_classes3/eu/konix/poc
./app/smali/eu/konix/poc
Renamed into eu/konix/simplecamera
Also globally renamed eu/konix/poc into eu/konix/simplecamera and afterwards eu.konix.poc into eu.konix.simplecamera and “poc” into “simplecamera” and “Poc” into “Simplecamera”
apktool b app && apksigner sign --ks your-keystore.jks --ks-key-alias your-alias --ks-pass pass:000000 ./app/dist/app.apk
I: Using Apktool 2.10.0 with 4 thread(s).
I: Checking whether sources has changed...
I: Checking whether sources has changed...
I: Checking whether sources has changed...
I: Checking whether sources has changed...
I: Checking whether sources has changed...
I: Checking whether sources has changed...
I: Checking whether resources has changed...
I: Building resources...
I: Building apk file...
I: Copying unknown files/dir...
I: Built apk into: app/dist/app.apk
Once installed, I needed to provide the authorizations manually (photo and sdcard), as the application did not ask for them.
clk android adb uninstall eu.konix.simplecamera
clk android adb install ./app/dist/app.apk
ipfa ./app/dist/app.apk