Android: New bearer plugin

Replacement for the the generic bearer plugin.
Compared to the generic bearer engine, this plugin provides a more
detailed overview of the network configurations on Android.

Added features are:
- Correct bearer type, also for mobile connections.
- Connection state (e.g., roaming).
- Data statistics (On devices that supports it).
- Polling is not required.

Change-Id: I728cb91e04a66343648c0add6be2a003caca0f1f
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
Christian Strømme 2013-07-02 18:51:49 +02:00 committed by Christian Stromme
parent 50c04d6318
commit ff7fdf78ef
16 changed files with 1288 additions and 0 deletions

View File

@ -25,3 +25,14 @@ include(socket/socket.pri)
include(ssl/ssl.pri)
QMAKE_LIBS += $$QMAKE_LIBS_NETWORK
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
jar/QtAndroidBearer-bundled.jar
ANDROID_JAR_DEPENDENCIES = \
jar/QtAndroidBearer.jar
ANDROID_LIB_DEPENDENCIES = \
plugins/bearer/libqandroidbearer.so
MODULE_PLUGIN_TYPES = \
bearer
ANDROID_PERMISSIONS += \
android.permission.ACCESS_NETWORK_STATE

View File

@ -0,0 +1,4 @@
TEMPLATE = subdirs
SUBDIRS += src \
jar

View File

@ -0,0 +1,3 @@
TARGET = QtAndroidBearer-bundled
CONFIG += bundled_jar_file
include(jar.pri)

View File

@ -0,0 +1,2 @@
TARGET = QtAndroidBearer
include(jar.pri)

View File

@ -0,0 +1,13 @@
load(qt_build_paths)
CONFIG += java
DESTDIR = $$MODULE_BASE_OUTDIR/jar
JAVACLASSPATH += $$PWD/src
JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java
# install
target.path = $$[QT_INSTALL_PREFIX]/jar
INSTALLS += target
OTHER_FILES += $$JAVASOURCES

View File

@ -0,0 +1,2 @@
TEMPLATE=subdirs
SUBDIRS += distributedjar.pro bundledjar.pro

View File

@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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$
**
****************************************************************************/
package org.qtproject.qt5.android.bearer;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.app.Activity;
import android.net.ConnectivityManager;
public class QtNetworkReceiver
{
private static final String LOG_TAG = "QtNetworkReceiver";
private static native void activeNetworkInfoChanged();
private static BroadcastReceiverPrivate m_broadcastReceiver = null;
private static final Object m_lock = new Object();
private static class BroadcastReceiverPrivate extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
activeNetworkInfoChanged();
}
}
private QtNetworkReceiver() {}
public static void registerReceiver(final Activity activity)
{
synchronized (m_lock) {
if (m_broadcastReceiver == null) {
m_broadcastReceiver = new BroadcastReceiverPrivate();
IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
activity.registerReceiver(m_broadcastReceiver, intentFilter);
}
}
}
public static void unregisterReceiver(final Activity activity)
{
synchronized (m_lock) {
if (m_broadcastReceiver == null)
return;
activity.unregisterReceiver(m_broadcastReceiver);
}
}
public static ConnectivityManager getConnectivityManager(final Activity activity)
{
return (ConnectivityManager)activity.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
}
}

View File

@ -0,0 +1,3 @@
{
"Keys": [ "android" ]
}

View File

@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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 "qandroidbearerengine.h"
#include <QtNetwork/private/qbearerplugin_p.h>
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
class QAndroidBearerEnginePlugin : public QBearerEnginePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QBearerEngineFactoryInterface" FILE "android.json")
public:
QBearerEngine *create(const QString &key) const Q_DECL_OVERRIDE
{
return (key == QStringLiteral("android")) ? new QAndroidBearerEngine() : 0;
}
};
QT_END_NAMESPACE
#include "main.moc"
#endif // QT_NO_BEARERMANAGEMENT

View File

