mplement platform helper on ios

pull/42/head
nymea 2018-09-19 15:21:12 +02:00 committed by Michael Zanetti
parent 1fb2d43bec
commit 3ac8570f4a
7 changed files with 162 additions and 15 deletions

View File

@ -614,7 +614,7 @@ void AWSClient::registerPushNotificationEndpoint(const QString &registrationId,
if (tokensExpired()) {
qDebug() << "Cannot register push endpoint. Need to refresh our tokens";
refreshAccessToken();
m_callQueue.append(QueuedCall("registerPushNotificationEndpoint", registrationId));
m_callQueue.append(QueuedCall("registerPushNotificationEndpoint", registrationId, deviceDisplayName, mobileDeviceId));
return;
}
@ -623,11 +623,6 @@ void AWSClient::registerPushNotificationEndpoint(const QString &registrationId,
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
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;
payload.insert("registrationId", registrationId);
@ -640,7 +635,13 @@ void AWSClient::registerPushNotificationEndpoint(const QString &registrationId,
payload.insert("mobileDeviceUuid", mobileDeviceId);
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));
connect(reply, &QNetworkReply::finished, this, [reply]() {
@ -784,9 +785,11 @@ void AWSClient::getCredentialsForIdentity(const QString &identityId)
if (qc.method == "fetchDevices") {
fetchDevices();
} else if (qc.method == "postToMQTT") {
postToMQTT(qc.boxId, qc.timestamp, qc.callback);
postToMQTT(qc.arg1, qc.arg2, qc.callback);
} else if (qc.method == "deleteAccount") {
deleteAccount();
} else if (qc.method == "registerPushNotificationEndpoint") {
registerPushNotificationEndpoint(qc.arg1, qc.arg2, qc.arg3);
}
}
});

View File

@ -175,11 +175,13 @@ private:
class QueuedCall {
public:
QueuedCall(const QString &method): method(method) { }
QueuedCall(const QString &method, const QString &boxId): method(method), boxId(boxId) { }
QueuedCall(const QString &method, const QString &boxId, const QString &timestamp, std::function<void(bool)> callback): method(method), boxId(boxId), timestamp(timestamp), callback(callback) {}
QueuedCall(const QString &method, const QString &arg1): method(method), arg1(arg1) { }
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 boxId;
QString timestamp;
QString arg1;
QString arg2;
QString arg3;
std::function<void(bool)> callback;
};

View File

@ -28,6 +28,8 @@
#ifdef Q_OS_ANDROID
#include <QtAndroidExtras/QtAndroid>
#include "platformintegration/android/platformhelperandroid.h"
#elif defined(Q_OS_IOS)
#include "platformintegration/ios/platformhelperios.h"
#else
#include "platformintegration/generic/platformhelpergeneric.h"
#endif
@ -44,6 +46,8 @@ QObject *platformHelperProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
Q_UNUSED(scriptEngine)
#ifdef Q_OS_ANDROID
return new PlatformHelperAndroid();
#elif defined(Q_OS_IOS)
return new PlatformHelperIOS();
#else
return new PlatformHelperGeneric();
#endif

View File

@ -20,13 +20,15 @@ HEADERS += \
stylecontroller.h \
pushnotifications.h \
platformhelper.h \
platformintegration/generic/platformhelpergeneric.h
platformintegration/generic/platformhelpergeneric.h \
platformintegration/ios/platformhelperios.h
SOURCES += main.cpp \
stylecontroller.cpp \
pushnotifications.cpp \
platformhelper.cpp \
platformintegration/generic/platformhelpergeneric.cpp
platformintegration/generic/platformhelpergeneric.cpp \
platformintegration/ios/platformhelperios.cpp
OTHER_FILES += $$files(*.qml, true)
@ -102,7 +104,8 @@ ios: {
IOS_ENTITLEMENTS.value = $$files($$PWD/../packaging/ios/pushnotifications.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

View 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");
}

View 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

View 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;
}
}