diff --git a/src/androidextras/android/android.pri b/src/androidextras/android/android.pri index 58693126028dc357a8b6dff5d200f036df1a822a..b86d380d082360e576acf1a81ea3aabff77d9734 100644 --- a/src/androidextras/android/android.pri +++ b/src/androidextras/android/android.pri @@ -1,4 +1,7 @@ SOURCES += \ - $$PWD/qandroidfunctions.cpp + $$PWD/qandroidfunctions.cpp \ + $$PWD/qandroidactivityresultreceiver.cpp HEADERS += \ - $$PWD/qandroidfunctions.h \ No newline at end of file + $$PWD/qandroidfunctions.h \ + $$PWD/qandroidactivityresultreceiver.h \ + $$PWD/qandroidactivityresultreceiver_p.h diff --git a/src/androidextras/android/qandroidactivityresultreceiver.cpp b/src/androidextras/android/qandroidactivityresultreceiver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..819d322adf7f4c732e52558d7e36dfd5a35811b8 --- /dev/null +++ b/src/androidextras/android/qandroidactivityresultreceiver.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qandroidactivityresultreceiver.h" +#include "qandroidactivityresultreceiver_p.h" +#include "qandroidfunctions.h" +#include <QtCore/private/qjnihelpers_p.h> +#include <QtCore/qmutex.h> + +QT_BEGIN_NAMESPACE + +// Get a unique activity request code. +static int uniqueActivityRequestCode() +{ + static QMutex mutex; + static int requestCode = 0x1000; // Reserve all request codes under 0x1000 for Qt. + + QMutexLocker locker(&mutex); + if (requestCode == 0xf3ee) // Special case for MINISTRO_INSTALL_REQUEST_CODE + requestCode++; + + if (requestCode == INT_MAX) + qWarning("Unique activity request code has wrapped. Unexpected behavior may occur."); + + return requestCode++; +} + +int QAndroidActivityResultReceiverPrivate::globalRequestCode(int localRequestCode) const +{ + if (!localToGlobalRequestCode.contains(localRequestCode)) { + int globalRequestCode = uniqueActivityRequestCode(); + localToGlobalRequestCode[localRequestCode] = globalRequestCode; + globalToLocalRequestCode[globalRequestCode] = localRequestCode; + } + return localToGlobalRequestCode.value(localRequestCode); +} + +bool QAndroidActivityResultReceiverPrivate::handleActivityResult(jint requestCode, jint resultCode, jobject data) +{ + if (globalToLocalRequestCode.contains(requestCode)) { + q->handleActivityResult(globalToLocalRequestCode.value(requestCode), resultCode, QAndroidJniObject(data)); + return true; + } + + return false; +} + +/*! + \class QAndroidActivityResultReceiver + \since 5.3 + \brief Interface used for callbacks from onActivityResult() in the main Android activity. + + Create a subclass of this class to be notified of the results when using the + \c QtAndroid::startActivity() and \c QtAndroid::startIntentSender() APIs. + */ + +/*! + \internal +*/ +QAndroidActivityResultReceiver::QAndroidActivityResultReceiver() + : d(new QAndroidActivityResultReceiverPrivate) +{ + d->q = this; + QtAndroidPrivate::registerActivityResultListener(d.data()); +} + +/*! + \internal +*/ +QAndroidActivityResultReceiver::~QAndroidActivityResultReceiver() +{ + QtAndroidPrivate::unregisterActivityResultListener(d.data()); +} + +/*! + \fn void QAndroidActivityResultReceiver::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data) = 0; + + Reimplement this function to get activity results after starting an activity using either QtAndroid::startActivity() or + QtAndroid::startIntentSender(). The \a receiverRequestCode is the request code unique to this receiver which was originally + passed to the startActivity() or startIntentSender() functions. The \a resultCode is the result returned by the activity, + and \a data is either null or a Java object of the class android.content.Intent. Both the last to arguments are identical to the + arguments passed to onActivityResult(). +*/ + +QT_END_NAMESPACE diff --git a/src/androidextras/android/qandroidactivityresultreceiver.h b/src/androidextras/android/qandroidactivityresultreceiver.h new file mode 100644 index 0000000000000000000000000000000000000000..787aebced3c2092435ba345f6d301859d263c413 --- /dev/null +++ b/src/androidextras/android/qandroidactivityresultreceiver.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANDROIDACTIVITYRESULTRECEIVER_H +#define QANDROIDACTIVITYRESULTRECEIVER_H + +#include "qandroidextrasglobal.h" +#include "qandroidjniobject.h" + +QT_BEGIN_NAMESPACE + +class QAndroidActivityResultReceiverPrivate; +class Q_ANDROIDEXTRAS_EXPORT QAndroidActivityResultReceiver +{ +public: + QAndroidActivityResultReceiver(); + virtual ~QAndroidActivityResultReceiver(); + virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data) = 0; + +private: + friend class QAndroidActivityResultReceiverPrivate; + Q_DISABLE_COPY(QAndroidActivityResultReceiver) + + QScopedPointer<QAndroidActivityResultReceiverPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDACTIVITYRESULTRECEIVER_H diff --git a/src/androidextras/android/qandroidactivityresultreceiver_p.h b/src/androidextras/android/qandroidactivityresultreceiver_p.h new file mode 100644 index 0000000000000000000000000000000000000000..713681470f383034b51fe50e345dfc1ae743d954 --- /dev/null +++ b/src/androidextras/android/qandroidactivityresultreceiver_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANDROIDACTIVITYRESULTRECEIVER_P_H +#define QANDROIDACTIVITYRESULTRECEIVER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qhash.h> +#include <QtCore/private/qjnihelpers_p.h> +#include "qandroidactivityresultreceiver.h" + +QT_BEGIN_NAMESPACE + +class QAndroidActivityResultReceiverPrivate: public QtAndroidPrivate::ActivityResultListener +{ +public: + QAndroidActivityResultReceiver *q; + mutable QHash<int, int> localToGlobalRequestCode; + mutable QHash<int, int> globalToLocalRequestCode; + + int globalRequestCode(int localRequestCode) const; + bool handleActivityResult(jint requestCode, jint resultCode, jobject data); + + static QAndroidActivityResultReceiverPrivate *get(QAndroidActivityResultReceiver *publicObject) + { + return publicObject->d.data(); + } +}; + +QT_END_NAMESPACE + +#endif // QANDROIDACTIVITYRESULTRECEIVER_P_H diff --git a/src/androidextras/android/qandroidfunctions.cpp b/src/androidextras/android/qandroidfunctions.cpp index 2524614a380051303e8581fcd8bac43333c08798..582ee4c8dc111ff254a2e972b8ccb0c32ff4c3f6 100644 --- a/src/androidextras/android/qandroidfunctions.cpp +++ b/src/androidextras/android/qandroidfunctions.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include "qandroidfunctions.h" +#include "qandroidactivityresultreceiver.h" +#include "qandroidactivityresultreceiver_p.h" #include <QtCore/private/qjnihelpers_p.h> @@ -77,4 +79,80 @@ int QtAndroid::androidSdkVersion() return QtAndroidPrivate::androidSdkVersion(); } +/*! + \since 5.3 + + Starts the activity given by \a intent and provides the result asynchronously through the + \a resultReceiver if this is non-null. + + If \a resultReceiver is null, then the \c startActivity() method in the \c androidActivity() + will be called. Otherwise \c startActivityForResult() will be called. + + The \a receiverRequestCode is a request code unique to the \a resultReceiver, and will be + returned along with the result, making it possible to use the same receiver for more than + one intent. + + The \a optionsBundle provides additional options for the activity. + */ +void QtAndroid::startActivity(const QAndroidJniObject &intent, + int receiverRequestCode, + QAndroidActivityResultReceiver *resultReceiver) +{ + QAndroidJniObject activity = androidActivity(); + if (resultReceiver != 0) { + QAndroidActivityResultReceiverPrivate *resultReceiverD = QAndroidActivityResultReceiverPrivate::get(resultReceiver); + activity.callMethod<void>("startActivityForResult", + "(Landroid/content/Intent;I)V", + intent.object<jobject>(), + resultReceiverD->globalRequestCode(receiverRequestCode)); + } else { + activity.callMethod<void>("startActivity", + "(Landroid/content/Intent;)V", + intent.object<jobject>()); + } +} + +/*! + \since 5.3 + + Starts the activity given by \a intentSender and provides the result asynchronously through the + \a resultReceiver if this is non-null. + + If \a resultReceiver is null, then the \c startIntentSender() method in the \c androidActivity() + will be called. Otherwise \c startIntentSenderForResult() will be called. + + The \a receiverRequestCode is a request code unique to the \a resultReceiver, and will be + returned along with the result, making it possible to use the same receiver for more than + one intent. + + The \a optionsBundle provides additional options for the activity. +*/ +void QtAndroid::startIntentSender(const QAndroidJniObject &intentSender, + int receiverRequestCode, + QAndroidActivityResultReceiver *resultReceiver) +{ + QAndroidJniObject activity = androidActivity(); + if (resultReceiver != 0) { + QAndroidActivityResultReceiverPrivate *resultReceiverD = QAndroidActivityResultReceiverPrivate::get(resultReceiver); + activity.callMethod<void>("startIntentSenderForResult", + "(Landroid/content/IntentSender;ILandroid/content/Intent;III)V", + intentSender.object<jobject>(), + resultReceiverD->globalRequestCode(receiverRequestCode), + 0, // fillInIntent + 0, // flagsMask + 0, // flagsValues + 0); // extraFlags + } else { + activity.callMethod<void>("startIntentSender", + "(Landroid/content/Intent;Landroid/content/Intent;III)V", + intentSender.object<jobject>(), + 0, // fillInIntent + 0, // flagsMask + 0, // flagsValues + 0); // extraFlags + + } + +} + QT_END_NAMESPACE diff --git a/src/androidextras/android/qandroidfunctions.h b/src/androidextras/android/qandroidfunctions.h index 700bee8099e39752f7a23e90a15b23b80a6b5905..cd8262eecbd7949deb776652f2e0ddb5650ac829 100644 --- a/src/androidextras/android/qandroidfunctions.h +++ b/src/androidextras/android/qandroidfunctions.h @@ -51,10 +51,19 @@ QT_BEGIN_NAMESPACE +class QAndroidActivityResultReceiver; namespace QtAndroid { Q_ANDROIDEXTRAS_EXPORT QAndroidJniObject androidActivity(); Q_ANDROIDEXTRAS_EXPORT int androidSdkVersion(); + + Q_ANDROIDEXTRAS_EXPORT void startIntentSender(const QAndroidJniObject &intentSender, + int receiverRequestCode, + QAndroidActivityResultReceiver *resultReceiver = 0); + Q_ANDROIDEXTRAS_EXPORT void startActivity(const QAndroidJniObject &intent, + int receiverRequestCode, + QAndroidActivityResultReceiver *resultReceiver = 0); + } QT_END_NAMESPACE