Jnius Android蓝牙低能量

2024-06-08 15:59:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个Android应用程序,它可以与一个可编程服务器进行通信。我正在用python编写它(使用kivy和buildozer),为了访问android java类,我使用pyjnius

到目前为止,我已经能够获得配对的BT设备,并检查它们的地址是否与我需要的地址匹配。但是,当我尝试调用“connectGatt()”方法时,我得到了一个错误

此方法需要一个作为参数传递的'BluetoothGattCallback'对象来处理所有事件,如'onConnectionStateChange()'。 在网上查看之后,我发现有人编写了这个类的一个实现,它应该与pyjnius一起工作

但是,在查看并遵循有关如何实现它的说明后,我发现以下错误: jnius.jnius.JavaException:没有与参数匹配的方法,可用:['(Landroid/content/Context;ZLandroid/BluetoothGattCallback;)Landroid/bluetooth/BluetoothGatt;',','(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;I)Landroid/bluetooth/BluetoothGatt;','(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;II)Landroid/bluetooth/BluetoothGatt;',','(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;IILandroid/bluetooth/BluetoothGattCallback;)Landroid/bluetooth/BluetoothGatt;',','(Landroid/content/Context;ZLandroid/BluetoothGattCallback/os/Handler;)Landroid/bluetooth/BluetoothGatt;']

下面是Java文件('BluetoothGattImplem.Java'):


    package org.test;
    
    import android.bluetooth.BluetoothGatt;
    import android.bluetooth.BluetoothGattCallback;
    import android.bluetooth.BluetoothGattCharacteristic;
    import android.bluetooth.BluetoothProfile;
    import android.bluetooth.BluetoothGattService;
    import android.util.Log;
    
    public class BluetoothGattImplem extends BluetoothGattCallback {
    
          public interface OnBluetoothGattCallback {
           // ... all the methods from BluetoothGattCallback here ...like:
             void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
    
             void onConnectionStateChange(BluetoothGatt gatt, int status, int newState);
    
             void onServicesDiscovered(BluetoothGatt gatt, int status);
    
             void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status);
          
        }
        // private storage for the callback object
        private OnBluetoothGattCallback callback = null;
    
        // method to set the callback object
        public void setCallback(OnBluetoothGattCallback callback) {
            this.callback = callback;
        }
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            if (this.callback != null)
                this.callback.onCharacteristicChanged(gatt, characteristic); 
        }
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (this.callback != null)
                this.callback.onConnectionStateChange(gatt, status, newState); 
        }
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (this.callback != null)
                this.callback.onServicesDiscovered(gatt, status); 
        }
        public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {
            if (this.callback != null)
                this.callback.onCharacteristicRead(gatt,characteristic,status); 
        }
    }

下面是我在'main.py'中代码的实现:


    from jnius import *
    
    PythonActivity = autoclass("org.kivy.android.PythonActivity")
    Context = cast("android.content.Context", PythonActivity.mActivity)
    JBoolean = autoclass("java.lang.Boolean")
    UUID = autoclass("java.util.UUID")
    BluetoothDevice = autoclass("android.bluetooth.BluetoothDevice")
    BluetoothAdapter = autoclass("android.bluetooth.BluetoothAdapter")
    BluetoothGATT = autoclass("android.bluetooth.BluetoothGatt")
    BluetoothGATTCallback = autoclass("android.bluetooth.BluetoothGattCallback")
    BluetoothGATTService = autoclass("android.bluetooth.BluetoothGattService")
    BluetoothGATTCharacteristic = autoclass("android.bluetooth.BluetoothGattCharacteristic")
    BluetoothGATTImplement = autoclass("org.test.BluetoothGattImplem")
    
    from android.permissions import request_permissions, Permission
    import android  
    
    def permissionCallback(permission, result):
        pass
    
    request_permissions([Permission.BLUETOOTH, Permission.BLUETOOTH_ADMIN], permissionCallback)
    
    class BLECallback(PythonJavaClass):
        __javainterfaces__ = ["org/test/BluetoothGattImplem$OnBluetoothGattCallback"]
        __javacontext__ = "app"
    
        @java_method("(Landroid/bluetooth/BluetoothGatt;II)V")
        def onConnectionStateChange(self, gatt, status, newstate):
            pass
    
        @java_method("(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V")
        def onCharacteristicRead(self, gatt, characteristic, state):
            pass
    
    pycallback = BLECallback()
    bg = BluetoothGATTImplement()
    bg.setCallback(pycallback)
    
    DEVICE_ADDRESS = "12:34:56:78"
    bl_adapter = BluetoothAdapter.getDefaultAdapter()
    
    def bluetoothConnect():
            res = bl_adapter.getState()
            if res != BluetoothAdapter.STATE_ON:
                return
            else:
                bl_devices = bl_adapter.getBondedDevices().toArray()
                for device in bl_devices:
                    if device.getAddress() == DEVICE_ADDRESS:
                        ### This is the line of code in which I get the error ###
                        bl_connection = device.connectGatt(Context, JBoolean(False), bg)
                        ###

