diff options
author | Samuel Mira <samuel.mira@qt.io> | 2021-09-08 17:00:20 +0300 |
---|---|---|
committer | Samuel Mira <samuel.mira@qt.io> | 2021-09-10 06:06:59 +0000 |
commit | 3c6f6ae6b49ae397e1071245bea9d94a0cf919e8 (patch) | |
tree | 68b0cf1e56721bf31a67af0bb2f1fa6a655fecc1 /src/multimedia | |
parent | e22ddea9d62d84a4b28b2395d4f259dd1d4b1094 (diff) |
Fix crash in Android Recorder example on permission request
On the first time the app runs, it asks for permission for recording
video as soon it starts and asks for permission to record audio only
when it is needed.
This permission to record audio can make a crash because requesting
permission makes the app go to background which can make android to
remove the camera surfaceTexture.
Fixed by forcing the app to request permission before creating the
surfaceTexture.
Pick-to: 6.2 6.2.0
Change-Id: I920917a6decf25f7b5f78ee8364d2b9403207aa4
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/multimedia')
5 files changed, 49 insertions, 12 deletions
diff --git a/src/multimedia/platform/android/common/qandroidmultimediautils.cpp b/src/multimedia/platform/android/common/qandroidmultimediautils.cpp index 51c08006f..75f012f07 100644 --- a/src/multimedia/platform/android/common/qandroidmultimediautils.cpp +++ b/src/multimedia/platform/android/common/qandroidmultimediautils.cpp @@ -124,6 +124,25 @@ static bool androidRequestPermission(QtAndroidPrivate::PermissionType key) return true; } +static bool androidCheckPermission(QtAndroidPrivate::PermissionType key) +{ + if (QNativeInterface::QAndroidApplication::sdkVersion() < 23) + return true; + + // Permission already granted? + return (QtAndroidPrivate::checkPermission(key).result() == QtAndroidPrivate::Authorized); +} + +bool qt_androidCheckCameraPermission() +{ + return androidCheckPermission(QtAndroidPrivate::Camera); +} + +bool qt_androidCheckMicrophonePermission() +{ + return androidCheckPermission(QtAndroidPrivate::Microphone); +} + bool qt_androidRequestCameraPermission() { if (!androidRequestPermission(QtAndroidPrivate::Camera)) { diff --git a/src/multimedia/platform/android/common/qandroidmultimediautils_p.h b/src/multimedia/platform/android/common/qandroidmultimediautils_p.h index 9a341c43b..5bc187da3 100644 --- a/src/multimedia/platform/android/common/qandroidmultimediautils_p.h +++ b/src/multimedia/platform/android/common/qandroidmultimediautils_p.h @@ -70,6 +70,9 @@ bool qt_androidRequestCameraPermission(); bool qt_androidRequestRecordingPermission(); bool qt_androidRequestWriteStoragePermission(); +bool qt_androidCheckCameraPermission(); +bool qt_androidCheckMicrophonePermission(); + QT_END_NAMESPACE #endif // QANDROIDMULTIMEDIAUTILS_H diff --git a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp index 1d85acf95..d89e494b1 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp @@ -748,10 +748,10 @@ void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state } } -bool QAndroidCameraSession::requestRecordingPermission() +bool QAndroidCameraSession::requestCameraPermission() { m_keepActive = true; - const bool result = qt_androidRequestRecordingPermission(); + const bool result = qt_androidRequestCameraPermission(); m_keepActive = false; return result; } diff --git a/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h b/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h index 56674757d..fd225ae04 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h +++ b/src/multimedia/platform/android/mediacapture/qandroidcamerasession_p.h @@ -108,7 +108,7 @@ public: virtual void onFrameAvailable(const QVideoFrame &frame) = 0; }; void setPreviewCallback(PreviewCallback *callback); - bool requestRecordingPermission(); + bool requestCameraPermission(); void setVideoSink(QVideoSink *surface); diff --git a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp index 677c3614d..ac2dad0d6 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp @@ -92,12 +92,24 @@ void QAndroidCaptureSession::setCameraSession(QAndroidCameraSession *cameraSessi if (!isActive) stop(); }); + + // It requests permission on setAudioInput instead of on start because asking for + // permission can pause the activity and android can release the surface referenced + // by camera crashing the app when mediaRecorder tries to use it + // TODO: https://bugreports.qt.io/browse/QTBUG-96346 + m_cameraSession->requestCameraPermission(); } } void QAndroidCaptureSession::setAudioInput(QPlatformAudioInput *input) { m_audioInput = input; + + // It requests permission on setAudioInput instead of on start because asking for + // permission can pause the activity and android can release the surface referenced + // by camera crashing the app when mediaRecorder tries to use it + // TODO: https://bugreports.qt.io/browse/QTBUG-96346 + qt_androidRequestRecordingPermission(); } void QAndroidCaptureSession::setAudioOutput(QPlatformAudioOutput *output) @@ -128,15 +140,7 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & } if (!m_cameraSession && !m_audioInput) { - Q_EMIT error(QMediaRecorder::ResourceError, QLatin1String("Audio Input device not set")); - return; - } - - const bool granted = m_cameraSession - ? m_cameraSession->requestRecordingPermission() - : qt_androidRequestRecordingPermission(); - if (!granted) { - Q_EMIT error(QMediaRecorder::ResourceError, QLatin1String("Permission denied.")); + Q_EMIT error(QMediaRecorder::ResourceError, QLatin1String("No devices are set")); return; } @@ -148,6 +152,11 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & // Set audio/video sources if (m_cameraSession) { + if (!qt_androidCheckCameraPermission()) { + Q_EMIT error(QMediaRecorder::ResourceError, QLatin1String("Camera permission denied.")); + return; + } + m_cameraSession->camera()->stopPreviewSynchronous(); m_cameraSession->applyResolution(settings.videoResolution(), false); m_cameraSession->camera()->unlock(); @@ -157,6 +166,12 @@ void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl & } if (m_audioInput) { + if (!qt_androidCheckMicrophonePermission()) { + Q_EMIT error(QMediaRecorder::ResourceError, + QLatin1String("Microphone permission denied.")); + return; + } + m_mediaRecorder->setAudioInput(m_audioInput->device.id()); if (!m_mediaRecorder->isAudioSourceSet()) m_mediaRecorder->setAudioSource(AndroidMediaRecorder::DefaultAudioSource); |