2

I'm currently working on a project where I need to connect a heart rate sensor to an Android device and visualize the data on a Kivy-based app.

Tried to use serial.tools.list_ports.comports but it returned nothing on the device. They have already stated that the function supports only a limited no. of operating systems so I thought that it wouldn't work on Android.

I have included all the needed requirements in buildozer.spec and whitelisted termios(so I don't have any problems with including the module):

# requirements of the app
requirements = kivy==master,python3crystax,hostpython3crystax,sdl2_image,sdl2_mixer,sdl2_ttf,sdl2_six,pyjnius,pyserial,serial

I tried to edit the AndroidManifest.xml file's intent-filter part to get my app to have USB permission, but it didn't work either.

I've checked on an app that the device does not have a specific name but a changing one that changes by plug the USB in and out like:

/dev/bus/usb/001/002 --> /dev/bus/usb/001/003 --> ...

Also tried to use a generic name /dev/ttyUSB0/ stated in other pages yet to no avail.

The error returned is that the permission is denied to the port.

How can I even list the USB devices connected to the device, ultimately opening a port to communicate with it?

UPDATE #1: I recently tried to use some pyjnius functions. Here's the code that I've written:

from jnius import autoclass
from jnius import cast #cast?


class Serial:
    def __init__(self):
    #Defining the variables for USB-OTG comm. in Android.
    #The strings in autoclasses are classes in Java
    #therefore classes that are used in Android programming.
    self.arrayList = autoclass('java.util.ArrayList')
    self.hashmap = autoclass('java.util.HashMap')
    self.context = autoclass('android.content.Context')
    self.usbConstants = autoclass('android.hardware.usb.UsbConstants')
    self.usbDevice = autoclass('android.hardware.usb.UsbDevice')
    self.usbDeviceConnection = autoclass('android.hardware.usb.UsbDeviceConnection')
    self.hashMap = autoclass('java.util.HashMap')
    self.usbEndpoint = autoclass('android.hardware.usb.UsbEndpoint')
    self.usbManager = autoclass('android.hardware.usb.UsbManager')
    self.usbRequest = autoclass('android.hardware.usb.UsbRequest')
    self.usbInterface = autoclass('android.hardware.usb.UsbInterface')
    self.a = 0

    #As we're using python-for-android, we'll be needing only 
    #the default PythonActivity class.
    self.PythonActivity = autoclass('org.kivy.android.PythonActivity')
    self.activity = self.PythonActivity.mActivity


    #Getting access to make the device a host for USB devices.
    self.usbMgr = cast(self.usbManager, self.activity.getSystemService(self.context.USB_SERVICE))


    self.device = self.usbMgr.getDeviceList().get("deviceName") 


def portName(self):
    return self.device         

where I call self.device in main.py. It returns None.

UPDATE #2: I tried to convert the HashMap I get from self.usbMgr.getDeviceList() but couldn't. I only get <java.util.HashMap at 0xdf8a6150 jclass=java/util/HashMap jself=<LocalRef obj=0x10134a at 0xdfa69760&gt>>

UPDATE #3: I found a method to return the plugged-in USB devices' names.

values = self.usb_mgr.getDeviceList().values() #returns Collection
valuesArray = values.toArray() #returns list in python
deviceName = valuesArray[0].getDeviceName() #[0] for testing
self.device = str(deviceName)

That worked. I currently do not have the USB sensor with me and I'm unsure whether pySerial works properly on Android but that'll get tested on Monday.

Deniz
  • 21
  • 1
  • 5

1 Answers1

0

So, I found a workaround which is a bit ugly but it works for me.

I tried to write a piece of file myself but I couldn't, so I searched internet a bit more and found:

https://github.com/frmdstryr/kivy-android-serial

By using this library, I could connect to my device and communicate it.

So the salvation was there all along, unseen by me though.

The code I've given:

values = self.usb_mgr.getDeviceList().values() valuesArray = values.toArray() #returns list in python deviceName = valuesArray[0].getDeviceName() self.device = str(deviceName)

works (in an ugly way as I am a Java newbie) to get the device's name.

I realised that pySerial could not connect to the device via its own port code as in a non-rooted device you simply cannot access or alter /dev or its subdirectories.

Deniz
  • 21
  • 1
  • 5
  • How did you connect USB device using Kivy-andorid-serial? I am confused with "Add device_filter.xml to your android res/xml/ folder." Can you please suggest steps to use Kivy-android-serial. – Prayag Sep 02 '18 at 03:07
  • I also want to use kivy-android-serial and faced the same problem as Prayag. Where to put device_filter.xml? I tried in ~/.buildozer/android/platform/android-sdk-20/platforms/android-19/data/res/xml and also ~/.buildozer/android/platform/android-sdk-20/platforms/android-24/data/res/xml because I have both directories but I have always the error message : "Error: No resource found that matches the given name (at 'resource' with value '@xml/device_filter')" – Yves Surrel Nov 14 '18 at 22:00
  • The answer: after a first unsuccessful build: In dir /.buildozer/android/platform/build/dists/YOUR_PROJECT_NAME/src/main Add "xml/device_filter.xml" in "res" folder. Note that you need to create "xml" folder manually. In dir .buildozer/android/platform/build/dists/YOUR_PROJECT_NAME/templates/ Add at a good position in the file named AndroidManifest.tmpl.xml – Yves Surrel Nov 16 '18 at 14:37
  • Sorry for very late response, this was an internship project of mine and if I remember correctly I created the xml folder myself, just as Yves mentioned. Thanks :) – Deniz Jan 17 '19 at 21:25