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
|
||||
\c{TransportMedium::Unknown}.
|
||||
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);
|
||||
connect(backend, &QNetworkInformationBackend::transportMediumChanged, this,
|
||||
&QNetworkInformation::transportMediumChanged);
|
||||
connect(backend, &QNetworkInformationBackend::isMeteredChanged, this,
|
||||
&QNetworkInformation::isMeteredChanged);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -579,6 +586,22 @@ QNetworkInformation::TransportMedium QNetworkInformation::transportMedium() cons
|
||||
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.
|
||||
*/
|
||||
|
@ -58,6 +58,7 @@ class Q_NETWORK_EXPORT QNetworkInformation : public QObject
|
||||
Q_PROPERTY(bool isBehindCaptivePortal READ isBehindCaptivePortal
|
||||
NOTIFY isBehindCaptivePortalChanged)
|
||||
Q_PROPERTY(TransportMedium transportMedium READ transportMedium NOTIFY transportMediumChanged)
|
||||
Q_PROPERTY(bool isMetered READ isMetered NOTIFY isMeteredChanged)
|
||||
public:
|
||||
enum class Reachability {
|
||||
Unknown,
|
||||
@ -81,6 +82,7 @@ public:
|
||||
Reachability = 0x1,
|
||||
CaptivePortal = 0x2,
|
||||
TransportMedium = 0x4,
|
||||
Metered = 0x8,
|
||||
};
|
||||
Q_DECLARE_FLAGS(Features, Feature)
|
||||
Q_FLAG(Features)
|
||||
@ -91,6 +93,8 @@ public:
|
||||
|
||||
TransportMedium transportMedium() const;
|
||||
|
||||
bool isMetered() const;
|
||||
|
||||
QString backendName() const;
|
||||
|
||||
bool supports(Features features) const;
|
||||
@ -106,6 +110,7 @@ Q_SIGNALS:
|
||||
void reachabilityChanged(Reachability newReachability);
|
||||
void isBehindCaptivePortalChanged(bool state);
|
||||
void transportMediumChanged(TransportMedium current);
|
||||
void isMeteredChanged(bool isMetered);
|
||||
|
||||
private:
|
||||
friend struct QNetworkInformationDeleter;
|
||||
|
@ -87,11 +87,13 @@ public:
|
||||
Reachability reachability() const { return m_reachability; }
|
||||
bool behindCaptivePortal() const { return m_behindCaptivePortal; }
|
||||
TransportMedium transportMedium() const { return m_transportMedium; }
|
||||
bool isMetered() const { return m_metered; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void reachabilityChanged(Reachability reachability);
|
||||
void behindCaptivePortalChanged(bool behindPortal);
|
||||
void transportMediumChanged(TransportMedium medium);
|
||||
void isMeteredChanged(bool isMetered);
|
||||
|
||||
protected:
|
||||
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:
|
||||
Reachability m_reachability = Reachability::Unknown;
|
||||
TransportMedium m_transportMedium = TransportMedium::Unknown;
|
||||
bool m_behindCaptivePortal = false;
|
||||
bool m_metered = false;
|
||||
|
||||
Q_DISABLE_COPY_MOVE(QNetworkInformationBackend)
|
||||
friend class QNetworkInformation;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <QtNetwork/private/qnetworkinformation_p.h>
|
||||
#include <QtNetwork/qnetworkinformation.h>
|
||||
#include <QtTest/qtest.h>
|
||||
#include <QtTest/qsignalspy.h>
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@ -43,6 +44,7 @@ private slots:
|
||||
void reachability();
|
||||
void behindCaptivePortal();
|
||||
void transportMedium();
|
||||
void isMetered();
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
@ -88,11 +90,18 @@ public:
|
||||
instance->setTransportMedium(medium);
|
||||
}
|
||||
|
||||
static void setNewMetered(bool metered)
|
||||
{
|
||||
Q_ASSERT(instance);
|
||||
instance->setMetered(metered);
|
||||
}
|
||||
|
||||
static QNetworkInformation::Features featuresSupportedStatic()
|
||||
{
|
||||
return { QNetworkInformation::Feature::Reachability
|
||||
| QNetworkInformation::Feature::CaptivePortal
|
||||
| QNetworkInformation::Feature::TransportMedium };
|
||||
| QNetworkInformation::Feature::TransportMedium
|
||||
| QNetworkInformation::Feature::Metered };
|
||||
}
|
||||
|
||||
private:
|
||||
@ -144,9 +153,10 @@ void tst_QNetworkInformation::supportedFeatures()
|
||||
{
|
||||
auto info = QNetworkInformation::instance();
|
||||
|
||||
auto allFeatures = QNetworkInformation::Features(
|
||||
QNetworkInformation::Feature::CaptivePortal | QNetworkInformation::Feature::Reachability
|
||||
| QNetworkInformation::Feature::TransportMedium);
|
||||
auto allFeatures = QNetworkInformation::Features(QNetworkInformation::Feature::CaptivePortal
|
||||
| QNetworkInformation::Feature::Reachability
|
||||
| QNetworkInformation::Feature::TransportMedium
|
||||
| QNetworkInformation::Feature::Metered);
|
||||
|
||||
QCOMPARE(info->supportedFeatures(), allFeatures);
|
||||
|
||||
@ -154,6 +164,7 @@ void tst_QNetworkInformation::supportedFeatures()
|
||||
QVERIFY(info->supports(QNetworkInformation::Feature::CaptivePortal));
|
||||
QVERIFY(info->supports(QNetworkInformation::Feature::Reachability));
|
||||
QVERIFY(info->supports(QNetworkInformation::Feature::TransportMedium));
|
||||
QVERIFY(info->supports(QNetworkInformation::Feature::Metered));
|
||||
}
|
||||
|
||||
void tst_QNetworkInformation::reachability()
|
||||
@ -248,5 +259,22 @@ void tst_QNetworkInformation::transportMedium()
|
||||
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);
|
||||
#include "tst_qnetworkinformation.moc"
|
||||
|
@ -74,13 +74,20 @@ public slots:
|
||||
updateText();
|
||||
}
|
||||
|
||||
void updateMetered(bool newValue)
|
||||
{
|
||||
metered = newValue;
|
||||
updateText();
|
||||
}
|
||||
|
||||
private:
|
||||
void updateText()
|
||||
{
|
||||
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"),
|
||||
enumToString(transportMedium));
|
||||
enumToString(transportMedium), metered ? u"true" : u"false");
|
||||
label->setText(str);
|
||||
}
|
||||
|
||||
@ -88,6 +95,7 @@ private:
|
||||
Reachability reachability = Reachability::Unknown;
|
||||
TransportMedium transportMedium = TransportMedium::Unknown;
|
||||
bool captive = false;
|
||||
bool metered = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -70,6 +70,11 @@ int main(int argc, char **argv)
|
||||
qDebug() << "Updated, current transport medium:" << newMedium;
|
||||
});
|
||||
|
||||
QObject::connect(info, &QNetworkInformation::isMeteredChanged,
|
||||
[](bool metered) {
|
||||
qDebug() << "Updated, metered:" << metered;
|
||||
});
|
||||
|
||||
#ifdef MOBILE
|
||||
// Some extra connections to update the window if we're on mobile
|
||||
QObject::connect(info, &QNetworkInformation::reachabilityChanged, &window,
|
||||
@ -78,11 +83,14 @@ int main(int argc, char **argv)
|
||||
&MainWindow::updateCaptiveState);
|
||||
QObject::connect(info, &QNetworkInformation::transportMediumChanged, &window,
|
||||
&MainWindow::updateTransportMedium);
|
||||
QObject::connect(info, &QNetworkInformation::isMeteredChanged, &window,
|
||||
&MainWindow::updateMetered);
|
||||
#endif
|
||||
|
||||
qDebug() << "Initial reachability:" << info->reachability();
|
||||
qDebug() << "Behind captive portal:" << info->isBehindCaptivePortal();
|
||||
qDebug() << "Transport medium:" << info->transportMedium();
|
||||
qDebug() << "Is metered:" << info->isMetered();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user