@ -0,0 +1,405 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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 "qandroidbearerengine.h"
#include "../../qnetworksession_impl.h"
#include "wrappers/androidconnectivitymanager.h"
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
static QString networkConfType(const AndroidNetworkInfo &networkInfo)
{
switch (networkInfo.getType()) {
case AndroidNetworkInfo::Mobile:
return QStringLiteral("Mobile");
case AndroidNetworkInfo::Wifi:
return QStringLiteral("WiFi");
case AndroidNetworkInfo::Wimax:
return QStringLiteral("WiMax");
case AndroidNetworkInfo::Ethernet:
return QStringLiteral("Ethernet");
case AndroidNetworkInfo::Bluetooth:
return QStringLiteral("Bluetooth");
default:
break;
}
return QString();
}
static inline bool isMobile(QNetworkConfiguration::BearerType type)
{
if (type == QNetworkConfiguration::BearerWLAN
|| type == QNetworkConfiguration::BearerWiMAX
|| type == QNetworkConfiguration::BearerBluetooth
|| type == QNetworkConfiguration::BearerEthernet
|| type == QNetworkConfiguration::BearerUnknown) {
return false;
}
return true;
}
static QNetworkConfiguration::BearerType getBearerType(const AndroidNetworkInfo &networkInfo)
{
switch (networkInfo.getType()) {
case AndroidNetworkInfo::Mobile:
{
switch (networkInfo.getSubtype()) {
case AndroidNetworkInfo::Gprs:
case AndroidNetworkInfo::Edge:
case AndroidNetworkInfo::Iden: // 2G
return QNetworkConfiguration::Bearer2G;
case AndroidNetworkInfo::Umts: // BearerWCDMA (3 .5 .75 G)
case AndroidNetworkInfo::Hsdpa: // 3G (?) UMTS
case AndroidNetworkInfo::Hsupa: // 3G (?) UMTS
return QNetworkConfiguration::BearerWCDMA;
case AndroidNetworkInfo::Cdma: // CDMA ISA95[AB]
case AndroidNetworkInfo::Cdma1xRTT: // BearerCDMA2000 (3G)
case AndroidNetworkInfo::Ehrpd: // CDMA Bridge thing?!?
return QNetworkConfiguration::BearerCDMA2000;
case AndroidNetworkInfo::Evdo0: // BearerEVDO
case AndroidNetworkInfo::EvdoA: // BearerEVDO
case AndroidNetworkInfo::EvdoB: // BearerEVDO
return QNetworkConfiguration::BearerEVDO;
case AndroidNetworkInfo::Hspa:
case AndroidNetworkInfo::Hspap: // HSPA+
return QNetworkConfiguration::BearerHSPA;
case AndroidNetworkInfo::Lte: // BearerLTE (4G)
return QNetworkConfiguration::BearerLTE;
default:
break;
}
}
case AndroidNetworkInfo::Wifi:
return QNetworkConfiguration::BearerWLAN;
case AndroidNetworkInfo::Wimax:
return QNetworkConfiguration::BearerWiMAX;
case AndroidNetworkInfo::Bluetooth:
case AndroidNetworkInfo::MobileDun:
return QNetworkConfiguration::BearerBluetooth;
case AndroidNetworkInfo::Ethernet:
return QNetworkConfiguration::BearerEthernet;
case AndroidNetworkInfo::MobileMms:
case AndroidNetworkInfo::MobileSupl:
case AndroidNetworkInfo::MobileHipri:
case AndroidNetworkInfo::Dummy:
case AndroidNetworkInfo::UnknownType:
break;
}
return QNetworkConfiguration::BearerUnknown;
}
QAndroidBearerEngine::QAndroidBearerEngine(QObject *parent)
: QBearerEngineImpl(parent),
m_connectivityManager(0)
{
}
QAndroidBearerEngine::~QAndroidBearerEngine()
{
}
QString QAndroidBearerEngine::getInterfaceFromId(const QString &id)
{
const QMutexLocker locker(&mutex);
return m_configurationInterface.value(id);
}
bool QAndroidBearerEngine::hasIdentifier(const QString &id)
{
const QMutexLocker locker(&mutex);
return m_configurationInterface.contains(id);
}
void QAndroidBearerEngine::connectToId(const QString &id)
{
Q_EMIT connectionError(id, OperationNotSupported);
}
void QAndroidBearerEngine::disconnectFromId(const QString &id)
{
Q_EMIT connectionError(id, OperationNotSupported);
}
QNetworkSession::State QAndroidBearerEngine::sessionStateForId(const QString &id)
{
const QMutexLocker locker(&mutex);
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if ((!ptr || !ptr->isValid) || m_connectivityManager == 0)
return QNetworkSession::Invalid;
const QMutexLocker configLocker(&ptr->mutex);
// Don't re-order...
if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
return (m_connectivityManager->isActiveNetworkMetered()
|| m_connectivityManager->getActiveNetworkInfo().isRoaming())
? QNetworkSession::Roaming
: QNetworkSession::Connected;
} else if ((ptr->state & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
return QNetworkSession::Disconnected;
} else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
return QNetworkSession::NotAvailable;
} else if ((ptr->state & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
return QNetworkSession::NotAvailable;
}
return QNetworkSession::Invalid;
}
QNetworkConfigurationManager::Capabilities QAndroidBearerEngine::capabilities() const
{
return AndroidTrafficStats::isTrafficStatsSupported()
? QNetworkConfigurationManager::ForcedRoaming
| QNetworkConfigurationManager::DataStatistics
: QNetworkConfigurationManager::ForcedRoaming;
}
QNetworkSessionPrivate *QAndroidBearerEngine::createSessionBackend()
{
return new QNetworkSessionPrivateImpl();
}
QNetworkConfigurationPrivatePointer QAndroidBearerEngine::defaultConfiguration()
{
return QNetworkConfigurationPrivatePointer();
}
bool QAndroidBearerEngine::requiresPolling() const
{
return false;
}
quint64 QAndroidBearerEngine::bytesWritten(const QString &id)
{
QMutexLocker lock(&mutex);
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (!ptr || !ptr->isValid)
return 0;
return isMobile(ptr->bearerType)
? AndroidTrafficStats::getMobileTxBytes()
: AndroidTrafficStats::getTotalTxBytes() - AndroidTrafficStats::getMobileTxBytes();
}
quint64 QAndroidBearerEngine::bytesReceived(const QString &id)
{
QMutexLocker lock(&mutex);
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (!ptr || !ptr->isValid)
return 0;
return isMobile(ptr->bearerType)
? AndroidTrafficStats::getMobileRxBytes()
: AndroidTrafficStats::getTotalRxBytes() - AndroidTrafficStats::getMobileRxBytes();
}
quint64 QAndroidBearerEngine::startTime(const QString &id)
{
Q_UNUSED(id);
return Q_UINT64_C(0);
}
void QAndroidBearerEngine::initialize()
{
if (m_connectivityManager != 0)
return;
m_connectivityManager = AndroidConnectivityManager::getInstance();
if (m_connectivityManager == 0)
return;
updateConfigurations();
connect(m_connectivityManager, &AndroidConnectivityManager::activeNetworkChanged,
this, &QAndroidBearerEngine::updateConfigurations);
}
void QAndroidBearerEngine::requestUpdate()
{
updateConfigurations();
}
void QAndroidBearerEngine::updateConfigurations()
{
#ifndef QT_NO_NETWORKINTERFACE
if (m_connectivityManager == 0)
return;
{
QMutexLocker locker(&mutex);
QStringList oldKeys = accessPointConfigurations.keys();
// Create a configuration for each of the main types (WiFi, Mobile, Bluetooth, WiMax, Ethernet)
foreach (const AndroidNetworkInfo &netInfo, m_connectivityManager->getAllNetworkInfo()) {
if (!netInfo.isValid())
continue;
const QString name = networkConfType(netInfo);
if (name.isEmpty())
continue;
QNetworkConfiguration::BearerType bearerType = getBearerType(netInfo);
QNetworkConfiguration::StateFlag state;
QString interfaceName;
if (netInfo.isAvailable()) {
if (netInfo.isConnected()) {
state = QNetworkConfiguration::Active;
// Attempt to map an interface to this configuration
const QList<QNetworkInterface> &interfaces = QNetworkInterface::allInterfaces();
foreach (const QNetworkInterface &interface, interfaces) {
// ignore loopback interface
if (!interface.isValid())
continue;
if (interface.flags() & QNetworkInterface::IsLoopBack)
continue;
// There is no way to get the interface from the NetworkInfo, so
// look for an active interface...
if (interface.flags() & QNetworkInterface::IsRunning
&& !interface.addressEntries().isEmpty()) {
interfaceName = interface.humanReadableName();
if (interfaceName.isEmpty())
interfaceName = interface.name();
}
}
} else if (netInfo.isConnectedOrConnecting()) {
state = QNetworkConfiguration::Undefined;
} else {
state = QNetworkConfiguration::Discovered;
}
} else {
state = QNetworkConfiguration::Defined;
}
const uint identifier = qHash(QLatin1String("android:") + name);
const QString id = QString::number(identifier);
oldKeys.removeAll(id);
if (accessPointConfigurations.contains(id)) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
bool changed = false;
{
const QMutexLocker confLocker(&ptr->mutex);
if (!ptr->isValid) {
ptr->isValid = true;
changed = true;
}
// Don't reset the bearer type to 'Unknown'
if (ptr->bearerType != QNetworkConfiguration::BearerUnknown
&& ptr->bearerType != bearerType) {
ptr->bearerType = bearerType;
changed = true;
}
if (ptr->name != name) {
ptr->name = name;
changed = true;
}
if (ptr->id != id) {
ptr->id = id;
changed = true;
}
if (ptr->state != state) {
ptr->state = state;
changed = true;
}
QString &oldIfName = m_configurationInterface[id];
if (oldIfName != interfaceName) {
oldIfName = interfaceName;
changed = true;
}
} // Unlock configuration
if (changed) {
locker.unlock();
Q_EMIT configurationChanged(ptr);
locker.relock();
}
} else {
QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
ptr->name = name;
ptr->isValid = true;
ptr->id = id;
ptr->state = state;
ptr->type = QNetworkConfiguration::InternetAccessPoint;
ptr->bearerType = bearerType;
accessPointConfigurations.insert(id, ptr);
m_configurationInterface.insert(id, interfaceName);
locker.unlock();
Q_EMIT configurationAdded(ptr);
locker.relock();
}
}
while (!oldKeys.isEmpty()) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldKeys.takeFirst());
m_configurationInterface.remove(ptr->id);
locker.unlock();
Q_EMIT configurationRemoved(ptr);
locker.relock();
}
} // Unlock engine
#endif // QT_NO_NETWORKINTERFACE
Q_EMIT updateCompleted();
}
QT_END_NAMESPACE
#endif // QT_NO_BEARERMANAGEMENT

