mplement platform helper on ios
This commit is contained in:
parent
1fb2d43bec
commit
3ac8570f4a
@ -614,7 +614,7 @@ void AWSClient::registerPushNotificationEndpoint(const QString ®istrationId,
|
|||||||
if (tokensExpired()) {
|
if (tokensExpired()) {
|
||||||
qDebug() << "Cannot register push endpoint. Need to refresh our tokens";
|
qDebug() << "Cannot register push endpoint. Need to refresh our tokens";
|
||||||
refreshAccessToken();
|
refreshAccessToken();
|
||||||
m_callQueue.append(QueuedCall("registerPushNotificationEndpoint", registrationId));
|
m_callQueue.append(QueuedCall("registerPushNotificationEndpoint", registrationId, deviceDisplayName, mobileDeviceId));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,11 +623,6 @@ void AWSClient::registerPushNotificationEndpoint(const QString ®istrationId,
|
|||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
request.setRawHeader("x-api-idToken", m_idToken);
|
request.setRawHeader("x-api-idToken", m_idToken);
|
||||||
|
|
||||||
// qDebug() << "POST" << url.toString();
|
|
||||||
// qDebug() << "HEADERS:";
|
|
||||||
// foreach (const QByteArray &hdr, request.rawHeaderList()) {
|
|
||||||
// qDebug() << hdr << ":" << request.rawHeader(hdr);
|
|
||||||
// }
|
|
||||||
|
|
||||||
QVariantMap payload;
|
QVariantMap payload;
|
||||||
payload.insert("registrationId", registrationId);
|
payload.insert("registrationId", registrationId);
|
||||||
@ -640,7 +635,13 @@ void AWSClient::registerPushNotificationEndpoint(const QString ®istrationId,
|
|||||||
payload.insert("mobileDeviceUuid", mobileDeviceId);
|
payload.insert("mobileDeviceUuid", mobileDeviceId);
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(payload);
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(payload);
|
||||||
|
|
||||||
qDebug() << "Registering push notification endpoint:" << payload.value("channel").toString();
|
qDebug() << "Registering push notification endpoint:";
|
||||||
|
qDebug() << "POST" << url.toString();
|
||||||
|
qDebug() << "HEADERS:";
|
||||||
|
foreach (const QByteArray &hdr, request.rawHeaderList()) {
|
||||||
|
qDebug() << hdr << ":" << request.rawHeader(hdr);
|
||||||
|
}
|
||||||
|
qDebug() << "Payload:" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
QNetworkReply *reply = m_nam->post(request, jsonDoc.toJson(QJsonDocument::Compact));
|
QNetworkReply *reply = m_nam->post(request, jsonDoc.toJson(QJsonDocument::Compact));
|
||||||
connect(reply, &QNetworkReply::finished, this, [reply]() {
|
connect(reply, &QNetworkReply::finished, this, [reply]() {
|
||||||
@ -784,9 +785,11 @@ void AWSClient::getCredentialsForIdentity(const QString &identityId)
|
|||||||
if (qc.method == "fetchDevices") {
|
if (qc.method == "fetchDevices") {
|
||||||
fetchDevices();
|
fetchDevices();
|
||||||
} else if (qc.method == "postToMQTT") {
|
} else if (qc.method == "postToMQTT") {
|
||||||
postToMQTT(qc.boxId, qc.timestamp, qc.callback);
|
postToMQTT(qc.arg1, qc.arg2, qc.callback);
|
||||||
} else if (qc.method == "deleteAccount") {
|
} else if (qc.method == "deleteAccount") {
|
||||||
deleteAccount();
|
deleteAccount();
|
||||||
|
} else if (qc.method == "registerPushNotificationEndpoint") {
|
||||||
|
registerPushNotificationEndpoint(qc.arg1, qc.arg2, qc.arg3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -175,11 +175,13 @@ private:
|
|||||||
class QueuedCall {
|
class QueuedCall {
|
||||||
public:
|
public:
|
||||||
QueuedCall(const QString &method): method(method) { }
|
QueuedCall(const QString &method): method(method) { }
|
||||||
QueuedCall(const QString &method, const QString &boxId): method(method), boxId(boxId) { }
|
QueuedCall(const QString &method, const QString &arg1): method(method), arg1(arg1) { }
|
||||||
QueuedCall(const QString &method, const QString &boxId, const QString ×tamp, std::function<void(bool)> callback): method(method), boxId(boxId), timestamp(timestamp), callback(callback) {}
|
QueuedCall(const QString &method, const QString &arg1, const QString &arg2, const QString &arg3): method(method), arg1(arg1), arg2(arg2), arg3(arg3) { }
|
||||||
|
QueuedCall(const QString &method, const QString &arg1, const QString &arg2, std::function<void(bool)> callback): method(method), arg1(arg1), arg2(arg2), callback(callback) {}
|
||||||
QString method;
|
QString method;
|
||||||
QString boxId;
|
QString arg1;
|
||||||
QString timestamp;
|
QString arg2;
|
||||||
|
QString arg3;
|
||||||
std::function<void(bool)> callback;
|
std::function<void(bool)> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,8 @@
|
|||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include <QtAndroidExtras/QtAndroid>
|
#include <QtAndroidExtras/QtAndroid>
|
||||||
#include "platformintegration/android/platformhelperandroid.h"
|
#include "platformintegration/android/platformhelperandroid.h"
|
||||||
|
#elif defined(Q_OS_IOS)
|
||||||
|
#include "platformintegration/ios/platformhelperios.h"
|
||||||
#else
|
#else
|
||||||
#include "platformintegration/generic/platformhelpergeneric.h"
|
#include "platformintegration/generic/platformhelpergeneric.h"
|
||||||
#endif
|
#endif
|
||||||
@ -44,6 +46,8 @@ QObject *platformHelperProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
|
|||||||
Q_UNUSED(scriptEngine)
|
Q_UNUSED(scriptEngine)
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
return new PlatformHelperAndroid();
|
return new PlatformHelperAndroid();
|
||||||
|
#elif defined(Q_OS_IOS)
|
||||||
|
return new PlatformHelperIOS();
|
||||||
#else
|
#else
|
||||||
return new PlatformHelperGeneric();
|
return new PlatformHelperGeneric();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -20,13 +20,15 @@ HEADERS += \
|
|||||||
stylecontroller.h \
|
stylecontroller.h \
|
||||||
pushnotifications.h \
|
pushnotifications.h \
|
||||||
platformhelper.h \
|
platformhelper.h \
|
||||||
platformintegration/generic/platformhelpergeneric.h
|
platformintegration/generic/platformhelpergeneric.h \
|
||||||
|
platformintegration/ios/platformhelperios.h
|
||||||
|
|
||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
stylecontroller.cpp \
|
stylecontroller.cpp \
|
||||||
pushnotifications.cpp \
|
pushnotifications.cpp \
|
||||||
platformhelper.cpp \
|
platformhelper.cpp \
|
||||||
platformintegration/generic/platformhelpergeneric.cpp
|
platformintegration/generic/platformhelpergeneric.cpp \
|
||||||
|
platformintegration/ios/platformhelperios.cpp
|
||||||
|
|
||||||
OTHER_FILES += $$files(*.qml, true)
|
OTHER_FILES += $$files(*.qml, true)
|
||||||
|
|
||||||
@ -102,7 +104,8 @@ ios: {
|
|||||||
IOS_ENTITLEMENTS.value = $$files($$PWD/../packaging/ios/pushnotifications.entitlements)
|
IOS_ENTITLEMENTS.value = $$files($$PWD/../packaging/ios/pushnotifications.entitlements)
|
||||||
QMAKE_MAC_XCODE_SETTINGS += IOS_ENTITLEMENTS
|
QMAKE_MAC_XCODE_SETTINGS += IOS_ENTITLEMENTS
|
||||||
|
|
||||||
OBJECTIVE_SOURCES += $$PWD/../packaging/ios/pushnotifications.mm
|
OBJECTIVE_SOURCES += $$PWD/../packaging/ios/pushnotifications.mm \
|
||||||
|
$$PWD/../packaging/ios/platformhelperios.mm
|
||||||
}
|
}
|
||||||
|
|
||||||
BR=$$BRANDING
|
BR=$$BRANDING
|
||||||
|
|||||||
41
nymea-app/platformintegration/ios/platformhelperios.cpp
Normal file
41
nymea-app/platformintegration/ios/platformhelperios.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include "platformhelperios.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
|
PlatformHelperIOS::PlatformHelperIOS(QObject *parent) : PlatformHelper(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformHelperIOS::requestPermissions()
|
||||||
|
{
|
||||||
|
emit permissionsRequestFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlatformHelperIOS::hasPermissions() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PlatformHelperIOS::deviceSerial() const
|
||||||
|
{
|
||||||
|
QString deviceId = const_cast<PlatformHelperIOS*>(this)->readKeyChainEntry("io.guh.nymea-app", "deviceId");
|
||||||
|
qDebug() << "read keychain value:" << deviceId;
|
||||||
|
if (deviceId.isEmpty()) {
|
||||||
|
deviceId = QUuid::createUuid().toString();
|
||||||
|
const_cast<PlatformHelperIOS*>(this)->writeKeyChainEntry("io.guh.nymea-app", "deviceId", deviceId);
|
||||||
|
}
|
||||||
|
qDebug() << "Returning device ID" << deviceId;
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PlatformHelperIOS::deviceModel() const
|
||||||
|
{
|
||||||
|
qDebug() << "SYSINFO:" << QSysInfo::productType() << QSysInfo::prettyProductName() << QSysInfo::productVersion();
|
||||||
|
return QSysInfo::prettyProductName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PlatformHelperIOS::deviceManufacturer() const
|
||||||
|
{
|
||||||
|
return QString("iPhone");
|
||||||
|
}
|
||||||
27
nymea-app/platformintegration/ios/platformhelperios.h
Normal file
27
nymea-app/platformintegration/ios/platformhelperios.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef PLATFORMHELPERIOS_H
|
||||||
|
#define PLATFORMHELPERIOS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "platformhelper.h"
|
||||||
|
|
||||||
|
class PlatformHelperIOS : public PlatformHelper
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit PlatformHelperIOS(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Q_INVOKABLE virtual void requestPermissions() override;
|
||||||
|
|
||||||
|
virtual bool hasPermissions() const override;
|
||||||
|
virtual QString deviceSerial() const override;
|
||||||
|
virtual QString deviceModel() const override;
|
||||||
|
virtual QString deviceManufacturer() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// defined in platformhelperios.mm
|
||||||
|
QString readKeyChainEntry(const QString &service, const QString &key);
|
||||||
|
void writeKeyChainEntry(const QString &service, const QString &key, const QString &value);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLATFORMHELPERIOS_H
|
||||||
67
packaging/ios/platformhelperios.mm
Normal file
67
packaging/ios/platformhelperios.mm
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Security/Security.h>
|
||||||
|
|
||||||
|
#include <QtDebug>
|
||||||
|
#include "platformintegration/ios/platformhelperios.h"
|
||||||
|
|
||||||
|
QString PlatformHelperIOS::readKeyChainEntry(const QString &service, const QString &key)
|
||||||
|
{
|
||||||
|
NSDictionary *const query = @{
|
||||||
|
(__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
|
||||||
|
(__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
|
||||||
|
(__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
|
||||||
|
(__bridge id) kSecReturnData: @YES,
|
||||||
|
};
|
||||||
|
|
||||||
|
CFTypeRef dataRef = nil;
|
||||||
|
const OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &dataRef);
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
if (status == errSecSuccess) {
|
||||||
|
if (dataRef)
|
||||||
|
data = QByteArray::fromCFData((CFDataRef) dataRef);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qWarning() << "Error accessing keychain value" << status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataRef)
|
||||||
|
[dataRef release];
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlatformHelperIOS::writeKeyChainEntry(const QString &service, const QString &key, const QString &value)
|
||||||
|
{
|
||||||
|
NSDictionary *const query = @{
|
||||||
|
(__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
|
||||||
|
(__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
|
||||||
|
(__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, nil);
|
||||||
|
|
||||||
|
if (status == errSecSuccess) {
|
||||||
|
NSDictionary *const update = @{
|
||||||
|
(__bridge id) kSecValueData: (__bridge NSData *) value.toUtf8().toCFData(),
|
||||||
|
};
|
||||||
|
|
||||||
|
status = SecItemUpdate((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) update);
|
||||||
|
} else {
|
||||||
|
NSDictionary *const insert = @{
|
||||||
|
(__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
|
||||||
|
(__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
|
||||||
|
(__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
|
||||||
|
(__bridge id) kSecValueData: (__bridge NSData *) value.toUtf8().toCFData(),
|
||||||
|
};
|
||||||
|
|
||||||
|
status = SecItemAdd((__bridge CFDictionaryRef) insert, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == errSecSuccess) {
|
||||||
|
qDebug() << "Successfully stored value in keychain";
|
||||||
|
} else {
|
||||||
|
qWarning() << "Error storing value in keycahin" << status;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user