使用JNI将字符串从java传递到c++
Passing strings from java to c++ using JNI
我有一个android应用程序,可以接收未读Facebook通知和收件箱。应用程序必须在QT中完成,但我几乎不知道QT c++,所以我在java中开发应用程序,只是使用JNI从QT调用java类。这是工作正常,但事情是我需要发送一个插槽(在QT方面),每次有一个新的Facebook通知/消息。
所以我的问题是:每分钟,我如何通知QT从Java,我有一个新的消息和发送字符串?
这是我的java代码:主类:
public class MainActivity extends FragmentActivity {
...
static public void startFacebookActivity() {
String msgTag = "FACEBOOK_APP";
try {
Activity mother = QtNative.activity();
Intent intent = new Intent(mother, MainActivity.class);
mother.startActivity(intent);
} catch (Exception e) {
Log.e(msgTag, e.toString());
e.printStackTrace();
}
}
}
FRAGMENT CLASS(每分钟验证是否有新的facebook消息,如果有,应该通知QT并发送消息,以便QT能够发送一个插槽)
private static native void publishNotification(String notification);
....
if (newNotification==true)
publishNotification(responseNotification);
...
QT侧
facebookAndroid.cpp
#include "facebookAndroid.h"
#include <QtAndroidExtras>
FacebookAndroid* FacebookAndroid::s_instance = 0;
FacebookAndroid::FacebookAndroid(QObject *parent) : QObject(parent) { s_instance = this;}
void FacebookAndroid::startAndroidFacebook() {
QAndroidJniObject::callStaticMethod<void>("org.qtproject.example.MainActivity",
"startFacebookActivity",
"()V");
}
FacebookAndroid* FacebookAndroid::instance() {
return s_instance;
}
static void publishNotification(JNIEnv *env, jclass /*clazz*/, jstring notification) {
const char* nativeString = env->GetStringUTFChars(notification, 0);
FacebookAndroid::instance()->handleNewNotification(QString(nativeString));
}
static JNINativeMethod methods[] = {
{"publishNotification", "(Ljava/lang/String;)V", (void *)publishNotification}
};
jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK)
return JNI_FALSE;
jclass clazz = env->FindClass("org/qtproject/example/MainActivity");
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0)
return JNI_FALSE;
return JNI_VERSION_1_4;
}
main.cpp
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QtQuick>
#include "facebookAndroid.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
FacebookAndroid sa(&viewer);
viewer.rootContext()->setContextProperty(QString("iniciaFacebook"), &sa);
viewer.setMainQmlFile(QStringLiteral("qml/FacebookTry/main.qml"));
viewer.showExpanded();
return app.exec();
}
facebookAndroid.h
#ifndef FACEBOOKANDROID_H
#define FACEBOOKANDROID_H
#include <QObject>
#include <jni.h>
class FacebookAndroid : public QObject {
Q_OBJECT
public:
FacebookAndroid(QObject *parent = 0);
FacebookAndroid* instance();
void handleNewNotification(QString notification);
protected:
static FacebookAndroid *s_instance;
public slots:
void startAndroidFacebook();
};
#endif // FACEBOOKANDROID_H
In function 'void publisNotification(JNIEnv*, jclass,jstring)'
cannot call member function 'FacebookAnddroid::instance()' without object
FacebookAndroid::instance()->handleNewNotification(QString(nativeString));
in facebookAndroid.cpp
每个帮助都会很有帮助
如果我必须这样做,我可能会选择以下路径:
- 定义一个本地Java方法。它将被用作来自Java端的"信号"为你的原生方法实现一个c++实现。操作要发布的实例(槽所有者)
- 注册本地方法
在你的Java类中:
class Main Activity {
// ...
private static native void publishNotification(String notification);
// Call it from your Java code as it has a proper implementation
//...
if (newNotification) {
publishNotification(notification);
}
//...
在c++/Qt端:
单例实现:
//in facebookandroid.h
class FacebookAndroid {
public:
FacebookAndroid* instance();
void handleNewNotification(QString notification);
protected:
static FacebookAndroid *s_instance;
};
//in facebookandroid.cpp
FacebookAndroid* FacebookAndroid::s_instance = 0;
FacebookAndroid::FacebookAndroid(QObject *parent) : QObject(parent) {
s_instance = this; // remind your first instanciation here
}
FacebookAndroid* FacebookAndroid::instance() {
return s_instance;
}
本地方法实现:
//In facebookandroid.cpp
static void publishNotifcation(JNIEnv *env, jclass /*clazz*/, jstring notification) {
const char* nativeString = env->GetStringUTFChars(notification, 0);
FacebookAndroid::instance()->handleNewNotification(QString(nativeString));
}
由于我们只能通过静态方法来做到这一点,我必须在我的类中定义一个单例,以特定地只访问一个实例。
注册方法:
//In facebookandroid.cpp
static JNINativeMethod methods[] = {
{"publishNotification", "(Ljava/lang/String;)V", (void *)publishNotification}
};
jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK)
return JNI_FALSE;
jclass clazz = env->FindClass("org/qtproject/example/MainActivity");
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0)
return JNI_FALSE;
return JNI_VERSION_1_4;
}
经过一番研究,我发现了一个特别有用和完整的例子。它的目的是实现InApp购买,但其机制与我在这个答案中描述的完全相同。
既然你在Java中定期检查通知,你是否有可能从Qt/c++中定期调用Java类,然后接收数据?这可以很容易地完成使用QTimer,我看到你已经实现了java类从Qt的调用。
我认为RegisterNatives是这里的关键:
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html wp17734
static void sendToQT(JNIEnv *env, jclass clazz, jstring notification) {
const char *GotInQTTheNotification = (*env)->GetStringUTFChars(env, notification, NULL);
printf("Hello %sn", GotInQTTheNotification );
(*env)->ReleaseStringUTFChars(env, notification, GotInQTTheNotification );
}
}
static JNINativeMethod method_table[] = {
{ "sendToQT", "(Ljava/lang/String;I)V", (void *) sendToQT }
};
int main(int argc, char *argv[])
{
JavaVM *vm;
JNIEnv *env;
/*
* more of code
*/
jclass clazz = (*env)->FindClass(env, "org/qtproject/example/MainActivity");
jint ret = (*env)->RegisterNatives(env, clazz, method_table, method_table_size);
vm->DestroyJavaVM();
return 0;
}
在mainactivity .java中包含一个本机声明。
public static void native sendToQT(String notification);
- 在java中解决这段代码时面临循环中的问题
- 尝试用java代码编译和运行c++代码
- 在这种情况下,java对象是否可以调用本机函数
- 在java中读取c++字节的位字段
- 为什么C++对链表中的下一个节点使用指针,而像 C# 或 Java 这样的语言只使用类 Node 的名称?
- 使用已使用 java 编码的 openssl 解码数据
- SWIG Java 在使用 -DSWIGWORDSIZE64 时将int64_t转换为 jlong
- Android Java USB for native cpp
- 在由Sublime文本3编译后在cmd上显示Java程序输出
- C++ equivalent to Java Map getOrDefault?
- C++ 中的 Java 样式枚举
- 是否有技术原因阻止 Java 中的 final C++ 像 const 一样严格?
- 加密在 Windows、C++ 和 Java 中传输中的数据
- Java从C++回调到C++回调
- 在 c++ 中模拟输入并在 JAVA 中读取它?
- 用C++包装 Java 库 (JNI)
- 使用 TreeSet Java 对反转进行计数
- 验证openssl c++中的签名,这是由JAVA DSA签名的?
- 如何通过 JNI 将 C 字符串表情符号传递给 Java
- 如何从保存在 Java 中C++的字节数组中读取数字?