View File

@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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 QANDROIDBEARERENGINE_H
#define QANDROIDBEARERENGINE_H
#include "../../qbearerengine_impl.h"
#include <QAbstractEventDispatcher>
#include <QAbstractNativeEventFilter>
#include <QtCore/private/qjni_p.h>
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
class QNetworkConfigurationPrivate;
class QNetworkSessionPrivate;
class AndroidConnectivityManager;
class QAndroidBearerEngine : public QBearerEngineImpl
{
Q_OBJECT
public:
explicit QAndroidBearerEngine(QObject *parent = 0);
~QAndroidBearerEngine() Q_DECL_OVERRIDE;
QString getInterfaceFromId(const QString &id) Q_DECL_OVERRIDE;
bool hasIdentifier(const QString &id) Q_DECL_OVERRIDE;
void connectToId(const QString &id) Q_DECL_OVERRIDE;
void disconnectFromId(const QString &id) Q_DECL_OVERRIDE;
QNetworkSession::State sessionStateForId(const QString &id) Q_DECL_OVERRIDE;
QNetworkConfigurationManager::Capabilities capabilities() const Q_DECL_OVERRIDE;
QNetworkSessionPrivate *createSessionBackend() Q_DECL_OVERRIDE;
QNetworkConfigurationPrivatePointer defaultConfiguration() Q_DECL_OVERRIDE;
bool requiresPolling() const Q_DECL_OVERRIDE;
quint64 bytesWritten(const QString &id) Q_DECL_OVERRIDE;
quint64 bytesReceived(const QString &id) Q_DECL_OVERRIDE;
quint64 startTime(const QString &id) Q_DECL_OVERRIDE;
Q_INVOKABLE void initialize();
Q_INVOKABLE void requestUpdate();
private Q_SLOTS:
void updateConfigurations();
private:
QJNIObjectPrivate m_networkReceiver;
AndroidConnectivityManager *m_connectivityManager;
QMap<QString, QString> m_configurationInterface;
};
QT_END_NAMESPACE
#endif // QT_NO_BEARERMANAGEMENT
#endif // QANDROIDBEARERENGINE_H

