diff options
author | Timur Pocheptsov <timur.pocheptsov@qt.io> | 2023-03-24 10:53:11 +0100 |
---|---|---|
committer | Timur Pocheptsov <timur.pocheptsov@qt.io> | 2023-03-28 18:37:36 +0200 |
commit | 21a6c86979064b70b11b14b97c8f828d08e29781 (patch) | |
tree | f542511c055ffb6baae2ab906893c1fe463736c7 | |
parent | b4afba0c3450fd0c14ec7bada098c4e82ca310e7 (diff) |
iOS: request authorization before presenting image-picker
Right now, image picker view is shown first (it does
not require access to photos, since it's essentially
Photos app getting access to photos ...). Then, we use
AssetsLibrary to get asset for an url (using ALAssetsLibrarie's
-assetForURL method). This may trigger a permission-related alert, asking to:
a. Select more photos or ...
b. Allow access to all photos or ...
c. Deny access.
Showing this alert _after_ picker has selected an image makes little sense
(and probably was never intended this way anyway). Instead, we now use
Photos.framework to check the authorization and, if needed, we request
an authorization (when the current status is 'Nondetermined'). If authorization
is 'Granted' as a result, we show picker view and proceed as normal/before.
Pick-to: 6.5
Task-number: QTBUG-109120
Change-Id: I0acfd7b0476346360d75a5e37f5845aaf2d6e3e0
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r-- | cmake/QtFrameworkHelpers.cmake | 1 | ||||
-rw-r--r-- | src/plugins/platforms/ios/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosfiledialog.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosfiledialog.mm | 44 |
4 files changed, 44 insertions, 3 deletions
diff --git a/cmake/QtFrameworkHelpers.cmake b/cmake/QtFrameworkHelpers.cmake index 1eed9df379..e8db635963 100644 --- a/cmake/QtFrameworkHelpers.cmake +++ b/cmake/QtFrameworkHelpers.cmake @@ -6,6 +6,7 @@ macro(qt_find_apple_system_frameworks) qt_internal_find_apple_system_framework(FWAppKit AppKit) qt_internal_find_apple_system_framework(FWCFNetwork CFNetwork) qt_internal_find_apple_system_framework(FWAssetsLibrary AssetsLibrary) + qt_internal_find_apple_system_framework(FWPhotos Photos) qt_internal_find_apple_system_framework(FWAudioToolbox AudioToolbox) qt_internal_find_apple_system_framework(FWApplicationServices ApplicationServices) qt_internal_find_apple_system_framework(FWCarbon Carbon) diff --git a/src/plugins/platforms/ios/CMakeLists.txt b/src/plugins/platforms/ios/CMakeLists.txt index e0473b3ce4..3745783248 100644 --- a/src/plugins/platforms/ios/CMakeLists.txt +++ b/src/plugins/platforms/ios/CMakeLists.txt @@ -65,6 +65,7 @@ qt_internal_extend_target(QIOSIntegrationPlugin CONDITION NOT TVOS LIBRARIES ${FWAssetsLibrary} ${FWUniformTypeIdentifiers} + ${FWPhotos} ) add_subdirectory(optional) diff --git a/src/plugins/platforms/ios/qiosfiledialog.h b/src/plugins/platforms/ios/qiosfiledialog.h index 12a3af7181..f00c154c03 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.h +++ b/src/plugins/platforms/ios/qiosfiledialog.h @@ -39,6 +39,7 @@ private: bool showImagePickerDialog(QWindow *parent); bool showNativeDocumentPickerDialog(QWindow *parent); + void showImagePickerDialog_helper(QWindow *parent); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm index 526c040335..5dea3c6446 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.mm +++ b/src/plugins/platforms/ios/qiosfiledialog.mm @@ -3,6 +3,8 @@ #import <UIKit/UIKit.h> +#import <Photos/Photos.h> + #include <QtCore/qstandardpaths.h> #include <QtGui/qwindow.h> #include <QDebug> @@ -53,6 +55,13 @@ bool QIOSFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality window return false; } +void QIOSFileDialog::showImagePickerDialog_helper(QWindow *parent) +{ + UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window + : qt_apple_sharedApplication().keyWindow; + [window.rootViewController presentViewController:m_viewController animated:YES completion:nil]; +} + bool QIOSFileDialog::showImagePickerDialog(QWindow *parent) { if (!m_viewController) { @@ -71,9 +80,38 @@ bool QIOSFileDialog::showImagePickerDialog(QWindow *parent) return false; } - UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window - : qt_apple_sharedApplication().keyWindow; - [window.rootViewController presentViewController:m_viewController animated:YES completion:nil]; + // "Old style" authorization (deprecated, but we have to work with AssetsLibrary anyway). + // + // From the documentation: + // "The authorizationStatus and requestAuthorization: methods aren’t compatible with the + // limited library and return PHAuthorizationStatusAuthorized when the user authorizes your + // app for limited access only." + // + // This is good enough for us. + + const auto authStatus = [PHPhotoLibrary authorizationStatus]; + if (authStatus == PHAuthorizationStatusAuthorized) { + showImagePickerDialog_helper(parent); + } else if (authStatus == PHAuthorizationStatusNotDetermined) { + QPointer<QWindow> winGuard(parent); + QPointer<QIOSFileDialog> thisGuard(this); + [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (status == PHAuthorizationStatusAuthorized) { + if (thisGuard && winGuard) + thisGuard->showImagePickerDialog_helper(winGuard); + + } else if (thisGuard) { + emit thisGuard->reject(); + } + }); + }]; + } else { + // Treat 'Limited' (we don't know how to deal with anyway) and 'Denied' as errors. + // FIXME: logging category? + qWarning() << "QIOSFileDialog: insufficient permission, cannot pick images"; + return false; + } return true; } |