UIApplication.shared.canOpenURL implements in Qt
-
In your case, it's not as complicated as the link you found.
Change the file extension of your cpp class implementation to .mm and in the function you want to make the check call, something like:
NSURL *url = myUrl.toNSUrl(); bool canOpen = [[NSApplication shared] canOpenUrl: url];
[edit: fixed class name typo]
-
@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
-
@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
-
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.
-
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.
-
From the documentation, NSUserNotification is a macOS API that is not deprecated.
-
In your case, it's not as complicated as the link you found.
Change the file extension of your cpp class implementation to .mm and in the function you want to make the check call, something like:
NSURL *url = myUrl.toNSUrl(); bool canOpen = [[NSApplication shared] canOpenUrl: url];
[edit: fixed class name typo]
-
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.
-
The exact same as you did with NSApplication, just use UIApplication in place.
-
In your case, it's not as complicated as the link you found.
Change the file extension of your cpp class implementation to .mm and in the function you want to make the check call, something like:
NSURL *url = myUrl.toNSUrl(); bool canOpen = [[NSApplication shared] canOpenUrl: url];
[edit: fixed class name typo]
@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
. -
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.