蓝牙与 Android 上的 Qt。通过抽象类上的jni调用java类

Posted

技术标签:

【中文标题】蓝牙与 Android 上的 Qt。通过抽象类上的jni调用java类【英文标题】:Bluetooth with Qt on Android. Calling java classes through jni on abstract class 【发布时间】:2014-01-02 02:10:40 【问题描述】:

here 可能重复,但接受的答案很短,没有多大帮助。

我正在使用适用于 android 的 Qt 5.2。我想使用 Qt 框架目前不直接支持的我的 android 设备蓝牙功能。因此我开始使用 JNI 来访问 Android Java 类和方法。

我可以通过这样做来创建 AudioTimestamp 类的对象:

QAndroidJniObject audioTimestamp2("android/media/AudioTimestamp");

if(!audioTimestamp2.isValid())

    qDebug() << "audioTimestamp2 is not a valid object";
    return false;

第一行调用了默认构造函数,所以它工作正常。这只是一个测试,看看我是否能够创建一个有效的对象。

当我从 developer.android.com 开始使用蓝牙实现时,我需要通过以下方式获取设备的蓝牙适配器:

BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

所以我尝试这样做:

//Create Java string used to obtain bluetooth adapter.
QAndroidJniObject systemService = QAndroidJniObject::fromString("BLUETOOTH_SERVICE");

//Create Context Object.
QAndroidJniObject context("android/content/Context");

if(!context.isValid())

    qDebug() << "context is not a valid object";
    return false;


//Call getSystemService method on context object and return manager object.
QAndroidJniObject bluetoothManager = context.callObjectMethod("getSystemService", "(Ljava/lang/String;)Landroid/bluetooth/BluetoothManager;", systemService.object<jstring>());

if(!bluetoothManager.isValid())

    qDebug() << "bluetoothManager is not a valid object";
    return false;


//Call getAdapter() on manager.
QAndroidJniObject bluetoothAdapter = bluetoothManager.callObjectMethod("getAdapter", "()Landroid/bluetooth/BluetoothAdapter;");

//More code

if (!bluetoothAdapter.callMethod<jboolean>("isEnabled"))

    qDebug() << "Bluetooth is off";

    //Code to ask user to turn bluetooth on here...

我很快发现“getSystemService(Context.BLUETOOTH_SERVICE)”似乎是突然被调用的。它属于抽象类Context.java。如何在抽象类上使用 Qt JNI 调用来获取 bluetoothManager?

编辑:

我也试过这样做:

QAndroidJniObject context("android/app/Service");

但仍然得到:

D/Qt      (22736): ..\AndroidTest\bluetooth.cpp:33 (bool Bluetooth::start()): context is not a valid object 

【问题讨论】:

看起来像是要报告的错误? @LaszloPapp:不确定是不是。我怀疑您必须在 Java 程序中调用这种代码才能获得正确的上下文?这是在我在问题顶部提供的链接中完成的。我认为您可以使用 registerNatives() 方法将上下文从 Java 发送到 C++。我更倾向于认为这是缺乏功能而不是错误。 【参考方案1】:

getSystemService() 是android.content.Context 的一个方法。我认为您会得到“上下文不是有效对象”,因为它是一个无法以这种方式实例化的抽象类。 android.app.Service 也是如此。

“发现“getSystemService(Context.BLUETOOTH_SERVICE)”似乎被突然调用了” - 在您来自 developer.android.com 的示例中,它是在 this 上调用的,这可能是从 Activity 派生的类,因此是 Context。

您需要一个上下文对象来调用 getSystemService()。

此外,您似乎正在调用具有错误签名的对象方法:“(Ljava/lang/String;)Ljava/lang/Object;”

【讨论】:

是的,我需要一个上下文对象才能调用 getSystemService(),但那是行不通的。我通过编写一些可调用的 java 代码暂时解决了这个问题。【参考方案2】:

仅对于可能最终在这里的其他人,您可以使用

获取主要上下文
QtAndroid::androidActivity()

这就是你在你的情况下使用它的方式:

// from https://developer.android.com/reference/android/content/Context.html#BLUETOOTH_SERVICE    
// note that the actual string value is "bluetooth" not "BLUETOOTH_SERVICE", Context.BLUETOOTH_SERVICE is a constant that holds "bluetooth" string value
QAndroidJniObject service_name = QAndroidJniObject::fromString("bluetooth");     

// this is your context
QAndroidJniObject activity = QtAndroid::androidActivity(); 

// now you get your bluetooth manager
QAndroidJniObject bluetoothManager = activity.callObjectMethod("getSystemService","(Ljava/lang/String;)Ljava/lang/Object;", service_name.object<jstring>()); 

【讨论】:

以上是关于蓝牙与 Android 上的 Qt。通过抽象类上的jni调用java类的主要内容,如果未能解决你的问题,请参考以下文章

抽象类上的 Json.reads(不支持密封特征:没有已知的子类)

通过蓝牙将 Android 应用程序连接到 Mac OS X 上的 Python 脚本

无法连接到android上的蓝牙套接字

如何将 Android 应用程序正确连接到支持蓝牙的 Arduino 微控制器上的 RFCOMM 插座?

在Android上的蓝牙中从InputStream读取数据时出错

如何在 Cordova 应用程序中使用 iPhone 上的蓝牙?