QNI: Add API to check if connection is metered
This may be a useful factor in deciding whether or not you should perform communications over the network which are not purely essential. For example, if you have a logging mechanism you can delay uploading them until you are no longer on a metered network. Task-number: QTBUG-91024 Change-Id: I19d32f031a3893512dc440914133678004987fb1 Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
2148e1f0e6
commit
bd52c1bba6
@ -457,6 +457,11 @@ QNetworkInformationBackendFactory::~QNetworkInformationBackendFactory()
|
|||||||
property will provide useful results. Otherwise it will always return
|
property will provide useful results. Otherwise it will always return
|
||||||
\c{TransportMedium::Unknown}.
|
\c{TransportMedium::Unknown}.
|
||||||
See also QNetworkInformation::TransportMedium.
|
See also QNetworkInformation::TransportMedium.
|
||||||
|
|
||||||
|
\value Metered
|
||||||
|
If the plugin supports this feature then the \c isMetered
|
||||||
|
property will provide useful results. Otherwise it will always return
|
||||||
|
\c{false}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -520,6 +525,8 @@ QNetworkInformation::QNetworkInformation(QNetworkInformationBackend *backend)
|
|||||||
&QNetworkInformation::isBehindCaptivePortalChanged);
|
&QNetworkInformation::isBehindCaptivePortalChanged);
|
||||||
connect(backend, &QNetworkInformationBackend::transportMediumChanged, this,
|
connect(backend, &QNetworkInformationBackend::transportMediumChanged, this,
|
||||||
&QNetworkInformation::transportMediumChanged);
|
&QNetworkInformation::transportMediumChanged);
|
||||||
|
connect(backend, &QNetworkInformationBackend::isMeteredChanged, this,
|
||||||
|
&QNetworkInformation::isMeteredChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -579,6 +586,22 @@ QNetworkInformation::TransportMedium QNetworkInformation::transportMedium() cons
|
|||||||
return d_func()->backend->transportMedium();
|
return d_func()->backend->transportMedium();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QNetworkInformation::isMetered
|
||||||
|
\brief Check if the current connection is metered
|
||||||
|
\since 6.3
|
||||||
|
|
||||||
|
This property returns whether the current connection is (known to be)
|
||||||
|
metered or not. You can use this as a guiding factor to decide whether your
|
||||||
|
application should perform certain network requests or uploads.
|
||||||
|
For instance, you may not want to upload logs or diagnostics while this
|
||||||
|
property is \c true.
|
||||||
|
*/
|
||||||
|
bool QNetworkInformation::isMetered() const
|
||||||
|
{
|
||||||
|
return d_func()->backend->isMetered();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the name of the currently loaded backend.
|
Returns the name of the currently loaded backend.
|
||||||
*/
|
*/
|
||||||
|
@ -58,6 +58,7 @@ class Q_NETWORK_EXPORT QNetworkInformation : public QObject
|
|||||||
Q_PROPERTY(bool isBehindCaptivePortal READ isBehindCaptivePortal
|
Q_PROPERTY(bool isBehindCaptivePortal READ isBehindCaptivePortal
|
||||||
NOTIFY isBehindCaptivePortalChanged)
|
NOTIFY isBehindCaptivePortalChanged)
|
||||||
Q_PROPERTY(TransportMedium transportMedium READ transportMedium NOTIFY transportMediumChanged)
|
Q_PROPERTY(TransportMedium transportMedium READ transportMedium NOTIFY transportMediumChanged)
|
||||||
|
Q_PROPERTY(bool isMetered READ isMetered NOTIFY isMeteredChanged)
|
||||||
public:
|
public:
|
||||||
enum class Reachability {
|
enum class Reachability {
|
||||||
Unknown,
|
Unknown,
|
||||||
@ -81,6 +82,7 @@ public:
|
|||||||
Reachability = 0x1,
|
Reachability = 0x1,
|
||||||
CaptivePortal = 0x2,
|
CaptivePortal = 0x2,
|
||||||
TransportMedium = 0x4,
|
TransportMedium = 0x4,
|
||||||
|
Metered = 0x8,
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Features, Feature)
|
Q_DECLARE_FLAGS(Features, Feature)
|
||||||
Q_FLAG(Features)
|
Q_FLAG(Features)
|
||||||
@ -91,6 +93,8 @@ public:
|
|||||||
|
|
||||||
TransportMedium transportMedium() const;
|
TransportMedium transportMedium() const;
|
||||||
|
|
||||||
|
bool isMetered() const;
|
||||||
|
|
||||||
QString backendName() const;
|
QString backendName() const;
|
||||||
|
|
||||||
bool supports(Features features) const;
|
bool supports(Features features) const;
|
||||||
@ -106,6 +110,7 @@ Q_SIGNALS:
|
|||||||
void reachabilityChanged(Reachability newReachability);
|
void reachabilityChanged(Reachability newReachability);
|
||||||
void isBehindCaptivePortalChanged(bool state);
|
void isBehindCaptivePortalChanged(bool state);
|
||||||
void transportMediumChanged(TransportMedium current);
|
void transportMediumChanged(TransportMedium current);
|
||||||
|
void isMeteredChanged(bool isMetered);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct QNetworkInformationDeleter;
|
friend struct QNetworkInformationDeleter;
|
||||||
|
@ -87,11 +87,13 @@ public:
|
|||||||
Reachability reachability() const { return m_reachability; }
|
Reachability reachability() const { return m_reachability; }
|
||||||
bool behindCaptivePortal() const { return m_behindCaptivePortal; }
|
bool behindCaptivePortal() const { return m_behindCaptivePortal; }
|
||||||
TransportMedium transportMedium() const { return m_transportMedium; }
|
TransportMedium transportMedium() const { return m_transportMedium; }
|
||||||
|
bool isMetered() const { return m_metered; }
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void reachabilityChanged(Reachability reachability);
|
void reachabilityChanged(Reachability reachability);
|
||||||
void behindCaptivePortalChanged(bool behindPortal);
|
void behindCaptivePortalChanged(bool behindPortal);
|
||||||
void transportMediumChanged(TransportMedium medium);
|
void transportMediumChanged(TransportMedium medium);
|
||||||
|
void isMeteredChanged(bool isMetered);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setReachability(QNetworkInformation::Reachability reachability)
|
void setReachability(QNetworkInformation::Reachability reachability)
|
||||||
@ -118,10 +120,19 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setMetered(bool isMetered)
|
||||||
|
{
|
||||||
|
if (m_metered != isMetered) {
|
||||||
|
m_metered = isMetered;
|
||||||
|
emit isMeteredChanged(isMetered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Reachability m_reachability = Reachability::Unknown;
|
Reachability m_reachability = Reachability::Unknown;
|
||||||
TransportMedium m_transportMedium = TransportMedium::Unknown;
|
TransportMedium m_transportMedium = TransportMedium::Unknown;
|
||||||
bool m_behindCaptivePortal = false;
|
bool m_behindCaptivePortal = false;
|
||||||
|
bool m_metered = false;
|
||||||
|
|
||||||
Q_DISABLE_COPY_MOVE(QNetworkInformationBackend)
|
Q_DISABLE_COPY_MOVE(QNetworkInformationBackend)
|
||||||
friend class QNetworkInformation;
|
friend class QNetworkInformation;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <QtNetwork/private/qnetworkinformation_p.h>
|
#include <QtNetwork/private/qnetworkinformation_p.h>
|
||||||
#include <QtNetwork/qnetworkinformation.h>
|
#include <QtNetwork/qnetworkinformation.h>
|
||||||
#include <QtTest/qtest.h>
|
#include <QtTest/qtest.h>
|
||||||
|
#include <QtTest/qsignalspy.h>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -43,6 +44,7 @@ private slots:
|
|||||||
void reachability();
|
void reachability();
|
||||||
void behindCaptivePortal();
|
void behindCaptivePortal();
|
||||||
void transportMedium();
|
void transportMedium();
|
||||||
|
void isMetered();
|
||||||
void cleanupTestCase();
|
void cleanupTestCase();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -88,11 +90,18 @@ public:
|
|||||||
instance->setTransportMedium(medium);
|
instance->setTransportMedium(medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setNewMetered(bool metered)
|
||||||
|
{
|
||||||
|
Q_ASSERT(instance);
|
||||||
|
instance->setMetered(metered);
|
||||||
|
}
|
||||||
|
|
||||||
static QNetworkInformation::Features featuresSupportedStatic()
|
static QNetworkInformation::Features featuresSupportedStatic()
|
||||||
{
|
{
|
||||||
return { QNetworkInformation::Feature::Reachability
|
return { QNetworkInformation::Feature::Reachability
|
||||||
| QNetworkInformation::Feature::CaptivePortal
|
| QNetworkInformation::Feature::CaptivePortal
|
||||||
| QNetworkInformation::Feature::TransportMedium };
|
| QNetworkInformation::Feature::TransportMedium
|
||||||
|
| QNetworkInformation::Feature::Metered };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -144,9 +153,10 @@ void tst_QNetworkInformation::supportedFeatures()
|
|||||||
{
|
{
|
||||||
auto info = QNetworkInformation::instance();
|
auto info = QNetworkInformation::instance();
|
||||||
|
|
||||||
auto allFeatures = QNetworkInformation::Features(
|
auto allFeatures = QNetworkInformation::Features(QNetworkInformation::Feature::CaptivePortal
|
||||||
QNetworkInformation::Feature::CaptivePortal | QNetworkInformation::Feature::Reachability
|
| QNetworkInformation::Feature::Reachability
|
||||||
| QNetworkInformation::Feature::TransportMedium);
|
| QNetworkInformation::Feature::TransportMedium
|
||||||
|
| QNetworkInformation::Feature::Metered);
|
||||||
|
|
||||||
QCOMPARE(info->supportedFeatures(), allFeatures);
|
QCOMPARE(info->supportedFeatures(), allFeatures);
|
||||||
|
|
||||||
@ -154,6 +164,7 @@ void tst_QNetworkInformation::supportedFeatures()
|
|||||||
QVERIFY(info->supports(QNetworkInformation::Feature::CaptivePortal));
|
QVERIFY(info->supports(QNetworkInformation::Feature::CaptivePortal));
|
||||||
QVERIFY(info->supports(QNetworkInformation::Feature::Reachability));
|
QVERIFY(info->supports(QNetworkInformation::Feature::Reachability));
|
||||||
QVERIFY(info->supports(QNetworkInformation::Feature::TransportMedium));
|
QVERIFY(info->supports(QNetworkInformation::Feature::TransportMedium));
|
||||||
|
QVERIFY(info->supports(QNetworkInformation::Feature::Metered));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QNetworkInformation::reachability()
|
void tst_QNetworkInformation::reachability()
|
||||||
@ -248,5 +259,22 @@ void tst_QNetworkInformation::transportMedium()
|
|||||||
QVERIFY(!signalEmitted);
|
QVERIFY(!signalEmitted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QNetworkInformation::isMetered()
|
||||||
|
{
|
||||||
|
auto info = QNetworkInformation::instance();
|
||||||
|
|
||||||
|
QSignalSpy spy(info, &QNetworkInformation::isMeteredChanged);
|
||||||
|
QVERIFY(!info->isMetered());
|
||||||
|
MockBackend::setNewMetered(true);
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
QVERIFY(info->isMetered());
|
||||||
|
QVERIFY(spy[0][0].toBool());
|
||||||
|
spy.clear();
|
||||||
|
|
||||||
|
// Set the same value again, signal should not be emitted again
|
||||||
|
MockBackend::setNewMetered(true);
|
||||||
|
QCOMPARE(spy.count(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QNetworkInformation);
|
QTEST_MAIN(tst_QNetworkInformation);
|
||||||
#include "tst_qnetworkinformation.moc"
|
#include "tst_qnetworkinformation.moc"
|
||||||
|
@ -74,13 +74,20 @@ public slots:
|
|||||||
updateText();
|
updateText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateMetered(bool newValue)
|
||||||
|
{
|
||||||
|
metered = newValue;
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateText()
|
void updateText()
|
||||||
{
|
{
|
||||||
QString str =
|
QString str =
|
||||||
QLatin1String("Reachability: %1\nBehind captive portal: %2\nTransport medium: %3")
|
QLatin1String("Reachability: %1\nBehind captive portal: %2\nTransport medium: %3"
|
||||||
|
"\nMetered: %4")
|
||||||
.arg(enumToString(reachability), QStringView(captive ? u"true" : u"false"),
|
.arg(enumToString(reachability), QStringView(captive ? u"true" : u"false"),
|
||||||
enumToString(transportMedium));
|
enumToString(transportMedium), metered ? u"true" : u"false");
|
||||||
label->setText(str);
|
label->setText(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +95,7 @@ private:
|
|||||||
Reachability reachability = Reachability::Unknown;
|
Reachability reachability = Reachability::Unknown;
|
||||||
TransportMedium transportMedium = TransportMedium::Unknown;
|
TransportMedium transportMedium = TransportMedium::Unknown;
|
||||||
bool captive = false;
|
bool captive = false;
|
||||||
|
bool metered = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,6 +70,11 @@ int main(int argc, char **argv)
|
|||||||
qDebug() << "Updated, current transport medium:" << newMedium;
|
qDebug() << "Updated, current transport medium:" << newMedium;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QObject::connect(info, &QNetworkInformation::isMeteredChanged,
|
||||||
|
[](bool metered) {
|
||||||
|
qDebug() << "Updated, metered:" << metered;
|
||||||
|
});
|
||||||
|
|
||||||
#ifdef MOBILE
|
#ifdef MOBILE
|
||||||
// Some extra connections to update the window if we're on mobile
|
// Some extra connections to update the window if we're on mobile
|
||||||
QObject::connect(info, &QNetworkInformation::reachabilityChanged, &window,
|
QObject::connect(info, &QNetworkInformation::reachabilityChanged, &window,
|
||||||
@ -78,11 +83,14 @@ int main(int argc, char **argv)
|
|||||||
&MainWindow::updateCaptiveState);
|
&MainWindow::updateCaptiveState);
|
||||||
QObject::connect(info, &QNetworkInformation::transportMediumChanged, &window,
|
QObject::connect(info, &QNetworkInformation::transportMediumChanged, &window,
|
||||||
&MainWindow::updateTransportMedium);
|
&MainWindow::updateTransportMedium);
|
||||||
|
QObject::connect(info, &QNetworkInformation::isMeteredChanged, &window,
|
||||||
|
&MainWindow::updateMetered);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qDebug() << "Initial reachability:" << info->reachability();
|
qDebug() << "Initial reachability:" << info->reachability();
|
||||||
qDebug() << "Behind captive portal:" << info->isBehindCaptivePortal();
|
qDebug() << "Behind captive portal:" << info->isBehindCaptivePortal();
|
||||||
qDebug() << "Transport medium:" << info->transportMedium();
|
qDebug() << "Transport medium:" << info->transportMedium();
|
||||||
|
qDebug() << "Is metered:" << info->isMetered();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user