最后是“buildozer.spec”


    [app]
    
    # (str) Source code where the main.py live
    source.dir = .
    
    # (list) Source files to include (let empty to include all the files)
    source.include_exts = py,png,jpg,kv,atlas
    
    # (list) Application requirements
    # comma separated e.g. requirements = sqlite3,kivy
    requirements = python3,kivy,pyjnius
    
    # (list) List of service to declare
    #services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
    
    #
    # Android specific
    #
    
    # (list) Permissions
    #android.permissions = INTERNET
    android.permissions = BLUETOOTH, BLUETOOTH_ADMIN, ACCES_FINE_LOCATION, ACCES_BACKGROUND_LOCATION
    
    # (list) List of Java files to add to the android project (can be java or a
    # directory containing the files)
    android.add_src = java/
    
    # (list) add java compile options
    # this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option
    # see https://developer.android.com/studio/write/java8-support for further information
    # android.add_compile_options = "sourceCompatibility = 1.8", "targetCompatibility = 1.8"
    
    # (list) Java classes to add as activities to the manifest.
    #android.add_activities = com.example.ExampleActivity
    
    # (list) Android library project to add (will be added in the
    # project.properties automatically.)
    #android.library_references =
    
    # (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
    android.arch = armeabi-v7a

由于我不太了解Java,因此也不太了解它的,我还将写下我的目录结构:

    App/
    ├─ bin/
    ├─ java/
    │  ├─ org/
    │  │  ├─ test/
    │  │  │  ├─ BluetoothGattImplem.java
    │  │  │  ├─ MyBluetoothCallback.java
    ├─ buildozer.spec
    ├─ main.py

我已经为此挣扎了几天了,我想用这个应用程序实现的唯一一件事就是连接到一个BLE设备,并写入(也可能读取)它的特性

非常感谢您的帮助,谢谢

编辑: 根据我的要求,我将代码精简到我认为最简单的程度

我还尝试创建一个新的.java文件,该文件包含一个具有单个属性的类:BluetoothGattCallback对象。如果我打印传递的connectGatt()参数,它们将返回正确的对象,但仍然会出现类似的错误:

jnius.jnius.JavaException:没有与参数匹配的方法,请求:(<;android.content.Context在0xd2629820 jclass=android/content/Context jself=<;LocalRef obj=0x77ca在0xb8424710>;,<;java.lang.Boolean在0xb84966b8 jclass=java/lang/Boolean jself=<;LocalRef obj=0x753a在0xd380fa90>;,<;android.bluetooth.BluetoothGattCallback在0xb7d882d0 jclass=android/bluetooth/bluetoothgatcallback jse;)lf=<;LocalRef obj=0x7646在0xb8424cf0处>;),可用:['(Landroid/content/Context;ZLandroid/BluetoothGattCallback;)Landroid/BluetoothGatt;','(Landroid/content/Context;ZLandroid/BluetoothGattCallback;I)Landroid/bluetooth/BluetoothGattCallback;','(Landroid/content/Context;ZLandroid/BluetoothGattCallback;II)Landroid/bluetooth/BluetoothGatt;','(Landroid/content/Context;ZLandroid/BluetoothGattCallback;ilandroid/os/Handler;)Landroid/bluetooth/BluetoothGatt;','(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;IZILandroid/bluetooth/os/Handler;)Landroid/BluetoothGatt;']

如您所见,其中显示的request,这些是我传递的参数,它们与available列表中的第一个方法匹配,但应用程序仍然会因此错误而崩溃


Tags: thetostatuscontextcallbackjavacontentgatt