Android Immersive fullscreen mode
-
Is there newer regular way to force app work in this mode? I discovered some possible solutions but no one is regular. I tried some - no one works fine. I do not want change Qt Java code as suggested here some years ago. It should be just some simple expression for AndroidManifest.xml which turns this mode on. Is there QTBUG suggestion about this? Or it's needed create new one...
-
Is there newer regular way to force app work in this mode? I discovered some possible solutions but no one is regular. I tried some - no one works fine. I do not want change Qt Java code as suggested here some years ago. It should be just some simple expression for AndroidManifest.xml which turns this mode on. Is there QTBUG suggestion about this? Or it's needed create new one...
UP!
I almost have found the way but I cannot find final piece of mosaic. The code is like this:
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { JNIEnv* env; vm->AttachCurrentThread(&env, Q_NULLPTR); jclass activityClass = env->FindClass("android/app/NativeActivity"); jmethodID getWindow = env->GetMethodID(activityClass, "getWindow", "()Landroid/view/Window;"); jclass windowClass = env->FindClass("android/view/Window"); jmethodID getDecorView = env->GetMethodID(windowClass, "getDecorView", "()Landroid/view/View;"); jclass viewClass = env->FindClass("android/view/View"); jmethodID setSystemUiVisibility = env->GetMethodID(viewClass, "setSystemUiVisibility", "(I)V"); jobject window = env->CallObjectMethod(?????????, getWindow); jobject decorView = env->CallObjectMethod(window, getDecorView); jfieldID flagFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_FULLSCREEN", "I"); jfieldID flagHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I"); jfieldID flagImmersiveStickyID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_IMMERSIVE", "I"); jfieldID flagLayoutStableID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_STABLE", "I"); jfieldID flagLayoutHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION", "I"); jfieldID flagLayoutFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN", "I"); const int flagFullscreen = env->GetStaticIntField(viewClass, flagFullscreenID); const int flagHideNavigation = env->GetStaticIntField(viewClass, flagHideNavigationID); const int flagImmersiveSticky = env->GetStaticIntField(viewClass, flagImmersiveStickyID); const int flagLayoutStable = env->GetStaticIntField(viewClass, flagLayoutStableID); const int flagLayoutHideNavigation = env->GetStaticIntField(viewClass, flagLayoutHideNavigationID); const int flagLayoutFullscreen = env->GetStaticIntField(viewClass, flagLayoutFullscreenID); const int flag = flagFullscreen | flagHideNavigation | flagImmersiveSticky | flagLayoutStable | flagLayoutFullscreen | flagLayoutFullscreen; env->CallVoidMethod(decorView, setSystemUiVisibility, flag); vm->DetachCurrentThread(); }
Instead of ????????? there must be some call returning pointer to NativeActivity jobject. How get it?
-
UP!
I almost have found the way but I cannot find final piece of mosaic. The code is like this:
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { JNIEnv* env; vm->AttachCurrentThread(&env, Q_NULLPTR); jclass activityClass = env->FindClass("android/app/NativeActivity"); jmethodID getWindow = env->GetMethodID(activityClass, "getWindow", "()Landroid/view/Window;"); jclass windowClass = env->FindClass("android/view/Window"); jmethodID getDecorView = env->GetMethodID(windowClass, "getDecorView", "()Landroid/view/View;"); jclass viewClass = env->FindClass("android/view/View"); jmethodID setSystemUiVisibility = env->GetMethodID(viewClass, "setSystemUiVisibility", "(I)V"); jobject window = env->CallObjectMethod(?????????, getWindow); jobject decorView = env->CallObjectMethod(window, getDecorView); jfieldID flagFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_FULLSCREEN", "I"); jfieldID flagHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I"); jfieldID flagImmersiveStickyID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_IMMERSIVE", "I"); jfieldID flagLayoutStableID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_STABLE", "I"); jfieldID flagLayoutHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION", "I"); jfieldID flagLayoutFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN", "I"); const int flagFullscreen = env->GetStaticIntField(viewClass, flagFullscreenID); const int flagHideNavigation = env->GetStaticIntField(viewClass, flagHideNavigationID); const int flagImmersiveSticky = env->GetStaticIntField(viewClass, flagImmersiveStickyID); const int flagLayoutStable = env->GetStaticIntField(viewClass, flagLayoutStableID); const int flagLayoutHideNavigation = env->GetStaticIntField(viewClass, flagLayoutHideNavigationID); const int flagLayoutFullscreen = env->GetStaticIntField(viewClass, flagLayoutFullscreenID); const int flag = flagFullscreen | flagHideNavigation | flagImmersiveSticky | flagLayoutStable | flagLayoutFullscreen | flagLayoutFullscreen; env->CallVoidMethod(decorView, setSystemUiVisibility, flag); vm->DetachCurrentThread(); }
Instead of ????????? there must be some call returning pointer to NativeActivity jobject. How get it?
There is NO NativeActivity object... :-((
QPlatformNativeInterface* interface = QApplication::platformNativeInterface(); jobject nativeActivity = (jobject) interface->nativeResourceForIntegration("NativeActivity"); qWarning()<<"============ Found native activity"<<nativeActivity;
Shows 0x0.
I am frustrating... I strongly need fullscreen mode for Android app.
-
Is there newer regular way to force app work in this mode? I discovered some possible solutions but no one is regular. I tried some - no one works fine. I do not want change Qt Java code as suggested here some years ago. It should be just some simple expression for AndroidManifest.xml which turns this mode on. Is there QTBUG suggestion about this? Or it's needed create new one...
@Gourmet said in Android Immersive fullscreen mode:
I do not want change Qt Java code as suggested here some years ago.
If you want to enable immersive mode, the only working way, as far as I know, is to adapt the java code.
It is easy and well documented by Google at https://developer.android.com/training/system-ui/immersiveSimply adapt your activity class like this:
import org.qtproject.qt5.android.bindings.QtActivity; import android.view.View; public class MainActivity extends QtActivity { ... @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { hideSystemUI(); } } private void hideSystemUI() { // Enables regular immersive mode. // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE. // Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_IMMERSIVE // Set the content to appear under the system bars so that the // content doesn't resize when the system bars hide and show. | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // Hide the nav bar and status bar | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN); } // Shows the system bars by removing all the flags // except for the ones that make the content appear under the system bars. private void showSystemUI() { View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } }
-
@Gourmet said in Android Immersive fullscreen mode:
I do not want change Qt Java code as suggested here some years ago.
If you want to enable immersive mode, the only working way, as far as I know, is to adapt the java code.
It is easy and well documented by Google at https://developer.android.com/training/system-ui/immersiveSimply adapt your activity class like this:
import org.qtproject.qt5.android.bindings.QtActivity; import android.view.View; public class MainActivity extends QtActivity { ... @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { hideSystemUI(); } } private void hideSystemUI() { // Enables regular immersive mode. // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE. // Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_IMMERSIVE // Set the content to appear under the system bars so that the // content doesn't resize when the system bars hide and show. | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // Hide the nav bar and status bar | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN); } // Shows the system bars by removing all the flags // except for the ones that make the content appear under the system bars. private void showSystemUI() { View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } }
@KroMignon this does not work if simply add these lines to my QtActivity extending class. I have this class in my app and tried doing this. The method onWindowFocusChanged() was not called. Here I found solution with QtActivity.java modified. But I hate modify framework files and never do this. It will be needed after each version upgrade. Another one possible solution described here - but it has same disadvantage. Both are not appropriate for me. It must be more reliable solution.
-
In Qt5 source code QtActivityDelegate.java I've found function setSystemUiVisibility(int systemUiVisibility) allowing switch immersive mode on and off. But how to use this???
-
@KroMignon this does not work if simply add these lines to my QtActivity extending class. I have this class in my app and tried doing this. The method onWindowFocusChanged() was not called. Here I found solution with QtActivity.java modified. But I hate modify framework files and never do this. It will be needed after each version upgrade. Another one possible solution described here - but it has same disadvantage. Both are not appropriate for me. It must be more reliable solution.
@Gourmet said in Android Immersive fullscreen mode:
The method onWindowFocusChanged() was not called.
I am using this successfully in applications using Qt 5.7 or Qt 5.12 on many Android devices (Android 4.4., 5.0, 5.1, 6, 7, 8 and 9).
Maybe a silly question, but did you adapt your AndroidManifest to use your own QtActivity extended class for your activity?
<?xml version="1.0"?> <manifest package="my.package" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionName="1.0" android:versionCode="1" android:installLocation="auto"> <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" ...> <activity android:name="my.package.MainActivity" ...>
-
In Qt5 source code QtActivityDelegate.java I've found function setSystemUiVisibility(int systemUiVisibility) allowing switch immersive mode on and off. But how to use this???
-
The best result I've got with following code. But it is not stable. Once app starts without Android taskbar and control buttons - but next start is with them both. Sometimes taskbar and control bar disappear while application runs. If then are not visible then swipe gesture from control bar side forces them both appear and swipe back can force disappear. It is unpredictable if app will start with or without them.
static JavaVM* vm; JNIEXPORT jint JNI_OnLoad(JavaVM* _vm, void*) { vm = _vm; return JNI_VERSION_1_4; } void goFullScr() { JNIEnv* env; qWarning()<<"*************** entering goFullScr"; vm->AttachCurrentThread(&env, Q_NULLPTR); qWarning()<<"------------ Finding native activity class"; jclass activityClass = env->FindClass("org/qtproject/qt5/android/bindings/QtActivity"); qWarning()<<"------------ getting window method ID for activity class"<<activityClass; jmethodID getWindow = env->GetMethodID(activityClass, "getWindow", "()Landroid/view/Window;"); qWarning()<<"++++++++++++++++++++++ got window"<<getWindow; qWarning()<<"------------ Finding window class"; jclass windowClass = env->FindClass("android/view/Window"); qWarning()<<"------------ getting decor view ID for window class"<<windowClass; jmethodID getDecorView = env->GetMethodID(windowClass, "getDecorView", "()Landroid/view/View;"); qWarning()<<"++++++++++++++++++++++ got decor view"<<getDecorView; qWarning()<<"------------ Finding view class"; jclass viewClass = env->FindClass("android/view/View"); qWarning()<<"------------ getting system visibility ID for view class"<<viewClass; jmethodID setSystemUiVisibility = env->GetMethodID(viewClass, "setSystemUiVisibility", "(I)V"); qWarning()<<"++++++++++++++++++++++"<<setSystemUiVisibility; qWarning()<<"------------ Getting activity jobject"; QPlatformNativeInterface* interface = QApplication::platformNativeInterface(); qWarning()<<"============ got interface"<<interface; jobject nativeActivity = (jobject) interface->nativeResourceForIntegration("QtActivity"); qWarning()<<"============ Found activity"<<nativeActivity; qWarning()<<"============ calling activity class object method"; jobject window = env->CallObjectMethod(nativeActivity, getWindow); qWarning()<<"------------ got window object"<<window; qWarning()<<"============ calling window object method"; jobject decorView = env->CallObjectMethod(window, getDecorView); qWarning()<<"------------ got decorView"<<decorView; qWarning()<<"++++++++++++ getting flag IDs"; jfieldID flagFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_FULLSCREEN", "I"); qWarning()<<"flagFullscreenID"<<flagFullscreenID; jfieldID flagHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I"); qWarning()<<"flagHideNavigationID"<<flagHideNavigationID; jfieldID flagImmersiveStickyID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_IMMERSIVE", "I"); qWarning()<<"flagImmersiveStickyID"<<flagImmersiveStickyID; jfieldID flagLayoutStableID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_STABLE", "I"); qWarning()<<"flagLayoutStableID"<<flagLayoutStableID; jfieldID flagLayoutHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION", "I"); qWarning()<<"flagLayoutHideNavigationID"<<flagLayoutHideNavigationID; jfieldID flagLayoutFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN", "I"); qWarning()<<"flagLayoutFullscreenID"<<flagLayoutFullscreenID; qWarning()<<"++++++++++++ getting flags"; const int flagFullscreen = env->GetStaticIntField(viewClass, flagFullscreenID); qWarning()<<"flagFullscreen"<<flagFullscreen; const int flagHideNavigation = env->GetStaticIntField(viewClass, flagHideNavigationID); qWarning()<<"flagHideNavigation"<<flagHideNavigation; const int flagImmersiveSticky = env->GetStaticIntField(viewClass, flagImmersiveStickyID); qWarning()<<"flagImmersiveSticky"<<flagImmersiveSticky; const int flagLayoutStable = env->GetStaticIntField(viewClass, flagLayoutStableID); qWarning()<<"flagLayoutStable"<<flagLayoutStable; const int flagLayoutHideNavigation = env->GetStaticIntField(viewClass, flagLayoutHideNavigationID); qWarning()<<"flagLayoutHideNavigation"<<flagLayoutHideNavigation; const int flagLayoutFullscreen = env->GetStaticIntField(viewClass, flagLayoutFullscreenID); qWarning()<<"flagLayoutFullscreen"<<flagLayoutFullscreen; const int flag = flagFullscreen | flagHideNavigation | flagImmersiveSticky | flagLayoutStable | flagLayoutHideNavigation | flagLayoutFullscreen; qWarning()<<"------------ setting full screen on flag"<<flag; env->CallVoidMethod(decorView, setSystemUiVisibility, flag); qWarning()<<"------------ leaving goFullScr"; } int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w(nullptr); goFullScr(); w.show(); return a.exec(); }
-
In Qt5 source code QtActivityDelegate.java I've found function setSystemUiVisibility(int systemUiVisibility) allowing switch immersive mode on and off. But how to use this???
@KroMignon said in Android Immersive fullscreen mode:
I am using this successfully in applications using Qt 5.7 or Qt 5.12 on many Android devices (Android 4.4., 5.0, 5.1, 6, 7, 8 and 9).
Couldn't you please post the complete lines for <application...> and <activity...> from yout mainfest file?
-
In Qt5 source code QtActivityDelegate.java I've found function setSystemUiVisibility(int systemUiVisibility) allowing switch immersive mode on and off. But how to use this???
@KroMignon said in Android Immersive fullscreen mode:
Maybe a silly question, but did you adapt your AndroidManifest to use your own QtActivity extended class for your activity?
With this modification the app does not start at all. In console "it's dead" message appears immediately after start attempt.
-
-
Damn! It Works! I had return to this problem after worked on another project. But now I noticed one typo in package name. I don't know how I was not able notice this before. I fixed it, assembled package, and... it works! Application starts fullscreen!