I am making a program for Android that shows a demonstration of the PC screen on the phone. On Windows the code works fine, but when I build the apk via Bulldozer and try to connect via IP to the server where the image is taken, an error appears in the console (via adb logcat). Application code:
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.graphics.texture import Texture
import cv2
import numpy as np
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
KV = '''
#<KvLang>
MDScreen:
MDBoxLayout:
orientation: 'vertical'
padding: dp(20)
spacing: dp(10)
MDTextField:
id: ip_input
mode: "outlined"
size_hint_y: None
height: "50dp"
MDTextFieldHintText:
text: "Enter the server IP address"
MDButton:
on_release: app.start_stream()
size_hint_y: None
height: "50dp"
MDButtonText:
text: "Connect"
BoxLayout:
id: image_container
size_hint: (1, 1)
pos_hint: {"center_x": 0.5, "center_y": 0.5}
MDLabel:
id: status_label
text: "Status: Waiting for connection"
halign: "center"
size_hint_y: None
height: "50dp"
#</KvLang>
'''
class KivyCamera(Image):
def __init__(self, url, fps=30, **kwargs):
super(KivyCamera, self).__init__(**kwargs)
self.url = url
self.fps = fps
self.capture = None
self.status_label = None
logger.debug(f"Initializing KivyCamera with URL: {url}")
Clock.schedule_interval(self.update, 1.0 / fps)
def set_status(self, text):
try:
if self.status_label is None:
parent = self.parent
while parent is not None:
if hasattr(parent, 'ids') and 'status_label' in parent.ids:
self.status_label = parent.ids['status_label']
break
parent = parent.parent
if self.status_label:
self.status_label.text = text
except Exception:
pass
def update(self, dt):
try:
if self.capture is None:
self.capture = cv2.VideoCapture(self.url)
if not self.capture.isOpened():
self.set_status("Status: Connection Error")
return
self.set_status("Status: Connected")
ret, frame = self.capture.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='rgb')
texture.blit_buffer(cv2.flip(frame, 0).tobytes(), colorfmt='rgb', bufferfmt='ubyte')
self.texture = texture
else:
self.capture.release()
self.capture = None
self.set_status("Status: Reconnecting...")
except Exception as e:
self.set_status(f"Status: Error - {str(e)}")
if self.capture:
self.capture.release()
self.capture = None
def __del__(self):
if self.capture:
self.capture.release()
class MainApp(MDApp):
def __init__(self, **kwargs):
super(MainApp, self).__init__(**kwargs)
self.camera_widget = None
def build(self):
return Builder.load_string(KV)
def start_stream(self):
screen = self.root
ip_address = screen.ids.ip_input.text
if not ip_address:
screen.ids.status_label.text = "Status: Enter IP address"
return
if self.camera_widget is not None:
screen.ids.image_container.remove_widget(self.camera_widget)
try:
url = f'http://{ip_address}:5000/video_feed'
self.camera_widget = KivyCamera(url=url, fps=30)
screen.ids.image_container.add_widget(self.camera_widget)
screen.ids.status_label.text = "Status: Connecting..."
except Exception as e:
screen.ids.status_label.text = f"Status: Error - {str(e)}"
if __name__ == '__main__':
MainApp().run()
buildozer.spec:
requirements = python3,kivy,.zip,opencv_extras,materialyoucolor,numpy,asyncgui,asynckivy
android.permissions = android.permission.INTERNET, android.permission.CAMERA, (name=android.permission.WRITE_EXTERNAL_STORAGE;maxSdkVersion=18)
adb logcat:
03-22 23:32:58.029 13883 15538 E cv::error(): OpenCV(4.5.1) Error: Bad argument (CAP_IMAGES: can't find starting number (in the name of file): http://192.168.0.11:5000/video_feed) in icvExtractPattern, file /home/mapium/python/PyRemoteControl/project_oop/android/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/modules/videoio/src/cap_images.cpp, line 253
03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1: [ERROR:0] global /home/mapium/python/PyRemoteControl/project_oop/android/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/modules/videoio/src/cap.cpp (142) open VIDEOIO(CV_IMAGES): raised OpenCV exception:
03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1:
03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1: OpenCV(4.5.1) /home/mapium/python/PyRemoteControl/project_oop/android/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/modules/videoio/src/cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): http://192.168.0.11:5000/video_feed in function 'icvExtractPattern'
03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1:
03-22 23:32:58.030 13883 15538 E NativeCodec: failed to stat file: http://192.168.0.11:5000/video_feed (No such file or directory)
If I go to the site from where the screen sharing is taken from my phone, everything works fine there.