QJniObject cannot get the android safe cutout areas
-
I am trying to use QNativeInterface to access some of the android API. I want my application to be edge-to-edge, as i have a live video feed that i want to be displayed on the most screen real estate as possible. However, i do not want my actual UI components to be placed behind the notch areas (the top notch of the screen where the camera is, and the bottom notch where the home button, back button, and other open apps buttons are), and simply just want to add margins there.
This is my main function:
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // init application app.setOrganizationName("OrgName"); app.setApplicationVersion(0.0.1); app.setApplicationName(AppName); QQuickStyle::setStyle("Material"); QQmlApplicationEngine app_engine; QObject::connect( &app_engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); auto mobile_context = app_engine.rootContext(); #if !defined(QT_NO_DEBUG) qDebug() << "This is an internal build from git revision" << APP_VER_GIT; QString app_name; QString sdk_version; const QString app_version = QCoreApplication::applicationVersion(); qDebug() << QString("%1 version %2 using WaveSDK version %3") .arg(app_name) .arg(app_version) .arg(sdk_version); qDebug() << "This is an internal build from git revision" << APP_VER_GIT; qDebug() << "C++ flags:" << CMAKE_CXX_FLAGS_DEBUG; QLoggingCategory::setFilterRules(QStringLiteral("qt.qml=true\n" "qt.qml.debug=true\n")); #endif // #if !defined(QT_NO_DEBUG) // init properties MobileNotchUtils notch_utils; mobile_context->setContextProperty("notchUtils", ¬ch_utils); #if !defined(QT_NO_DEBUG) mobile_context->setContextProperty("devMode", QVariant(true)); #else mobile_context->setContextProperty("devMode", QVariant(false)); #endif // connect to quit QObject::connect(&app_engine, &QQmlEngine::quit, &app, &QGuiApplication::quit); app_engine.loadFromModule("MyAppModule", "QmlMainEntryPoint"); return app.exec(); }
This is where i am using the notchUtils to get the safe area insets:
Item { id: usableAreaItem anchors.fill: parent anchors.leftMargin: notchUtils.safeAreaLeftInset() anchors.rightMargin: notchUtils.safeAreaRightInset() anchors.topMargin: notchUtils.safeAreaTopInset() anchors.bottomMargin: notchUtils.safeAreaBottomInset() ToolBar { position: ToolBar.Header anchors.right: parent.right Material.background: "transparent" RowLayout { anchors.fill: parent RoundButton { Layout.alignment: Qt.AlignRight Layout.rightMargin: 2 Layout.topMargin: 2 Material.background: "transparent" icon.source: "qrc:/qt/qml/MyAppModule/images/settings.svg" enabled: !connecting onClicked: root.triggerSettings() } } } }
Function to get the safe area inset:
double MobileNotchUtils::safeAreaTopInset() { #ifdef Q_OS_ANDROID qreal device_pixel_ratio = qApp->devicePixelRatio(); QJniObject cutout = get_cutout(); if (!cutout.isValid()) { return 0; } double inset = cutout.callMethod<int>("getSafeInsetTop", "()I") / device_pixel_ratio; qDebug() << "TOP INSET: " << inset; return inset; #else return 0; #endif }
And the code to get the cutout:
inline QJniObject get_cutout() { QJniObject activity = QNativeInterface::QAndroidApplication::context(); if (!activity.isValid()) { qWarning() << "Could not get android context"; return QJniObject(); } QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;"); if (!window.isValid()) { qWarning() << "Cannot get window"; return QJniObject(); } QJniObject decoView = window.callObjectMethod("getDecorView", "()Landroid/view/View;"); if (!decoView.isValid()) { qWarning() << "Cannot get decorator view"; return QJniObject(); } QJniObject insets = decoView.callObjectMethod("getRootWindowInsets", "()Landroid/view/WindowInsets;"); if (!insets.isValid()) { qWarning() << "Cannot get root window insets"; return QJniObject(); } return insets.callObjectMethod("getDisplayCutout", "()Landroid/view/DisplayCutout;"); }
Now, this works for the top inset without fail. Always gives me the correct inset value for every device I've tested on. However, all of the other insets just return 0. Which means that my UI is still being drawn beneath the android home, back, and other open apps buttons.
Qt: 6.8.4
Android 35
NDK 29