summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorMÃ¥rten Nordheim <marten.nordheim@qt.io>2021-01-26 12:39:11 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-02-08 11:30:37 +0000
commit2d5506dd9ca7f1ee2e90c4b47eee3fb642dd4c60 (patch)
treefe90a6cce3cf06a47f12ad5d15737bac923fac8f /src/plugins
parent134ee7d932391c7b3c1b801e64e4f5693c3cdd20 (diff)
QNetworkInformation backend for Android
Based on the old bearer manager code! A lot of the old code went away though since it had been deprecated in the time since it was written. Task-number: QTBUG-86966 Change-Id: I21a6db1d4ebd8367084355a8e3202f4c05d9dce5 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> (cherry picked from commit 8652493529a46a375c11bbaf16d2122ee8466c29) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/networkinformationbackends/CMakeLists.txt4
-rw-r--r--src/plugins/networkinformationbackends/android/CMakeLists.txt47
-rw-r--r--src/plugins/networkinformationbackends/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java131
-rw-r--r--src/plugins/networkinformationbackends/android/qandroidnetworkinformationbackend.cpp132
-rw-r--r--src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.cpp132
-rw-r--r--src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.h74
6 files changed, 520 insertions, 0 deletions
diff --git a/src/plugins/networkinformationbackends/CMakeLists.txt b/src/plugins/networkinformationbackends/CMakeLists.txt
index 57ce300b6d..b1eafa4441 100644
--- a/src/plugins/networkinformationbackends/CMakeLists.txt
+++ b/src/plugins/networkinformationbackends/CMakeLists.txt
@@ -9,3 +9,7 @@ endif()
if(APPLE)
add_subdirectory(scnetworkreachability)
endif()
+
+if(ANDROID)
+ add_subdirectory(android)
+endif()
diff --git a/src/plugins/networkinformationbackends/android/CMakeLists.txt b/src/plugins/networkinformationbackends/android/CMakeLists.txt
new file mode 100644
index 0000000000..d5d3fa5eb6
--- /dev/null
+++ b/src/plugins/networkinformationbackends/android/CMakeLists.txt
@@ -0,0 +1,47 @@
+
+set(java_sources
+ jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java
+)
+
+qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}AndroidNetworkInformationBackend
+ INCLUDE_JARS ${QT_ANDROID_JAR}
+ SOURCES ${java_sources}
+ OUTPUT_DIR "${QT_BUILD_DIR}/jar"
+)
+
+install_jar(Qt${QtBase_VERSION_MAJOR}AndroidNetworkInformationBackend
+ DESTINATION jar
+ COMPONENT Devel
+)
+
+qt_internal_add_plugin(QAndroidNetworkInformationBackend
+ OUTPUT_NAME androidnetworkinformationbackend
+ TYPE networkinformationbackends
+ DEFAULT_IF ANDROID
+ SOURCES
+ qandroidnetworkinformationbackend.cpp
+ wrapper/androidconnectivitymanager.cpp wrapper/androidconnectivitymanager.h
+ LIBRARIES
+ Qt::NetworkPrivate
+ DEFINES
+ QT_USE_QSTRINGBUILDER
+)
+
+# @todo: androiddeployqt doesn't deploy JARs bundled with plugins, needs fix, temporarily bundle with Network
+# QTBUG-90812
+set_property(
+ TARGET
+ # QAndroidNetworkInformationBackend
+ Network
+ APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
+ jar/Qt${QtBase_VERSION_MAJOR}AndroidNetworkInformationBackend.jar
+)
+
+# @todo: same as above, but for permissions
+set_property(
+ TARGET
+ # QAndroidNetworkInformationBackend
+ Network
+ APPEND PROPERTY QT_ANDROID_PERMISSIONS
+ android.permission.ACCESS_NETWORK_STATE
+)
diff --git a/src/plugins/networkinformationbackends/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java b/src/plugins/networkinformationbackends/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java
new file mode 100644
index 0000000000..4ae17252eb
--- /dev/null
+++ b/src/plugins/networkinformationbackends/android/jar/src/org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation.java
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.qt.android.networkinformation;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkRequest;
+import android.net.NetworkCapabilities;
+import android.net.Network;
+
+public class QtAndroidNetworkInformation {
+ private static final String LOG_TAG = "QtAndroidNetworkInformation";
+
+ private static native void connectivityChanged();
+
+ private static QtNetworkInformationCallback m_callback = null;
+ private static final Object m_lock = new Object();
+
+ enum AndroidConnectivity {
+ Connected, Unknown, Disconnected
+ }
+
+ private static class QtNetworkInformationCallback extends NetworkCallback {
+ public AndroidConnectivity previousState = null;
+
+ QtNetworkInformationCallback() {
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
+ AndroidConnectivity s;
+ if (!capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))
+ s = AndroidConnectivity.Disconnected;
+ else if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ s = AndroidConnectivity.Connected;
+ else
+ s = AndroidConnectivity.Unknown; // = we _may_ have Internet access
+ setState(s);
+ }
+
+ private void setState(AndroidConnectivity s) {
+ if (previousState != s) {
+ previousState = s;
+ connectivityChanged();
+ }
+ }
+
+ @Override
+ public void onLost(Network network) {
+ setState(AndroidConnectivity.Disconnected);
+ }
+ }
+
+ private QtAndroidNetworkInformation() {
+ }
+
+ public static AndroidConnectivity state() {
+ if (m_callback != null && m_callback.previousState != null)
+ return m_callback.previousState;
+ return AndroidConnectivity.Unknown;
+ }
+
+ public static void registerReceiver(final Context context) {
+ synchronized (m_lock) {
+ if (m_callback == null) {
+ ConnectivityManager manager = getConnectivityManager(context);
+ m_callback = new QtNetworkInformationCallback();
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder = builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P)
+ builder = builder.addCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND);
+ NetworkRequest request = builder.build();
+ manager.registerNetworkCallback(request, m_callback);
+ }
+ }
+ }
+
+ public static void unregisterReceiver(final Context context) {
+ synchronized (m_lock) {
+ if (m_callback != null) {
+ getConnectivityManager(context).unregisterNetworkCallback(m_callback);
+ m_callback = null;
+ }
+ }
+ }
+
+ public static ConnectivityManager getConnectivityManager(final Context context) {
+ return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+}
diff --git a/src/plugins/networkinformationbackends/android/qandroidnetworkinformationbackend.cpp b/src/plugins/networkinformationbackends/android/qandroidnetworkinformationbackend.cpp
new file mode 100644
index 0000000000..81e30610a2
--- /dev/null
+++ b/src/plugins/networkinformationbackends/android/qandroidnetworkinformationbackend.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtNetwork/private/qnetworkinformation_p.h>
+
+#include "wrapper/androidconnectivitymanager.h"
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcNetInfoAndroid)
+Q_LOGGING_CATEGORY(lcNetInfoAndroid, "qt.network.info.android");
+
+static const QString backendName = QStringLiteral("android");
+
+class QAndroidNetworkInformationBackend : public QNetworkInformationBackend
+{
+ Q_OBJECT
+public:
+ QAndroidNetworkInformationBackend();
+ ~QAndroidNetworkInformationBackend() { m_valid = false; }
+
+ QString name() const override { return backendName; }
+ QNetworkInformation::Features featuresSupported() const override
+ {
+ return featuresSupportedStatic();
+ }
+
+ static QNetworkInformation::Features featuresSupportedStatic()
+ {
+ return QNetworkInformation::Features(QNetworkInformation::Feature::Reachability);
+ }
+
+ bool isValid() { return m_valid; }
+
+private:
+ Q_DISABLE_COPY_MOVE(QAndroidNetworkInformationBackend);
+ bool m_valid = false;
+};
+
+class QAndroidNetworkInformationBackendFactory : public QNetworkInformationBackendFactory
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QNetworkInformationBackendFactory_iid)
+ Q_INTERFACES(QNetworkInformationBackendFactory)
+public:
+ QAndroidNetworkInformationBackendFactory() = default;
+ ~QAndroidNetworkInformationBackendFactory() = default;
+ QString name() const override { return backendName; }
+ QNetworkInformation::Features featuresSupported() const override
+ {
+ return QAndroidNetworkInformationBackend::featuresSupportedStatic();
+ }
+
+ QNetworkInformationBackend *
+ create(QNetworkInformation::Features requiredFeatures) const override
+ {
+ if ((requiredFeatures & featuresSupported()) != requiredFeatures)
+ return nullptr;
+ auto backend = new QAndroidNetworkInformationBackend();
+ if (!backend->isValid())
+ delete std::exchange(backend, nullptr);
+ return backend;
+ }
+
+private:
+ Q_DISABLE_COPY_MOVE(QAndroidNetworkInformationBackendFactory);
+};
+
+QAndroidNetworkInformationBackend::QAndroidNetworkInformationBackend()
+{
+ auto conman = AndroidConnectivityManager::getInstance();
+ if (!conman)
+ return;
+ m_valid = true;
+ setReachability(QNetworkInformation::Reachability::Unknown);
+ connect(conman, &AndroidConnectivityManager::connectivityChanged, this, [this, conman]() {
+ static const auto mapState = [](AndroidConnectivityManager::AndroidConnectivity state) {
+ switch (state) {
+ case AndroidConnectivityManager::AndroidConnectivity::Connected:
+ return QNetworkInformation::Reachability::Online;
+ case AndroidConnectivityManager::AndroidConnectivity::Disconnected:
+ return QNetworkInformation::Reachability::Disconnected;
+ case AndroidConnectivityManager::AndroidConnectivity::Unknown:
+ default:
+ return QNetworkInformation::Reachability::Unknown;
+ }
+ };
+
+ setReachability(mapState(conman->networkConnectivity()));
+ });
+}
+
+QT_END_NAMESPACE
+
+#include "qandroidnetworkinformationbackend.moc"
diff --git a/src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.cpp b/src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.cpp
new file mode 100644
index 0000000000..c22f16f7b4
--- /dev/null
+++ b/src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "androidconnectivitymanager.h"
+
+#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/qjnienvironment.h>
+
+QT_BEGIN_NAMESPACE
+
+struct AndroidConnectivityManagerInstance
+{
+ AndroidConnectivityManagerInstance() : connManager(new AndroidConnectivityManager) { }
+ std::unique_ptr<AndroidConnectivityManager> connManager = nullptr;
+};
+Q_GLOBAL_STATIC(AndroidConnectivityManagerInstance, androidConnManagerInstance)
+
+static const char networkInformationClass[] =
+ "org/qtproject/qt/android/networkinformation/QtAndroidNetworkInformation";
+
+static void networkConnectivityChanged()
+{
+ Q_EMIT androidConnManagerInstance->connManager->connectivityChanged();
+}
+
+AndroidConnectivityManager::AndroidConnectivityManager()
+{
+ if (!registerNatives())
+ return;
+
+ m_connectivityManager = QJniObject::callStaticObjectMethod(
+ networkInformationClass, "getConnectivityManager",
+ "(Landroid/content/Context;)Landroid/net/ConnectivityManager;",
+ QtAndroidPrivate::context());
+ if (!m_connectivityManager.isValid())
+ return;
+
+ QJniObject::callStaticMethod<void>(networkInformationClass, "registerReceiver",
+ "(Landroid/content/Context;)V", QtAndroidPrivate::context());
+}
+
+AndroidConnectivityManager *AndroidConnectivityManager::getInstance()
+{
+ if (!androidConnManagerInstance())
+ return nullptr;
+ return androidConnManagerInstance->connManager->isValid()
+ ? androidConnManagerInstance->connManager.get()
+ : nullptr;
+}
+
+AndroidConnectivityManager::~AndroidConnectivityManager()
+{
+ QJniObject::callStaticMethod<void>(networkInformationClass, "unregisterReceiver",
+ "(Landroid/content/Context;)V", QtAndroidPrivate::context());
+}
+
+AndroidConnectivityManager::AndroidConnectivity AndroidConnectivityManager::networkConnectivity()
+{
+ QJniEnvironment env;
+ QJniObject networkReceiver(networkInformationClass);
+ jclass clazz = env->GetObjectClass(networkReceiver.object());
+ static const QByteArray functionSignature =
+ QByteArray(QByteArray("()L") + networkInformationClass + "$AndroidConnectivity;");
+ QJniObject enumObject =
+ QJniObject::callStaticObjectMethod(clazz, "state", functionSignature.data());
+ if (!enumObject.isValid())
+ return AndroidConnectivityManager::AndroidConnectivity::Unknown;
+
+ QJniObject enumName = enumObject.callObjectMethod<jstring>("name");
+ if (!enumName.isValid())
+ return AndroidConnectivityManager::AndroidConnectivity::Unknown;
+
+ QString name = enumName.toString();
+ if (name == u"Connected")
+ return AndroidConnectivity::Connected;
+ if (name == u"Disconnected")
+ return AndroidConnectivity::Disconnected;
+ return AndroidConnectivity::Unknown;
+}
+
+bool AndroidConnectivityManager::registerNatives()
+{
+ QJniEnvironment env;
+ QJniObject networkReceiver(networkInformationClass);
+ if (!networkReceiver.isValid())
+ return false;
+
+ jclass clazz = env->GetObjectClass(networkReceiver.object());
+ static JNINativeMethod method = { "connectivityChanged", "()V",
+ reinterpret_cast<void *>(networkConnectivityChanged) };
+ const bool ret = (env->RegisterNatives(clazz, &method, 1) == JNI_OK);
+ env->DeleteLocalRef(clazz);
+ return ret;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.h b/src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.h
new file mode 100644
index 0000000000..8126125983
--- /dev/null
+++ b/src/plugins/networkinformationbackends/android/wrapper/androidconnectivitymanager.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ANDROIDCONNECTIVITYMANAGER_H
+#define ANDROIDCONNECTIVITYMANAGER_H
+
+#include <QObject>
+#include <QtCore/qjniobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class AndroidConnectivityManager : public QObject
+{
+ Q_OBJECT
+public:
+ enum class AndroidConnectivity { Connected, Unknown, Disconnected };
+ Q_ENUM(AndroidConnectivity);
+ static AndroidConnectivityManager *getInstance();
+ ~AndroidConnectivityManager();
+
+ AndroidConnectivity networkConnectivity();
+ inline bool isValid() const { return m_connectivityManager.isValid(); }
+
+Q_SIGNALS:
+ void connectivityChanged();
+
+private:
+ friend struct AndroidConnectivityManagerInstance;
+ AndroidConnectivityManager();
+ bool registerNatives();
+ QJniObject m_connectivityManager;
+
+ Q_DISABLE_COPY_MOVE(AndroidConnectivityManager);
+};
+
+QT_END_NAMESPACE
+
+#endif // ANDROIDCONNECTIVITYMANAGER_H