View File

@ -0,0 +1,17 @@
include(wrappers/wrappers.pri)
TARGET = qandroidbearer
PLUGIN_TYPE = bearer
PLUGIN_CLASS_NAME = QAndroidBearerEnginePlugin
load(qt_plugin)
QT = core-private network-private
HEADERS += qandroidbearerengine.h \
../../qnetworksession_impl.h \
../../qbearerengine_impl.h
SOURCES += main.cpp \
qandroidbearerengine.cpp \
../../qnetworksession_impl.cpp

View File

@ -0,0 +1,394 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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 "androidconnectivitymanager.h"
#include <QtCore/private/qjni_p.h>
#include <QtCore/private/qjnihelpers_p.h>
QT_BEGIN_NAMESPACE
static inline bool exceptionCheckAndClear(JNIEnv *env)
{
if (!env->ExceptionCheck())
return false;
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif // QT_DEBUG
env->ExceptionClear();
return true;
}
struct AndroidConnectivityManagerInstance
{
AndroidConnectivityManagerInstance()
: connManager(new AndroidConnectivityManager)
{ }
~AndroidConnectivityManagerInstance()
{
delete connManager;
}
AndroidConnectivityManager* connManager;
};
Q_GLOBAL_STATIC(AndroidConnectivityManagerInstance, androidConnManagerInstance)
static const char networkReceiverClass[] = "org/qtproject/qt5/android/bearer/QtNetworkReceiver";
static const char trafficStatsClass[] = "android/net/TrafficStats";
/**
* Returns the number of bytes transmitted over the mobile network since last device boot.
*/
qint64 AndroidTrafficStats::getMobileTxBytes()
{
return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
"getMobileTxBytes",
"()J");
}
/**
* Returns the number of bytes received over the mobile network since last device boot.
*/
qint64 AndroidTrafficStats::getMobileRxBytes()
{
return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
"getMobileRxBytes",
"()J");
}
/**
* Returns the total transmitted bytes since last device boot.
*/
qint64 AndroidTrafficStats::getTotalTxBytes()
{
return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
"getTotalTxBytes",
"()J");
}
/**
* Returns the total received bytes since last device boot.
*/
qint64 AndroidTrafficStats::getTotalRxBytes()
{
return QJNIObjectPrivate::callStaticMethod<jlong>(trafficStatsClass,
"getTotalRxBytes",
"()J");
}
bool AndroidTrafficStats::isTrafficStatsSupported()
{
// Before API level 18 DataStatistics might not be supported, so make sure that we get something
// else then -1 from from getXXBytes().
return (AndroidTrafficStats::getMobileRxBytes() != -1
&& AndroidTrafficStats::getTotalRxBytes() != -1);
}
static AndroidNetworkInfo::NetworkState stateForName(const QString stateName)
{
if (stateName == QLatin1String("CONNECTED"))
return AndroidNetworkInfo::Connected;
else if (stateName == QLatin1String("CONNECTING"))
return AndroidNetworkInfo::Connecting;
else if (stateName == QLatin1String("DISCONNECTED"))
return AndroidNetworkInfo::Disconnected;
else if (stateName == QLatin1String("DISCONNECTING"))
return AndroidNetworkInfo::Disconnecting;
else if (stateName == QLatin1String("SUSPENDED"))
return AndroidNetworkInfo::Suspended;
return AndroidNetworkInfo::UnknownState;
}
AndroidNetworkInfo::NetworkState AndroidNetworkInfo::getDetailedState() const
{
QJNIObjectPrivate enumObject = m_networkInfo.callObjectMethod("getDetailedState",
"()Landroid/net/NetworkInfo$DetailedState;");
if (!enumObject.isValid())
return UnknownState;
QJNIObjectPrivate enumName = enumObject.callObjectMethod<jstring>("name");
if (!enumName.isValid())
return UnknownState;
return stateForName(enumName.toString());
}
QString AndroidNetworkInfo::getExtraInfo() const
{
QJNIObjectPrivate extraInfo = m_networkInfo.callObjectMethod<jstring>("getExtraInfo");
if (!extraInfo.isValid())
return QString();
return extraInfo.toString();
}
QString AndroidNetworkInfo::getReason() const
{
QJNIObjectPrivate reason = m_networkInfo.callObjectMethod<jstring>("getReason");
if (!reason.isValid())
return QString();
return reason.toString();
}
AndroidNetworkInfo::NetworkState AndroidNetworkInfo::getState() const
{
QJNIObjectPrivate enumObject = m_networkInfo.callObjectMethod("getState",
"()Landroid/net/NetworkInfo$State;");
if (!enumObject.isValid())
return UnknownState;
QJNIObjectPrivate enumName = enumObject.callObjectMethod<jstring>("name");
if (!enumName.isValid())
return UnknownState;
return stateForName(enumName.toString());
}
AndroidNetworkInfo::NetworkSubType AndroidNetworkInfo::getSubtype() const
{
return AndroidNetworkInfo::NetworkSubType(m_networkInfo.callMethod<jint>("getSubtype"));
}
QString AndroidNetworkInfo::getSubtypeName() const
{
QJNIObjectPrivate subtypeName = m_networkInfo.callObjectMethod<jstring>("getSubtypeName");
if (!subtypeName.isValid())
return QString();
return subtypeName.toString();
}
AndroidNetworkInfo::NetworkType AndroidNetworkInfo::getType() const
{
return AndroidNetworkInfo::NetworkType(m_networkInfo.callMethod<jint>("getType"));
}
QString AndroidNetworkInfo::getTypeName() const
{
QJNIObjectPrivate typeName = m_networkInfo.callObjectMethod<jstring>("getTypeName");
if (!typeName.isValid())
return QString();
return typeName.toString();
}
bool AndroidNetworkInfo::isAvailable() const
{
return m_networkInfo.callMethod<jboolean>("isAvailable");
}
bool AndroidNetworkInfo::isConnected() const
{
return m_networkInfo.callMethod<jboolean>("isConnected");
}
bool AndroidNetworkInfo::isConnectedOrConnecting() const
{
return m_networkInfo.callMethod<jboolean>("isConnectedOrConnecting");
}
bool AndroidNetworkInfo::isFailover() const
{
return m_networkInfo.callMethod<jboolean>("isFailover");
}
bool AndroidNetworkInfo::isRoaming() const
{
return m_networkInfo.callMethod<jboolean>("isRoaming");
}
bool AndroidNetworkInfo::isValid() const
{
return m_networkInfo.isValid();
}
AndroidConnectivityManager::AndroidConnectivityManager()
{
QJNIEnvironmentPrivate env;
if (!registerNatives(env))
return;
m_connectivityManager = QJNIObjectPrivate::callStaticObjectMethod(networkReceiverClass,
"getConnectivityManager",
"(Landroid/app/Activity;)Landroid/net/ConnectivityManager;",
QtAndroidPrivate::activity());
if (!m_connectivityManager.isValid())
return;
QJNIObjectPrivate::callStaticMethod<void>(networkReceiverClass,
"registerReceiver",
"(Landroid/app/Activity;)V",
QtAndroidPrivate::activity());
}
AndroidConnectivityManager *AndroidConnectivityManager::getInstance()
{
return androidConnManagerInstance->connManager->isValid()
? androidConnManagerInstance->connManager
: 0;
}
AndroidConnectivityManager::~AndroidConnectivityManager()
{
QJNIObjectPrivate::callStaticMethod<void>(networkReceiverClass,
"unregisterReceiver",
"(Landroid/app/Activity;)V",
QtAndroidPrivate::activity());
}
AndroidNetworkInfo AndroidConnectivityManager::getActiveNetworkInfo() const
{
QJNIObjectPrivate networkInfo = m_connectivityManager.callObjectMethod("getActiveNetworkInfo",
"()Landroid/net/NetworkInfo;");
return networkInfo;
}
QList<AndroidNetworkInfo> AndroidConnectivityManager::getAllNetworkInfo() const
{
QJNIEnvironmentPrivate env;
QJNIObjectPrivate objArray = m_connectivityManager.callObjectMethod("getAllNetworkInfo",
"()[Landroid/net/NetworkInfo;");
QList<AndroidNetworkInfo> list;
if (!objArray.isValid())
return list;
const jsize length = env->GetArrayLength(static_cast<jarray>(objArray.object()));
if (exceptionCheckAndClear(env))
return list;
for (int i = 0; i != length; ++i) {
jobject lref = env->GetObjectArrayElement(static_cast<jobjectArray>(objArray.object()), i);
if (exceptionCheckAndClear(env))
break;
list << AndroidNetworkInfo(lref);
env->DeleteLocalRef(lref);
}
return list;
}
bool AndroidConnectivityManager::getBackgroundDataSetting() const
{
return m_connectivityManager.callMethod<jboolean>("getBackgroundDataSetting");
}
AndroidNetworkInfo AndroidConnectivityManager::getNetworkInfo(int networkType) const
{
QJNIObjectPrivate networkInfo = m_connectivityManager.callObjectMethod("getNetworkInfo",
"(I)Landroid/net/NetworkInfo;",
networkType);
return networkInfo;
}
int AndroidConnectivityManager::getNetworkPreference() const
{
return m_connectivityManager.callMethod<jint>("getNetworkPreference");
}
bool AndroidConnectivityManager::isActiveNetworkMetered() const
{
// This function was added in JB
if (QtAndroidPrivate::androidSdkVersion() < 16)
return false;
return m_connectivityManager.callMethod<jboolean>("isActiveNetworkMetered");
}
bool AndroidConnectivityManager::isNetworkTypeValid(int networkType)
{
return QJNIObjectPrivate::callStaticMethod<jboolean>("android/net/ConnectivityManager",
"isNetworkTypeValid",
"(I)Z",
networkType);
}
bool AndroidConnectivityManager::requestRouteToHost(int networkType, int hostAddress)
{
return m_connectivityManager.callMethod<jboolean>("requestRouteToHost", "(II)Z", networkType, hostAddress);
}
void AndroidConnectivityManager::setNetworkPreference(int preference)
{
m_connectivityManager.callMethod<void>("setNetworkPreference", "(I)V", preference);
}
int AndroidConnectivityManager::startUsingNetworkFeature(int networkType, const QString &feature)
{
QJNIObjectPrivate jfeature = QJNIObjectPrivate::fromString(feature);
return m_connectivityManager.callMethod<jint>("startUsingNetworkFeature",
"(ILjava/lang/String;)I",
networkType,
jfeature.object());
}
int AndroidConnectivityManager::stopUsingNetworkFeature(int networkType, const QString &feature)
{
QJNIObjectPrivate jfeature = QJNIObjectPrivate::fromString(feature);
return m_connectivityManager.callMethod<jint>("stopUsingNetworkFeature",
"(ILjava/lang/String;)I",
networkType,
jfeature.object());
}
static void activeNetworkInfoChanged()
{
Q_EMIT androidConnManagerInstance->connManager->activeNetworkChanged();
}
bool AndroidConnectivityManager::registerNatives(JNIEnv *env)
{
QJNIObjectPrivate networkReceiver(networkReceiverClass);
if (!networkReceiver.isValid())
return false;
jclass clazz = env->GetObjectClass(networkReceiver.object());
static JNINativeMethod method = {"activeNetworkInfoChanged", "()V", reinterpret_cast<void *>(activeNetworkInfoChanged)};
const bool ret = (env->RegisterNatives(clazz, &method, 1) == JNI_OK);
env->DeleteLocalRef(clazz);
return ret;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,170 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** 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 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 ANDROIDCONNECTIVITYMANAGER_H
#define ANDROIDCONNECTIVITYMANAGER_H
#include <QObject>
#include <QtCore/private/qjni_p.h>
QT_BEGIN_NAMESPACE
class AndroidTrafficStats
{
public:
static qint64 getMobileTxBytes();
static qint64 getMobileRxBytes();
static qint64 getTotalTxBytes();
static qint64 getTotalRxBytes();
static bool isTrafficStatsSupported();
};
class AndroidNetworkInfo
{
public:
// Needs to be in sync with the values from the android api.
enum NetworkState {
UnknownState,
Authenticating,
Blocked,
CaptivePortalCheck,
Connected,
Connecting,
Disconnected,
Disconnecting,
Failed,
Idle,
ObtainingIpAddr,
Scanning,
Suspended,
VerifyingPoorLink
};
enum NetworkType {
Mobile,
Wifi,
MobileMms,
MobileSupl,
MobileDun,
MobileHipri,
Wimax,
Bluetooth,
Dummy,
Ethernet,
UnknownType
};
enum NetworkSubType {
UnknownSubType,
Gprs,
Edge,
Umts,
Cdma,
Evdo0,
EvdoA,
Cdma1xRTT,
Hsdpa,
Hsupa,
Hspa,
Iden,
EvdoB,
Lte,
Ehrpd,
Hspap
};
inline AndroidNetworkInfo(const QJNIObjectPrivate &obj) : m_networkInfo(obj)
{ }
NetworkState getDetailedState() const;
QString getExtraInfo() const;
QString getReason() const;
NetworkState getState() const;
NetworkSubType getSubtype() const;
QString getSubtypeName() const;
NetworkType getType() const;
QString getTypeName() const;
bool isAvailable() const;
bool isConnected() const;
bool isConnectedOrConnecting() const;
bool isFailover() const;
bool isRoaming() const;
bool isValid() const;
private:
QJNIObjectPrivate m_networkInfo;
};
class AndroidConnectivityManager : public QObject
{
Q_OBJECT
public:
static AndroidConnectivityManager *getInstance();
~AndroidConnectivityManager();
AndroidNetworkInfo getActiveNetworkInfo() const;
QList<AndroidNetworkInfo> getAllNetworkInfo() const;
bool getBackgroundDataSetting() const;
AndroidNetworkInfo getNetworkInfo(int networkType) const;
int getNetworkPreference() const;
bool isActiveNetworkMetered() const;
static bool isNetworkTypeValid(int networkType);
bool requestRouteToHost(int networkType, int hostAddress);
void setNetworkPreference(int preference);
int startUsingNetworkFeature(int networkType, const QString &feature);
int stopUsingNetworkFeature(int networkType, const QString &feature);
inline bool isValid() const
{
return m_connectivityManager.isValid();
}
Q_SIGNAL void activeNetworkChanged();
private:
friend struct AndroidConnectivityManagerInstance;
AndroidConnectivityManager();
bool registerNatives(JNIEnv *env);
QJNIObjectPrivate m_connectivityManager;
};
QT_END_NAMESPACE
#endif // ANDROIDCONNECTIVITYMANAGER_H

View File

@ -0,0 +1,6 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/androidconnectivitymanager.h
SOURCES += \
$$PWD/androidconnectivitymanager.cpp

View File

@ -11,5 +11,6 @@ blackberry:SUBDIRS += blackberry
win32:!wince*:SUBDIRS += nativewifi
mac:contains(QT_CONFIG, corewlan):SUBDIRS += corewlan
mac:SUBDIRS += generic
android:!android-no-sdk:SUBDIRS += android
isEmpty(SUBDIRS):SUBDIRS = generic