Unsolved UIApplication.shared.canOpenURL implements in Qt
-
@SGaist said in UIApplication.shared.canOpenURL implements in Qt:
NSUrl
Thank you, It was a good progress for first step.
But we have error and cannot compile it.Error:
Code of .pro file:
QT += widgets quick webview CONFIG += c++17 DEFINES += QT_DEPRECATED_WARNINGS LIBS += -framework Foundation SOURCES += \ HandleURL.mm \ main.cpp \ RESOURCES += qml.qrc QML_IMPORT_PATH = QML_DESIGNER_IMPORT_PATH = # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target contains(ANDROID_TARGET_ARCH,arm64-v8a) { ANDROID_ARM64 = 1 ANDROID_EXTRA_LIBS = \ $$PWD/openssl-1.1.1a-clang/arm64-v8a/lib/libcrypto.so \ $$PWD/openssl-1.1.1a-clang/arm64-v8a/lib/libssl.so ANDROID_PACKAGE_SOURCE_DIR = \ $$PWD/android } contains(ANDROID_TARGET_ARCH,armeabi-v7a) { ANDROID_EXTRA_LIBS = \ $$PWD/openssl-1.1.1a-clang/armeabi-v7a/lib/libcrypto.so \ $$PWD/openssl-1.1.1a-clang/armeabi-v7a/lib/libssl.so ANDROID_PACKAGE_SOURCE_DIR = \ $$PWD/android } DISTFILES += \ android/AndroidManifest.xml \ android/build.gradle \ android/gradle/wrapper/gradle-wrapper.jar \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradlew \ android/gradlew.bat \ android/res/values/libs.xml defineReplace(droidVersionCode) { segments = $$split(1, ".") for(segment, segments): vCode = "$$first(vCode)$$format_number($$segment, width=3 zeropad)" ## arm64-v8a, armeabi-v7a contains(ANDROID_TARGET_ARCH, arm64-v8a): \ suffix = 1 else:contains(ANDROID_TARGET_ARCH, armeabi-v7a): \ suffix = 0 return($$first(vCode)$$first(suffix)) } ios { QMAKE_INFO_PLIST = ios/info.plist } VERSION = 1.2.3 ANDROID_VERSION_NAME = $$VERSION ANDROID_VERSION_CODE = $$droidVersionCode($$ANDROID_VERSION_NAME) HEADERS += \ HandleURL.hpp
HandleURL.mm file:
#include <QDebug> #include <QUrlQuery> #include <QUrl> #include <QDesktopServices> #include "HandleURL.hpp" #import <Foundation/NSUserNotification.h> #import <AppKit/NSApplication.h> #import <Foundation/Foundation.h> void HandleURL::handleURL(const QUrl &url) { // parse it... // protclname://methodName?token=dfgdfgdfgdfg&callbackurl=https%3A%2F%2Fgoogle.test.com QUrlQuery query(url); // qDebug() << url.toString(); // qDebug() << query.queryItemValue("callbackurl"); // qDebug() << QUrl::toString(...); // NSUrl *urls = url.toNSUrl(); //NSUrl *urls = url.toString().toNSUrl(); NSUrl *urls = url.toNSUrl(); bool canOpen = [[NSApplication shared] canOpenUrl: urls]; qDebug() << canOpen; if(canOpen) { QDesktopServices::openUrl(url); } emit incomingURL(query.queryItemValue("callbackurl")); // emit incomingURL(url.toString()); }
What's this problem?unknown type name nsurl
Error: unknown type name NsURL
-
It's NSURL
-
@Max-Base
Start by reading https://doc.qt.io/qt-5/qurl.html#toNSURL, where you will see it's speltNSURL
. -
Hello,
Thank you for your help and message.
Sorry for my question @SGaist @JonBmain.cpp file:
#include <QApplication> #include <QQmlApplicationEngine> #include <QtWebView> #include <QDesktopServices> #include <QUrl> #include <QQmlContext> #include "HandleURL.hpp" int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QApplication app(argc, argv); QtWebView::initialize(); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); HandleURL *URLHandler = new HandleURL(); QDesktopServices::setUrlHandler("swish", URLHandler, "handleURL"); engine.load(url); engine.rootContext()->setContextProperty("URLHandler", URLHandler); return app.exec(); }
HandleURL.mm file:
#include <QDebug> #include <QUrlQuery> #include <QUrl> #include <QDesktopServices> #include "HandleURL.hpp" #import <AppKit/NSApplication.h> #import <Foundation/Foundation.h> void HandleURL::handleURL(const QUrl &url) { QUrlQuery query(url); QUrl path(query.queryItemValue("callbackurl")); NSURL *urls = path.toNSURL(); bool canOpen = [[NSApplication shared] canOpenUrl: urls]; qDebug() << canOpen; if(canOpen) { QDesktopServices::openUrl(url); } emit incomingURL(query.queryItemValue("callbackurl")); // emit incomingURL(url.toString()); }
.pro file:
QT += widgets quick webview CONFIG += c++17 TEMPLATE = app DEFINES += QT_DEPRECATED_WARNINGS LIBS += -framework AppKit -framework Foundation SOURCES += \ HandleURL.mm \ main.cpp \ RESOURCES += qml.qrc QML_IMPORT_PATH = QML_DESIGNER_IMPORT_PATH = # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target contains(ANDROID_TARGET_ARCH,arm64-v8a) { ANDROID_ARM64 = 1 ANDROID_EXTRA_LIBS = \ $$PWD/openssl-1.1.1a-clang/arm64-v8a/lib/libcrypto.so \ $$PWD/openssl-1.1.1a-clang/arm64-v8a/lib/libssl.so ANDROID_PACKAGE_SOURCE_DIR = \ $$PWD/android } contains(ANDROID_TARGET_ARCH,armeabi-v7a) { ANDROID_EXTRA_LIBS = \ $$PWD/openssl-1.1.1a-clang/armeabi-v7a/lib/libcrypto.so \ $$PWD/openssl-1.1.1a-clang/armeabi-v7a/lib/libssl.so ANDROID_PACKAGE_SOURCE_DIR = \ $$PWD/android } DISTFILES += \ android/AndroidManifest.xml \ android/build.gradle \ android/gradle/wrapper/gradle-wrapper.jar \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradlew \ android/gradlew.bat \ android/res/values/libs.xml defineReplace(droidVersionCode) { segments = $$split(1, ".") for(segment, segments): vCode = "$$first(vCode)$$format_number($$segment, width=3 zeropad)" ## arm64-v8a, armeabi-v7a contains(ANDROID_TARGET_ARCH, arm64-v8a): \ suffix = 1 else:contains(ANDROID_TARGET_ARCH, armeabi-v7a): \ suffix = 0 return($$first(vCode)$$first(suffix)) } ios { QMAKE_INFO_PLIST = ios/info.plist } VERSION = 1.2.3 ANDROID_VERSION_NAME = $$VERSION ANDROID_VERSION_CODE = $$droidVersionCode($$ANDROID_VERSION_NAME) HEADERS += \ HandleURL.hpp OBJECTIVE_SOURCES = HandleURL.mm
HandleURL.hpp file:
#ifndef HANDLEURL #define HANDLEURL #include <QObject> #include <QDesktopServices> class HandleURL : public QObject { Q_OBJECT signals: void incomingURL(QString path); public slots: void handleURL(const QUrl &url); }; #endif
Compile Error
/Users/user/Desktop/silvcopy2/HandleURL.mm:7: error: 'AppKit/NSApplication.h' file not found #import <AppKit/NSApplication.h> ^~~~~~~~~~~~~~~~~~~~~~~~ :-1: error: Xcodebuild failed.
-
Did you re-run qmake after modifying your .pro file ?
If not then either nuke the build folder and restart a build or force a run of qmake.
On a side note, your .pro file has two issues: you have
HandleURL.mm
in both SOURCES and OBJECTIVE_SOURCES. If you are using a recent version of Qt, you don't need the later.The other issue is the backslash after main.cpp.
-
@SGaist Thank you for your message.
But we have error yet!
.mm file:
#include <QDebug> #include <QUrlQuery> #include <QUrl> #include <QDesktopServices> #include "HandleURL.hpp" #import <Foundation/NSUserNotification.h> #import <AppKit/NSApplication.h> void HandleURL::handleURL(const QUrl &url) { // parse it... QUrlQuery query(url); // qDebug() << url.toString(); // qDebug() << query.queryItemValue("callbackurl"); // qDebug() << QUrl::toString(...); // NSUrl *urls = url.toNSUrl(); //NSUrl *urls = url.toString().toNSUrl(); NSUrl *urls = url.toNSUrl(); bool canOpen = [[NSApplication shared] canOpenUrl: urls]; qDebug() << canOpen; if(canOpen) { QDesktopServices::openUrl(url); } emit incomingURL(query.queryItemValue("callbackurl")); // emit incomingURL(url.toString()); }
.pro file:
#include Foundation/NSUserNotification.h> #include AppKit/NSApplication.h> QT += widgets quick webview CONFIG += c++17 TEMPLATE = app DEFINES += QT_DEPRECATED_WARNINGS LIBS += -framework AppKit -framework Foundation SOURCES += \ main.cpp RESOURCES += qml.qrc QML_IMPORT_PATH = QML_DESIGNER_IMPORT_PATH = # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target contains(ANDROID_TARGET_ARCH,arm64-v8a) { ANDROID_ARM64 = 1 ANDROID_EXTRA_LIBS = \ $$PWD/openssl-1.1.1a-clang/arm64-v8a/lib/libcrypto.so \ $$PWD/openssl-1.1.1a-clang/arm64-v8a/lib/libssl.so ANDROID_PACKAGE_SOURCE_DIR = \ $$PWD/android } contains(ANDROID_TARGET_ARCH,armeabi-v7a) { ANDROID_EXTRA_LIBS = \ $$PWD/openssl-1.1.1a-clang/armeabi-v7a/lib/libcrypto.so \ $$PWD/openssl-1.1.1a-clang/armeabi-v7a/lib/libssl.so ANDROID_PACKAGE_SOURCE_DIR = \ $$PWD/android } DISTFILES += \ android/AndroidManifest.xml \ android/build.gradle \ android/gradle/wrapper/gradle-wrapper.jar \ android/gradle/wrapper/gradle-wrapper.properties \ android/gradlew \ android/gradlew.bat \ android/res/values/libs.xml defineReplace(droidVersionCode) { segments = $$split(1, ".") for(segment, segments): vCode = "$$first(vCode)$$format_number($$segment, width=3 zeropad)" ## arm64-v8a, armeabi-v7a contains(ANDROID_TARGET_ARCH, arm64-v8a): \ suffix = 1 else:contains(ANDROID_TARGET_ARCH, armeabi-v7a): \ suffix = 0 return($$first(vCode)$$first(suffix)) } ios { QMAKE_INFO_PLIST = ios/info.plist } VERSION = 1.2.3 ANDROID_VERSION_NAME = $$VERSION ANDROID_VERSION_CODE = $$droidVersionCode($$ANDROID_VERSION_NAME) HEADERS += \ HandleURL.hpp OBJECTIVE_SOURCES = HandleURL.mm
ios -> info.plist file:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDisplayName</key> <string>${PRODUCT_NAME}</string> <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleGetInfoString</key> <string>Created by Qt/QMake</string> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleName</key> <string>${PRODUCT_NAME}</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>${QMAKE_SHORT_VERSION}</string> <key>CFBundleSignature</key> <string>${QMAKE_PKGINFO_TYPEINFO}</string> <key>CFBundleVersion</key> <string>${QMAKE_FULL_VERSION}</string> <key>LSRequiresIPhoneOS</key> <true/> <key>MinimumOSVersion</key> <string>${IPHONEOS_DEPLOYMENT_TARGET}</string> <key>NOTE</key> <string>This file was generated by Qt/QMake.</string> <key>UILaunchStoryboardName</key> <string>LaunchScreen</string> <key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>swish</string> </array> </dict> </array> </dict> </plist>
Errors
/Users/user/Desktop/silvcopy22/HandleURL.mm:6: error: 'Foundation/NSUserNotification.h' file not found #include <Foundation/NSUserNotification.h> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /Users/user/Desktop/silvcopy22/HandleURL.mm:6: did not find header 'NSUserNotification.h' in framework 'Foundation' (loaded from '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.2.sdk/System/Library/Frameworks') :-1: error: Xcodebuild failed.
Qt version: 5.13.2
Can you help and guide me?
Thank you -
Are you building for macOS or iOS ?
I built successfully for macOS but you seem to target the simulator.
-
We want this for iOS (iphone). @SGaist
-
From the documentation, NSUserNotification is a macOS API that is not deprecated.
-
This post is deleted! -
How we can access to UIApplication? and how can call canopenurl?
Target is iOS using Qt.
https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl
-
It's written on the page you are linking as well as the URL: use the UIKit framework.
-
@SGaist said in UIApplication.shared.canOpenURL implements in Qt:
UIKit
I don't know how to use UIKit, UIApplication in my Qt project.
I cannot find any solution and sample code for this.
Can you help me? -
The exact same as you did with NSApplication, just use UIApplication in place.
-
@SGaist said in UIApplication.shared.canOpenURL implements in Qt:
NSURL *url = myUrl.toNSUrl();
bool canOpen = [[UIApplication shared] canOpenUrl: url];Thank you so much for your message.
Also how we can access to
shared
object when we are in another file?It's a globally object in
OBJECT C
(.mm) files? -
The same way you did there. The function returns the singleton app instance.
-
@SGaist said in UIApplication.shared.canOpenURL implements in Qt:
The same way you did there. The function returns the singleton app instance.
![photo_2020-01-21_01-25-10.jpg]
main.mm file:
#include <QApplication> #include <QQmlApplicationEngine> #include <QtWebView> #include <QDesktopServices> #include <QUrl> #include <QQmlContext> #include "HandleURL.hpp" #include <QDebug> #include <QUrlQuery> //Two of these?? #include <QUrl> #include <QDesktopServices> #include "HandleURL.hpp" //#import <AppKit/NSApplication.h> #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #include <QUrl> int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QApplication app(argc, argv); QUrl testURL("swish://paymentrequest?token=Shk9Q9C-RaatwCxZ_lYZ-u11ShJafIg5&callbackurl=https%3A%2F%2Fpay.direct2internet.com%2Fpay%2Fsuccess%3Fd2iwebpay-hh%3DV3n%252FCX%26d2iwebpay-tm%3D1579033717%26d2iwebpay%3D88c96710-5e08-43f6-bf46-f0ba89a3b3f6"); NSURL *urls = testURL.toNSURL(); bool canOpen = [[UIApplication sharedApplication] canOpenUrl: urls]; qDebug() << canOpen; if(canOpen) { QDesktopServices::openUrl(testURL); } QtWebView::initialize(); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); HandleURL *URLHandler = new HandleURL(); QDesktopServices::setUrlHandler("swish", URLHandler, "handleURL"); engine.load(url); engine.rootContext()->setContextProperty("URLHandler", URLHandler); return app.exec(); }
Error:
ld: framework not found AppKit clang: error: linker command failed with exit code 1 (use -v to see invocation)
-
The code you pasted does not match the code you are showing in the image.
One uses
shared
and the othersharedApplication
. -
@SGaist said in UIApplication.shared.canOpenURL implements in Qt:
The code you pasted does not match the code you are showing in the image.
One uses
shared
and the othersharedApplication
.Sorry,
shared
have error: Class method 'shared' not found.So we did used
sharedApplication
in images.Please check old my message, i did update it.
-
You know that Objective-C/C++ like C/C++ is case sensitive ?
It's canOpenURL.