aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergio Ahumada <sergio.ahumada@digia.com>2013-11-08 18:06:39 +0100
committerSergio Ahumada <sergio.ahumada@digia.com>2013-11-08 18:06:39 +0100
commit23da3a7856bb3810fcc135fe4062da810af89f57 (patch)
tree4f55aced1093cfcfc87a8f7d2bda8675fa49b209
parent467e7b9f4f7d723ead59eaf835cb741c091ed837 (diff)
parentabdb38773693745f5d2f8319b470bfbe0373cc1f (diff)
Merge remote-tracking branch 'origin/stable' into dev
-rw-r--r--src/androidextras/androidextras.pro3
-rw-r--r--src/androidextras/doc/qtandroidextras.qdocconf10
-rw-r--r--src/androidextras/doc/snippets/code/src_androidextras_qandroidjniobject.cpp53
-rw-r--r--src/androidextras/doc/src/qtandroidextras-examples.qdoc36
-rw-r--r--src/androidextras/doc/src/qtandroidextras-index.qdoc9
-rw-r--r--src/androidextras/doc/src/qtandroidextras-module.qdoc3
-rw-r--r--src/androidextras/jni/qandroidjniobject.cpp223
-rw-r--r--tests/auto/qandroidjnienvironment/qandroidjnienvironment.pro2
-rw-r--r--tests/auto/qandroidjnienvironment/tst_qandroidjnienvironment.cpp25
-rw-r--r--tests/auto/qandroidjniobject/tst_qandroidjniobject.cpp32
10 files changed, 294 insertions, 102 deletions
diff --git a/src/androidextras/androidextras.pro b/src/androidextras/androidextras.pro
index f3caeea..24d4371 100644
--- a/src/androidextras/androidextras.pro
+++ b/src/androidextras/androidextras.pro
@@ -1,6 +1,7 @@
TARGET = QtAndroidExtras
DEFINES += QT_NO_USING_NAMESPACE
-QMAKE_DOCS = $$PWD/doc/qtandroidextras.qdocconf
+QMAKE_DOCS = \
+ $$PWD/doc/qtandroidextras.qdocconf
QT -= gui
QT += core-private
load(qt_module)
diff --git a/src/androidextras/doc/qtandroidextras.qdocconf b/src/androidextras/doc/qtandroidextras.qdocconf
index c69586c..16ed611 100644
--- a/src/androidextras/doc/qtandroidextras.qdocconf
+++ b/src/androidextras/doc/qtandroidextras.qdocconf
@@ -2,7 +2,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtAndroidExtras
description = Qt Android Extras Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER/qtandroidextras
+url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = qtandroidextras
@@ -24,18 +24,16 @@ qhp.QtAndroidExtras.subprojects.classes.title = C++ Classes
qhp.QtAndroidExtras.subprojects.classes.indexTitle = Qt Android Extras C++ Classes
qhp.QtAndroidExtras.subprojects.classes.selectors = class fake:headerfile
qhp.QtAndroidExtras.subprojects.classes.sortPages = true
-
-tagfile = ../../../doc/qtandroidextras/qtandroidextras.tags
+qhp.QtAndroidExtras.subprojects.examples.title = Examples
+qhp.QtAndroidExtras.subprojects.examples.indexTitle = Qt Android Extras Examples
+qhp.QtAndroidExtras.subprojects.examples.selectors = fake:example
depends += qtcore qtdoc
-
headerdirs += ..
sourcedirs += ..
exampledirs += ../../../examples/androidextras \
- ../ \
snippets
-excludedirs += ../../../examples/widgets/doc
imagedirs += images
navigation.landingpage = "Qt Android Extras"
navigation.cppclassespage = "Qt Android Extras C++ Classes"
diff --git a/src/androidextras/doc/snippets/code/src_androidextras_qandroidjniobject.cpp b/src/androidextras/doc/snippets/code/src_androidextras_qandroidjniobject.cpp
index 899ca74..6f545fb 100644
--- a/src/androidextras/doc/snippets/code/src_androidextras_qandroidjniobject.cpp
+++ b/src/androidextras/doc/snippets/code/src_androidextras_qandroidjniobject.cpp
@@ -81,3 +81,56 @@ void function()
}
}
//! [Check for exceptions]
+
+//! [Registering native methods]
+static void fromJavaOne(JNIEnv *env, jobject thiz, jint x)
+{
+ Q_UNUSED(env)
+ Q_UNUSED(thiz)
+ qDebug() << x << "< 100";
+}
+
+static void fromJavaTwo(JNIEnv *env, jobject thiz, jint x)
+{
+ Q_UNUSED(env)
+ Q_UNUSED(thiz)
+ qDebug() << x << ">= 100";
+}
+
+void registerNativeMethods() {
+ JNINativeMethod methods[] {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
+ {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
+
+ QAndroidJniObject javaClass("my/java/project/FooJavaClass");
+ QAndroidJniEnvironment env;
+ jclass objectClass = env->GetObjectClass(javaClass)
+ env->RegisterNatives(objectClass,
+ methods,
+ sizeof(methods) / sizeof(methods[0]));
+ env->DeleteLocalRef(objectClass);
+}
+
+void foo()
+{
+ QAndroidJniObject::callStaticMethod("my/java/project/FooJavaClass", "foo", "(I)V", 10); // Output: 10 < 100
+ QAndroidJniObject::callStaticMethod("my/java/project/FooJavaClass", "foo", "(I)V", 100); // Output: 100 >= 100
+}
+
+//! [Registering native methods]
+
+//! [Java native methods]
+class FooJavaClass
+{
+ public static void foo(int x)
+ {
+ if (x < 100)
+ callNativeOne(x);
+ else
+ callNativeTwo(x);
+ }
+
+private static native void callNativeOne(int x);
+private static native void callNativeTwo(int x);
+
+}
+//! [Java native methods]
diff --git a/src/androidextras/doc/src/qtandroidextras-examples.qdoc b/src/androidextras/doc/src/qtandroidextras-examples.qdoc
new file mode 100644
index 0000000..725641e
--- /dev/null
+++ b/src/androidextras/doc/src/qtandroidextras-examples.qdoc
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/*!
+ \group examples-qtandroidextras
+ \title Qt Android Extras Examples
+ \brief Examples in the Qt Android Extras module.
+ \ingroup all-examples
+
+ These are the examples available in the \l{Qt Android Extras} module.
+
+ \note These examples will only work on Android.
+*/
diff --git a/src/androidextras/doc/src/qtandroidextras-index.qdoc b/src/androidextras/doc/src/qtandroidextras-index.qdoc
index cf7d3df..74ca249 100644
--- a/src/androidextras/doc/src/qtandroidextras-index.qdoc
+++ b/src/androidextras/doc/src/qtandroidextras-index.qdoc
@@ -40,8 +40,7 @@
#include <QtAndroidExtras>
\endcode
- To link against the module, add this line to your \l qmake \c
- .pro file:
+ To link against the Qt Android Extras module, add this line to your project file:
\code
QT += androidextras
@@ -53,4 +52,10 @@
\list
\li \l{Qt Android Extras C++ Classes}{C++ Classes}
\endlist
+
+ \section1 Examples
+
+ \list
+ \li \l{Qt Android Extras Examples}
+ \endlist
*/
diff --git a/src/androidextras/doc/src/qtandroidextras-module.qdoc b/src/androidextras/doc/src/qtandroidextras-module.qdoc
index badb8a7..8a5eccb 100644
--- a/src/androidextras/doc/src/qtandroidextras-module.qdoc
+++ b/src/androidextras/doc/src/qtandroidextras-module.qdoc
@@ -40,8 +40,7 @@
#include <QtAndroidExtras>
\endcode
- To link against the module, add this line to your \l qmake \c
- .pro file:
+ To link against the Qt Android Extras module, add this line to your project file:
\code
QT += androidextras
diff --git a/src/androidextras/jni/qandroidjniobject.cpp b/src/androidextras/jni/qandroidjniobject.cpp
index 79740e3..1057650 100644
--- a/src/androidextras/jni/qandroidjniobject.cpp
+++ b/src/androidextras/jni/qandroidjniobject.cpp
@@ -48,55 +48,193 @@ QT_BEGIN_NAMESPACE
/*!
\class QAndroidJniObject
\inmodule QtAndroidExtras
- \brief The QAndroidJniObject is a C++ wrapper around a Java class.
+ \brief Provides APIs to call Java code from C++.
\since 5.2
- QAndroidJniObject provides APIs to call Java methods
+ \sa QAndroidJniEnvironment
- \section1 JNI types
+ \section1 General Notes
- Object types:
\list
- \li jobject
- \li jclass
- \li jstring
- \li jarray
- \li jobjectArray
- \li jbooleanArray
- \li jbyteArray
- \li jcharArray
- \li jshortArray
- \li jintArray
- \li jlongArray
- \li jfloatArray
- \li jdoubleArray
+ \li Class names needs to contain the fully-qualified class name, for example: \b"java/lang/String".
+ \li Method signatures are written as \b"(Arguments)ReturnType"
+ \li All object types are returned as a QAndroidJniObject.
\endlist
- Primitive types:
- \list
- \li jboolean
- \li jbyte
- \li jchar
- \li jshort
- \li jint
- \li jlong
- \li jfloat
- \li jdouble
- \endlist
+ \section1 Method Signatures
+
+ For functions that take no arguments, QAndroidJniObject provides convenience functions that will use
+ the correct signature based on the provided template type. For example:
+
+ \code
+ jint x = QAndroidJniObject::callMethod<jint>("getSize");
+ QAndroidJniObject::callMethod<void>("touch");
+ \endcode
+
+ In other cases you will need to supply the signature yourself, and it is important that the
+ signature matches the function you want to call. The signature structure is \b \(A\)R, where \b A
+ is the type of the argument\(s\) and \b R is the return type. Array types in the signature must
+ have the \b\[ suffix and the fully-qualified type names must have the \b L prefix and \b ; suffix.
+
+ The example below demonstrates how to call two different static functions.
+ \code
+ // Java class
+ package org.qtproject.qt5;
+ class TestClass
+ {
+ static String fromNumber(int x) { ... }
+ static String[] stringArray(String s1, String s2) { ... }
+ }
+ \endcode
+
+ The signature for the first function is \b"\(I\)Ljava/lang/String;"
+
+ \code
+ // C++ code
+ QAndroidJniObject stringNumber = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/TestClass",
+ "fromNumber"
+ "(I)Ljava/lang/String;",
+ 10);
+ \endcode
- \section1 General Notes:
+ and the signature for the second function is \b"\(Ljava/lang/String;Ljava/lang/String;\)\[Ljava/lang/String;"
+
+ \code
+ // C++ code
+ QAndroidJniObject string1 = QAndroidJniObject::fromString("String1");
+ QAndroidJniObject string2 = QAndroidJniObject::fromString("String2");
+ QAndroidJniObject stringArray = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/TestClass",
+ "stringArray"
+ "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"
+ string1.object<jstring>(),
+ string2.object<jstring>());
+ \endcode
- - Class name strings needs to be the fully-qualified class name, for example: "java/lang/String".
- - Method signatures are written as "(Arguments)ReturnType"
- - All object types are returned as a QAndroidJniObject.
- \section1 Handling Java exception:
+ \section1 Handling Java Exception
- When calling Java functions that might throw an exception, it is important that you handle and
- clear out the exception before continuing.
+ When calling Java functions that might throw an exception, it is important that you check, handle
+ and clear out the exception before continuing.
+
+ \note It is unsafe to make a JNI call when there are exceptions pending.
\snippet code/src_androidextras_qandroidjniobject.cpp Check for exceptions
+ \section1 Java Native Methods
+
+ Java native methods makes it possible to call native code from Java, this is done by creating a
+ function declaration in Java and prefixing it with the \b native keyword.
+ Before a native function can be called from Java, you need to map the Java native function to a
+ native function in your code. Mapping functions can be done by calling the RegisterNatives() function
+ through the \l{QAndroidJniEnvironment}{JNI environment pointer}.
+
+ The example below demonstrates how this could be done.
+
+ Java implementation:
+ \snippet code/src_androidextras_qandroidjniobject.cpp Java native methods
+
+ C++ Implementation:
+ \snippet code/src_androidextras_qandroidjniobject.cpp Registering native methods
+
+ \section1 The Lifetime of a Java Object
+
+ Most \l{Object types}{objects} received from Java will be local references and will only stay valid
+ in the scope you received them. After that, the object becomes eligible for garbage collection. If you
+ want to keep a Java object alive you need to either create a new global reference to the object and
+ release it when you are done, or construct a new QAndroidJniObject and let it manage the lifetime of the Java object.
+ \sa object()
+
+ \note The QAndroidJniObject does only manage its own references, if you construct a QAndroidJniObject from a
+ global or local reference that reference will not be released by the QAndroidJniObject.
+
+ \section1 JNI Types
+
+ \section2 Object Types
+ \table
+ \header
+ \li Type
+ \li Signature
+ \row
+ \li jobject
+ \li {1, 3} L\e<fully-qulified-name>};
+ \row
+ \li jclass
+ \row
+ \li jstring
+ \row
+ \li jobjectArray
+ \li [L\e<fully-qulified-name>;
+ \row
+ \li jarray
+ \li [\e<type>
+ \row
+ \li jbooleanArray
+ \li [Z
+ \row
+ \li jbyteArray
+ \li [B
+ \row
+ \li jcharArray
+ \li [C
+ \row
+ \li jshortArray
+ \li [S
+ \row
+ \li jintArray
+ \li [I
+ \row
+ \li jlongArray
+ \li [J
+ \row
+ \li jfloatArray
+ \li [F
+ \row
+ \li jdoubleArray
+ \li [D
+ \endtable
+
+
+ \section2 Primitive Types
+ \table
+ \header
+ \li Type
+ \li Signature
+ \row
+ \li jboolean
+ \li Z
+ \row
+ \li jbyte
+ \li B
+ \row
+ \li jchar
+ \li C
+ \row
+ \li jshort
+ \li S
+ \row
+ \li jint
+ \li I
+ \row
+ \li jlong
+ \li J
+ \row
+ \li jfloat
+ \li F
+ \row
+ \li jdouble
+ \li D
+ \endtable
+
+ \section3 Other
+ \table
+ \header
+ \li Type
+ \li Signature
+ \row
+ \li void
+ \li V
+ \endtable
+
For more information about JNI see: \l http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html
*/
@@ -192,7 +330,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn T QAndroidJniObject::callMethod(const char *methodName) const
- Calls the method \a methodName and returs the value.
+ Calls the method \a methodName and returns the value.
\code
QAndroidJniObject myJavaString = ...;
@@ -228,7 +366,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn T QAndroidJniObject::callStaticMethod(jclass clazz, const char *methodName)
- Calls the static method \a methodName on \a clazz and returns the value T.
+ Calls the static method \a methodName on \a clazz and returns the value.
\code
...
@@ -265,8 +403,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn T QAndroidJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...)
- Calls the static method \a methodName with \a signature on \a clazz and returns the value T,
- unless T is void.
+ Calls the static method \a methodName with \a signature on \a clazz and returns the value.
\code
...
@@ -453,15 +590,15 @@ QT_BEGIN_NAMESPACE
/*!
\fn T QAndroidJniObject::object() const
- Returns a jobject as type T.
+ Returns the object held by the QAndroidJniObject as type T.
\code
QAndroidJniObject string = QAndroidJniObject::fromString("Hello, JNI");
jstring jstring = string.object<jstring>();
\endcode
- Note that the jobject is still owned by the QAndroidJniObject. If you want to keep the jobject valid
- you should create a new QAndroidJniObject or make a new global reference to the jobject and
+ \note The returned object is still owned by the QAndroidJniObject. If you want to keep the object valid
+ you should create a new QAndroidJniObject or make a new global reference to the object and
free it yourself.
\snippet code/src_androidextras_qandroidjniobject.cpp QAndroidJniObject scope
@@ -477,7 +614,7 @@ QT_BEGIN_NAMESPACE
\fn QString QAndroidJniObject::toString() const
Returns a QString with a string representation of the java object.
- Calling this function on a Java String object is a convenient way of getting the actuall string
+ Calling this function on a Java String object is a convenient way of getting the actual string
data.
\code
diff --git a/tests/auto/qandroidjnienvironment/qandroidjnienvironment.pro b/tests/auto/qandroidjnienvironment/qandroidjnienvironment.pro
index 3c4fcf7..b253c17 100644
--- a/tests/auto/qandroidjnienvironment/qandroidjnienvironment.pro
+++ b/tests/auto/qandroidjnienvironment/qandroidjnienvironment.pro
@@ -1,4 +1,4 @@
CONFIG += testcase
TARGET = tst_qandroidjnienvironment
-QT += testlib androidextras
+QT += testlib androidextras core-private
SOURCES += tst_qandroidjnienvironment.cpp
diff --git a/tests/auto/qandroidjnienvironment/tst_qandroidjnienvironment.cpp b/tests/auto/qandroidjnienvironment/tst_qandroidjnienvironment.cpp
index 307e6b7..3115ae3 100644
--- a/tests/auto/qandroidjnienvironment/tst_qandroidjnienvironment.cpp
+++ b/tests/auto/qandroidjnienvironment/tst_qandroidjnienvironment.cpp
@@ -41,6 +41,7 @@
#include <QtTest/QtTest>
#include <QtAndroidExtras/QAndroidJniEnvironment>
+#include <QtCore/private/qjnihelpers_p.h>
class tst_QAndroidJniEnvironment : public QObject
{
@@ -49,23 +50,19 @@ class tst_QAndroidJniEnvironment : public QObject
private slots:
void jniEnv();
void javaVM();
-
-public:
- static JavaVM *m_javaVM;
};
-JavaVM *tst_QAndroidJniEnvironment::m_javaVM = 0;
-
void tst_QAndroidJniEnvironment::jniEnv()
{
- QVERIFY(m_javaVM);
+ JavaVM *javaVM = QtAndroidPrivate::javaVM();
+ QVERIFY(javaVM);
{
QAndroidJniEnvironment env;
// JNI environment should now be attached to the current thread
JNIEnv *jni = 0;
- QCOMPARE(m_javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_OK);
+ QCOMPARE(javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_OK);
JNIEnv *e = env;
QVERIFY(e);
@@ -84,28 +81,22 @@ void tst_QAndroidJniEnvironment::jniEnv()
// The environment should automatically be detached when QAndroidJniEnvironment goes out of scope
JNIEnv *jni = 0;
- QCOMPARE(m_javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_EDETACHED);
+ QCOMPARE(javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_EDETACHED);
}
void tst_QAndroidJniEnvironment::javaVM()
{
- QVERIFY(m_javaVM);
+ JavaVM *javaVM = QtAndroidPrivate::javaVM();
+ QVERIFY(javaVM);
QAndroidJniEnvironment env;
- QCOMPARE(env.javaVM(), m_javaVM);
+ QCOMPARE(env.javaVM(), javaVM);
JavaVM *vm = 0;
QCOMPARE(env->GetJavaVM(&vm), JNI_OK);
QCOMPARE(env.javaVM(), vm);
}
-Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
-{
- Q_UNUSED(reserved)
- tst_QAndroidJniEnvironment::m_javaVM = vm;
- return JNI_VERSION_1_6;
-}
-
QTEST_APPLESS_MAIN(tst_QAndroidJniEnvironment)
#include "tst_qandroidjnienvironment.moc"
diff --git a/tests/auto/qandroidjniobject/tst_qandroidjniobject.cpp b/tests/auto/qandroidjniobject/tst_qandroidjniobject.cpp
index 4b8f1d5..47b476a 100644
--- a/tests/auto/qandroidjniobject/tst_qandroidjniobject.cpp
+++ b/tests/auto/qandroidjniobject/tst_qandroidjniobject.cpp
@@ -97,13 +97,8 @@ private slots:
void getIntField();
void cleanupTestCase();
-
-public:
- static jclass m_activityDelegateClass;
};
-jclass tst_QAndroidJniObject::m_activityDelegateClass = 0;
-
tst_QAndroidJniObject::tst_QAndroidJniObject()
{
}
@@ -686,7 +681,7 @@ void tst_QAndroidJniObject::getBooleanField()
{
QVERIFY(m_activityDelegateClass);
- QAndroidJniObject obj(m_activityDelegateClass);
+ QAndroidJniObject obj("org/qtproject/qt5/android/QtActivityDelegate");
QVERIFY(obj.isValid());
QVERIFY(!obj.getField<jboolean>("m_fullScreen"));
@@ -694,9 +689,7 @@ void tst_QAndroidJniObject::getBooleanField()
void tst_QAndroidJniObject::getIntField()
{
- QVERIFY(m_activityDelegateClass);
-
- QAndroidJniObject obj(m_activityDelegateClass);
+ QAndroidJniObject obj("org/qtproject/qt5/android/QtActivityDelegate");
QVERIFY(obj.isValid());
jint res = obj.getField<jint>("m_currentRotation");
@@ -704,27 +697,6 @@ void tst_QAndroidJniObject::getIntField()
QCOMPARE(res, -1);
}
-Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
-{
- typedef union {
- JNIEnv *nenv;
- void *venv;
- } _JNIEnv;
-
- _JNIEnv uenv;
- uenv.venv = Q_NULLPTR;
-
- if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK)
- return JNI_ERR;
-
- JNIEnv *env = uenv.nenv;
-
- jclass clazz = env->FindClass("org/qtproject/qt5/android/QtActivityDelegate");
- tst_QAndroidJniObject::m_activityDelegateClass = (jclass)env->NewGlobalRef(clazz);
-
- return JNI_VERSION_1_6;
-}
-
QTEST_APPLESS_MAIN(tst_QAndroidJniObject)
#include "tst_qandroidjniobject.moc"