From f5e230285147efa95f32594f9b2e2581de819e47 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Sun, 17 Sep 2023 23:13:04 +0300 Subject: [PATCH] Android: don't call delegates outside of the Activity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The delegate classes shouldn't be used outside of the Activity/Service classes, since they're practically private implementation, so don't use them anywhere outside Activity/Service. Since Qt Android apps still mainly support having one QtActivity/ QtService, QtNative heavily uses those objects to do various operations. For that reason, we still need to use the delegate there. The aim is to change that in future patches and do the operations where they make more sense for example directly under QtActivityBase/QtActivityDelegate or Service counterpart. The QtServiceDelegate is used no where and have no special implementation, so it's removed here. Task-number: QTBUG-118077 Change-Id: I5e106318169be19fec8163e8e500ee573af0e1bc Reviewed-by: Tinja Paavoseppä Reviewed-by: Qt CI Bot --- src/android/jar/CMakeLists.txt | 1 - .../qtproject/qt/android/QtActivityBase.java | 7 +- .../qt/android/QtActivityDelegate.java | 371 ++++++++++-------- .../org/qtproject/qt/android/QtEditText.java | 11 +- .../qt/android/QtInputConnection.java | 68 ++-- .../qtproject/qt/android/QtInputDelegate.java | 37 +- .../org/qtproject/qt/android/QtNative.java | 171 +------- .../qtproject/qt/android/QtServiceBase.java | 11 +- .../qt/android/QtServiceDelegate.java | 20 - .../android/qandroidnativeinterface.cpp | 3 +- .../platforms/android/androidjnimain.cpp | 44 +-- .../platforms/android/androidjnimenu.cpp | 56 ++- .../platforms/android/androidjnimenu.h | 2 +- .../android/qandroidplatformmenu.cpp | 2 +- .../corelib/platform/android/tst_android.cpp | 7 +- 15 files changed, 351 insertions(+), 460 deletions(-) delete mode 100644 src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt index 37f5e346ab9..f600598c4d2 100644 --- a/src/android/jar/CMakeLists.txt +++ b/src/android/jar/CMakeLists.txt @@ -12,7 +12,6 @@ set(java_sources src/org/qtproject/qt/android/QtActivityBase.java src/org/qtproject/qt/android/QtServiceBase.java src/org/qtproject/qt/android/QtActivityDelegate.java - src/org/qtproject/qt/android/QtServiceDelegate.java src/org/qtproject/qt/android/QtInputDelegate.java src/org/qtproject/qt/android/QtLoader.java src/org/qtproject/qt/android/QtActivityLoader.java diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java index f9db1ff24a4..2e1a0228d35 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java @@ -173,7 +173,7 @@ public class QtActivityBase extends Activity super.onDestroy(); if (m_delegate.isQuitApp()) { QtNative.terminateQt(); - QtNative.setActivity(null, null); + QtNative.setActivity(null); QtNative.m_qtThread.exit(); System.exit(0); } @@ -325,6 +325,11 @@ public class QtActivityBase extends Activity QtNative.sendRequestPermissionsResult(requestCode, permissions, grantResults); } + public void hideSplashScreen(final int duration) + { + m_delegate.hideSplashScreen(duration); + } + QtActivityDelegate getActivityDelegate() { return m_delegate; diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java index 8a32b44c00e..1d671170442 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -6,7 +6,6 @@ package org.qtproject.qt.android; import android.app.Activity; -import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; @@ -27,7 +26,6 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.Window; import android.view.WindowInsetsController; -import android.view.inputmethod.InputMethodManager; import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.PopupMenu; @@ -56,34 +54,36 @@ public class QtActivityDelegate private QtAccessibilityDelegate m_accessibilityDelegate = null; private final QtDisplayManager m_displayManager = new QtDisplayManager(); - private QtInputDelegate.KeyboardVisibilityListener m_keyboardVisibilityListener = - new QtInputDelegate.KeyboardVisibilityListener() { - @Override - public void onKeyboardVisibilityChange() { - m_displayManager.updateFullScreen(m_activity); - } - }; - private final QtInputDelegate m_inputDelegate = new QtInputDelegate(m_keyboardVisibilityListener); + private QtInputDelegate m_inputDelegate = null; QtActivityDelegate(Activity activity) { m_activity = activity; - QtNative.setActivity(m_activity, this); + QtNative.setActivity(m_activity); setActionBarVisibility(false); + m_displayManager.registerDisplayListener(m_activity, m_layout); + + QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener = + new QtInputDelegate.KeyboardVisibilityListener() { + @Override + public void onKeyboardVisibilityChange() { + m_displayManager.updateFullScreen(m_activity); + } + }; + m_inputDelegate = new QtInputDelegate(m_activity, keyboardVisibilityListener); + try { - m_inputDelegate.setSoftInputMode(m_activity.getPackageManager() - .getActivityInfo(m_activity.getComponentName(), 0).softInputMode); + PackageManager pm = m_activity.getPackageManager(); + ActivityInfo activityInfo = pm.getActivityInfo(m_activity.getComponentName(), 0); + m_inputDelegate.setSoftInputMode(activityInfo.softInputMode); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } - - m_displayManager.registerDisplayListener(m_activity, m_layout); } - QtDisplayManager displayManager() - { + QtDisplayManager displayManager() { return m_displayManager; } @@ -147,7 +147,7 @@ public class QtActivityDelegate try { // set new activity m_activity = activity; - QtNative.setActivity(m_activity, this); + QtNative.setActivity(m_activity); // update the new activity content view to old layout ViewGroup layoutParent = (ViewGroup) m_layout.getParent(); @@ -220,8 +220,6 @@ public class QtActivityDelegate e.printStackTrace(); } - m_inputDelegate.setEditText(new QtEditText(m_activity)); - m_inputDelegate.setInputMethodManager((InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE)); m_surfaces = new HashMap(); m_nativeViews = new HashMap(); m_activity.registerForContextMenu(m_layout); @@ -273,31 +271,40 @@ public class QtActivityDelegate public void hideSplashScreen(final int duration) { - if (m_splashScreen == null) - return; - - if (duration <= 0) { - m_layout.removeView(m_splashScreen); - m_splashScreen = null; - return; - } - - final Animation fadeOut = new AlphaAnimation(1, 0); - fadeOut.setInterpolator(new AccelerateInterpolator()); - fadeOut.setDuration(duration); - - fadeOut.setAnimationListener(new Animation.AnimationListener() { + QtNative.runAction(new Runnable() { @Override - public void onAnimationEnd(Animation animation) { hideSplashScreen(0); } + public void run() { + if (m_splashScreen == null) + return; - @Override - public void onAnimationRepeat(Animation animation) {} + if (duration <= 0) { + m_layout.removeView(m_splashScreen); + m_splashScreen = null; + return; + } - @Override - public void onAnimationStart(Animation animation) {} + final Animation fadeOut = new AlphaAnimation(1, 0); + fadeOut.setInterpolator(new AccelerateInterpolator()); + fadeOut.setDuration(duration); + + fadeOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationEnd(Animation animation) { + hideSplashScreen(0); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationStart(Animation animation) { + } + }); + + m_splashScreen.startAnimation(fadeOut); + } }); - - m_splashScreen.startAnimation(fadeOut); } public void notifyLocationChange(int viewId) @@ -381,7 +388,22 @@ public class QtActivityDelegate public void resetOptionsMenu() { - m_activity.invalidateOptionsMenu(); + QtNative.runAction(new Runnable() { + @Override + public void run() { + m_activity.invalidateOptionsMenu(); + } + }); + } + + public void openOptionsMenu() + { + QtNative.runAction(new Runnable() { + @Override + public void run() { + m_activity.openOptionsMenu(); + } + }); } private boolean m_contextMenuVisible = false; @@ -395,31 +417,36 @@ public class QtActivityDelegate public void openContextMenu(final int x, final int y, final int w, final int h) { m_layout.postDelayed(new Runnable() { - @Override - public void run() { - m_layout.setLayoutParams(m_inputDelegate.getQtEditText(), new QtLayout.LayoutParams(w, h, x, y), false); - PopupMenu popup = new PopupMenu(m_activity, m_inputDelegate.getQtEditText()); - QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu()); - popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem menuItem) { - return m_activity.onContextItemSelected(menuItem); - } - }); - popup.setOnDismissListener(new PopupMenu.OnDismissListener() { - @Override - public void onDismiss(PopupMenu popupMenu) { - m_activity.onContextMenuClosed(popupMenu.getMenu()); - } - }); - popup.show(); - } - }, 100); + @Override + public void run() { + m_layout.setLayoutParams(m_inputDelegate.getQtEditText(), new QtLayout.LayoutParams(w, h, x, y), false); + PopupMenu popup = new PopupMenu(m_activity, m_inputDelegate.getQtEditText()); + QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu()); + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + return m_activity.onContextItemSelected(menuItem); + } + }); + popup.setOnDismissListener(new PopupMenu.OnDismissListener() { + @Override + public void onDismiss(PopupMenu popupMenu) { + m_activity.onContextMenuClosed(popupMenu.getMenu()); + } + }); + popup.show(); + } + }, 100); } public void closeContextMenu() { - m_activity.closeContextMenu(); + QtNative.runAction(new Runnable() { + @Override + public void run() { + m_activity.closeContextMenu(); + } + }); } void setActionBarVisibility(boolean visible) @@ -433,96 +460,116 @@ public class QtActivityDelegate } public void insertNativeView(int id, View view, int x, int y, int w, int h) { - if (m_dummyView != null) { - m_layout.removeView(m_dummyView); - m_dummyView = null; - } + QtNative.runAction(new Runnable() { + @Override + public void run() { + if (m_dummyView != null) { + m_layout.removeView(m_dummyView); + m_dummyView = null; + } - if (m_nativeViews.containsKey(id)) - m_layout.removeView(m_nativeViews.remove(id)); + if (m_nativeViews.containsKey(id)) + m_layout.removeView(m_nativeViews.remove(id)); - if (w < 0 || h < 0) { - view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - } else { - view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); - } + if (w < 0 || h < 0) { + view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } else { + view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + } - view.setId(id); - m_layout.addView(view); - m_nativeViews.put(id, view); + view.setId(id); + m_layout.addView(view); + m_nativeViews.put(id, view); + } + }); } public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) { - if (m_surfaces.size() == 0) { - TypedValue attr = new TypedValue(); - m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true); - if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) { - m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data)); - } else { - m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme())); + QtNative.runAction(new Runnable() { + @Override + public void run() { + if (m_surfaces.size() == 0) { + TypedValue attr = new TypedValue(); + m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true); + if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) { + m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data)); + } else { + m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme())); + } + if (m_dummyView != null) { + m_layout.removeView(m_dummyView); + m_dummyView = null; + } + } + + if (m_surfaces.containsKey(id)) + m_layout.removeView(m_surfaces.remove(id)); + + QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth); + if (w < 0 || h < 0) { + surface.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } else { + surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + } + + // Native views are always inserted in the end of the stack (i.e., on top). + // All other views are stacked based on the order they are created. + final int surfaceCount = getSurfaceCount(); + m_layout.addView(surface, surfaceCount); + + m_surfaces.put(id, surface); + if (!m_splashScreenSticky) + hideSplashScreen(); } - if (m_dummyView != null) { - m_layout.removeView(m_dummyView); - m_dummyView = null; - } - } - - if (m_surfaces.containsKey(id)) - m_layout.removeView(m_surfaces.remove(id)); - - QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth); - if (w < 0 || h < 0) { - surface.setLayoutParams( new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - } else { - surface.setLayoutParams( new QtLayout.LayoutParams(w, h, x, y)); - } - - // Native views are always inserted in the end of the stack (i.e., on top). - // All other views are stacked based on the order they are created. - final int surfaceCount = getSurfaceCount(); - m_layout.addView(surface, surfaceCount); - - m_surfaces.put(id, surface); - if (!m_splashScreenSticky) - hideSplashScreen(); + }); } public void setSurfaceGeometry(int id, int x, int y, int w, int h) { - if (m_surfaces.containsKey(id)) { - QtSurface surface = m_surfaces.get(id); - surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); - } else if (m_nativeViews.containsKey(id)) { - View view = m_nativeViews.get(id); - view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); - } else { - Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); - return; - } + QtNative.runAction(new Runnable() { + @Override + public void run() { + if (m_surfaces.containsKey(id)) { + QtSurface surface = m_surfaces.get(id); + surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + } else if (m_nativeViews.containsKey(id)) { + View view = m_nativeViews.get(id); + view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + } else { + Log.e(QtNative.QtTAG, "Surface " + id + " not found!"); + return; + } + } + }); } public void destroySurface(int id) { - View view = null; + QtNative.runAction(new Runnable() { + @Override + public void run() { + View view = null; - if (m_surfaces.containsKey(id)) { - view = m_surfaces.remove(id); - } else if (m_nativeViews.containsKey(id)) { - view = m_nativeViews.remove(id); - } else { - Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); - } + if (m_surfaces.containsKey(id)) { + view = m_surfaces.remove(id); + } else if (m_nativeViews.containsKey(id)) { + view = m_nativeViews.remove(id); + } else { + Log.e(QtNative.QtTAG, "Surface " + id + " not found!"); + } - if (view == null) - return; + if (view == null) + return; - // Keep last frame in stack until it is replaced to get correct - // shutdown transition - if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) { - m_dummyView = view; - } else { - m_layout.removeView(view); - } + // Keep last frame in stack until it is replaced to get correct + // shutdown transition + if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) { + m_dummyView = view; + } else { + m_layout.removeView(view); + } + } + }); } public int getSurfaceCount() @@ -532,31 +579,41 @@ public class QtActivityDelegate public void bringChildToFront(int id) { - View view = m_surfaces.get(id); - if (view != null) { - final int surfaceCount = getSurfaceCount(); - if (surfaceCount > 0) - m_layout.moveChild(view, surfaceCount - 1); - return; - } + QtNative.runAction(new Runnable() { + @Override + public void run() { + View view = m_surfaces.get(id); + if (view != null) { + final int surfaceCount = getSurfaceCount(); + if (surfaceCount > 0) + m_layout.moveChild(view, surfaceCount - 1); + return; + } - view = m_nativeViews.get(id); - if (view != null) - m_layout.moveChild(view, -1); + view = m_nativeViews.get(id); + if (view != null) + m_layout.moveChild(view, -1); + } + }); } public void bringChildToBack(int id) { - View view = m_surfaces.get(id); - if (view != null) { - m_layout.moveChild(view, 0); - return; - } + QtNative.runAction(new Runnable() { + @Override + public void run() { + View view = m_surfaces.get(id); + if (view != null) { + m_layout.moveChild(view, 0); + return; + } - view = m_nativeViews.get(id); - if (view != null) { - final int index = getSurfaceCount(); - m_layout.moveChild(view, index); - } + view = m_nativeViews.get(id); + if (view != null) { + final int index = getSurfaceCount(); + m_layout.moveChild(view, index); + } + } + }); } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtEditText.java b/src/android/jar/src/org/qtproject/qt/android/QtEditText.java index b2df8959cce..a802abb2d47 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtEditText.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtEditText.java @@ -10,6 +10,8 @@ import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; +import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener; + public class QtEditText extends View { int m_initialCapsMode = 0; @@ -17,6 +19,13 @@ public class QtEditText extends View int m_inputType = InputType.TYPE_CLASS_TEXT; boolean m_optionsChanged = false; + private QtInputConnectionListener m_qtInputConnectionListener; + + public void setQtInputConnectionListener(QtInputConnectionListener listener) + { + m_qtInputConnectionListener = listener; + } + public void setImeOptions(int m_imeOptions) { if (m_imeOptions == this.m_imeOptions) @@ -56,7 +65,7 @@ public class QtEditText extends View outAttrs.imeOptions = m_imeOptions; outAttrs.initialCapsMode = m_initialCapsMode; outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI; - return new QtInputConnection(this); + return new QtInputConnection(this, m_qtInputConnectionListener); } // // DEBUG CODE diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java index bce476a94c6..5b76a9f4d87 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java @@ -51,31 +51,6 @@ class QtNativeInputConnection static native boolean updateCursorPosition(); } -class HideKeyboardRunnable implements Runnable { - private long m_hideTimeStamp = System.nanoTime(); - - @Override - public void run() { - // Check that the keyboard is really no longer there. - Activity activity = QtNative.activity(); - Rect r = new Rect(); - activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); - - int screenHeight = 0; - if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - DisplayMetrics metrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); - screenHeight = metrics.heightPixels; - } else { - final WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics(); - screenHeight = maximumWindowMetrics.getBounds().height(); - } - final int kbHeight = screenHeight - r.bottom; - if (kbHeight < 100) - QtNative.activityDelegate().getInputDelegate().setKeyboardVisibility(false, m_hideTimeStamp); - } -} - public class QtInputConnection extends BaseInputConnection { private static final int ID_SELECT_ALL = android.R.id.selectAll; @@ -86,21 +61,52 @@ public class QtInputConnection extends BaseInputConnection private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod; private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary; + private final QtInputConnectionListener m_qtInputConnectionListener; + + class HideKeyboardRunnable implements Runnable { + @Override + public void run() { + // Check that the keyboard is really no longer there. + Activity activity = QtNative.activity(); + Rect r = new Rect(); + activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); + + int screenHeight = 0; + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + DisplayMetrics metrics = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + screenHeight = metrics.heightPixels; + } else { + final WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics(); + screenHeight = maximumWindowMetrics.getBounds().height(); + } + final int kbHeight = screenHeight - r.bottom; + if (kbHeight < 100) + m_qtInputConnectionListener.onHideKeyboardRunnableDone(false, System.nanoTime()); + } + } + + public interface QtInputConnectionListener { + void onSetClosing(boolean closing); + void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp); + void onSendKeyEventDefaultCase(); + } + private QtEditText m_view = null; private void setClosing(boolean closing) { - if (closing) { + if (closing) m_view.postDelayed(new HideKeyboardRunnable(), 100); - } else { - QtNative.activityDelegate().getInputDelegate().setKeyboardVisibility(true, System.nanoTime()); - } + else + m_qtInputConnectionListener.onSetClosing(false); } - public QtInputConnection(QtEditText targetView) + public QtInputConnection(QtEditText targetView, QtInputConnectionListener listener) { super(targetView, true); m_view = targetView; + m_qtInputConnectionListener = listener; } @Override @@ -256,7 +262,7 @@ public class QtInputConnection extends BaseInputConnection break; default: - QtNative.activityDelegate().getInputDelegate().hideSoftwareKeyboard(); + m_qtInputConnectionListener.onSendKeyEventDefaultCase(); break; } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java index ebdfd5339c0..ee53dcd9acd 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java @@ -4,6 +4,7 @@ package org.qtproject.qt.android; import android.app.Activity; +import android.content.Context; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; @@ -17,6 +18,8 @@ import android.view.MotionEvent; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; +import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener; + public class QtInputDelegate { // keyboard methods @@ -96,7 +99,7 @@ public class QtInputDelegate { private int m_lastChar = 0; private boolean m_backKeyPressedSent = false; - // Note: because of the circular call to updateFullScreen() from QtActivityDelegate, we need + // Note: because of the circular call to updateFullScreen() from the delegate, we need // a listener to be able to do that call from the delegate, because that's where that // logic lives public interface KeyboardVisibilityListener { @@ -105,9 +108,29 @@ public class QtInputDelegate { private final KeyboardVisibilityListener m_keyboardVisibilityListener; - QtInputDelegate(KeyboardVisibilityListener listener) + QtInputDelegate(Activity activity, KeyboardVisibilityListener listener) { this.m_keyboardVisibilityListener = listener; + m_editText = new QtEditText(activity); + m_imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + QtInputConnectionListener inputConnectionListener = new QtInputConnectionListener() { + @Override + public void onSetClosing(boolean closing) { + if (!closing) + setKeyboardVisibility(true, System.nanoTime()); + } + + @Override + public void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp) { + setKeyboardVisibility(visibility, hideTimeStamp); + } + + @Override + public void onSendKeyEventDefaultCase() { + hideSoftwareKeyboard(); + } + }; + m_editText.setQtInputConnectionListener(inputConnectionListener); } public boolean isKeyboardVisible() @@ -131,16 +154,6 @@ public class QtInputDelegate { return m_editText; } - void setEditText(QtEditText editText) - { - m_editText = editText; - } - - void setInputMethodManager(InputMethodManager inputMethodManager) - { - m_imm = inputMethodManager; - } - void setEditPopupMenu(EditPopupMenu editPopupMenu) { m_editPopupMenu = editPopupMenu; diff --git a/src/android/jar/src/org/qtproject/qt/android/QtNative.java b/src/android/jar/src/org/qtproject/qt/android/QtNative.java index 4b812121cd2..b8d59785368 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtNative.java @@ -54,11 +54,10 @@ import android.graphics.Rect; public class QtNative { + // TODO get rid of the delegation from QtNative, call directly the Activity in c++ private static Activity m_activity = null; private static boolean m_activityPaused = false; private static Service m_service = null; - private static QtActivityDelegate m_activityDelegate = null; - private static QtServiceDelegate m_serviceDelegate = null; public static Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations public static final String QtTAG = "Qt JAVA"; // string used for Log.x @@ -81,8 +80,8 @@ public class QtNative public static boolean isStarted() { - boolean hasActivity = m_activity != null && m_activityDelegate != null; - boolean hasService = m_service != null && m_serviceDelegate != null; + boolean hasActivity = m_activity != null; + boolean hasService = m_service != null; return m_started && (hasActivity || hasService); } @@ -111,21 +110,6 @@ public class QtNative } } - - public static QtActivityDelegate activityDelegate() - { - synchronized (m_mainActivityMutex) { - return m_activityDelegate; - } - } - - public static QtServiceDelegate serviceDelegate() - { - synchronized (m_mainActivityMutex) { - return m_serviceDelegate; - } - } - public static String[] getStringArray(String joinedString) { return joinedString.split(","); @@ -204,19 +188,17 @@ public class QtNative return m_qtThread; } - public static void setActivity(Activity qtMainActivity, QtActivityDelegate qtActivityDelegate) + public static void setActivity(Activity qtMainActivity) { synchronized (m_mainActivityMutex) { m_activity = qtMainActivity; - m_activityDelegate = qtActivityDelegate; } } - public static void setService(Service qtMainService, QtServiceDelegate qtServiceDelegate) + public static void setService(Service qtMainService) { synchronized (m_mainActivityMutex) { m_service = qtMainService; - m_serviceDelegate = qtServiceDelegate; } } @@ -349,72 +331,6 @@ public class QtNative return perm; } - // TODO get rid of the delegation from QtNative, call directly the Activity in c++ - private static void setSystemUiVisibility(final int systemUiVisibility) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) { - m_activityDelegate.setSystemUiVisibility(systemUiVisibility); - } - updateWindow(); - } - }); - } - - public static void notifyQtAndroidPluginRunning(final boolean running) - { - if (m_activityDelegate != null) - m_activityDelegate.notifyQtAndroidPluginRunning(running); - } - - - - private static void openContextMenu(final int x, final int y, final int w, final int h) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.openContextMenu(x, y, w, h); - } - }); - } - - private static void closeContextMenu() - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.closeContextMenu(); - } - }); - } - - private static void resetOptionsMenu() - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.resetOptionsMenu(); - } - }); - } - - private static void openOptionsMenu() - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activity != null) - m_activity.openOptionsMenu(); - } - }); - } - private static byte[][] getSSLCertificates() { ArrayList certificateList = new ArrayList(); @@ -442,83 +358,6 @@ public class QtNative return certificateArray; } - private static void createSurface(final int id, final boolean onTop, final int x, final int y, final int w, final int h, final int imageDepth) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.createSurface(id, onTop, x, y, w, h, imageDepth); - } - }); - } - - private static void insertNativeView(final int id, final View view, final int x, final int y, final int w, final int h) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.insertNativeView(id, view, x, y, w, h); - } - }); - } - - private static void setSurfaceGeometry(final int id, final int x, final int y, final int w, final int h) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.setSurfaceGeometry(id, x, y, w, h); - } - }); - } - - private static void bringChildToFront(final int id) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.bringChildToFront(id); - } - }); - } - - private static void bringChildToBack(final int id) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.bringChildToBack(id); - } - }); - } - - private static void destroySurface(final int id) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.destroySurface(id); - } - }); - } - - private static void hideSplashScreen(final int duration) - { - runAction(new Runnable() { - @Override - public void run() { - if (m_activityDelegate != null) - m_activityDelegate.hideSplashScreen(duration); - } - }); - } - private static String[] listAssetContent(android.content.res.AssetManager asset, String path) { String [] list; ArrayList res = new ArrayList(); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java index 268a53044fb..51eba48e6bf 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java @@ -9,15 +9,11 @@ import android.os.IBinder; import android.util.Log; public class QtServiceBase extends Service { - private QtServiceDelegate m_delegate; - @Override public void onCreate() { super.onCreate(); - m_delegate = new QtServiceDelegate(this); - // the application has already started, do not reload everything again if (QtNative.isStarted()) { Log.w(QtNative.QtTAG, @@ -38,7 +34,7 @@ public class QtServiceBase extends Service { super.onDestroy(); QtNative.quitQtCoreApplication(); QtNative.terminateQt(); - QtNative.setService(null, null); + QtNative.setService(null); QtNative.m_qtThread.exit(); System.exit(0); } @@ -49,9 +45,4 @@ public class QtServiceBase extends Service { return QtNative.onBind(intent); } } - - QtServiceDelegate getServiceDelegate() - { - return m_delegate; - } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java deleted file mode 100644 index 9791bf78fc1..00000000000 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2016 BogDan Vatra -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -package org.qtproject.qt.android; - -import android.app.Service; - -public class QtServiceDelegate -{ - private Service m_service = null; - - QtServiceDelegate(Service service) - { - m_service = service; - - // Set native context - QtNative.setService(m_service, this); - } -} diff --git a/src/corelib/platform/android/qandroidnativeinterface.cpp b/src/corelib/platform/android/qandroidnativeinterface.cpp index 3632c7fad43..e9a59578955 100644 --- a/src/corelib/platform/android/qandroidnativeinterface.cpp +++ b/src/corelib/platform/android/qandroidnativeinterface.cpp @@ -94,8 +94,7 @@ int QNativeInterface::QAndroidApplication::sdkVersion() */ void QNativeInterface::QAndroidApplication::hideSplashScreen(int duration) { - QJniObject::callStaticMethod("org/qtproject/qt/android/QtNative", - "hideSplashScreen", "(I)V", duration); + QtAndroidPrivate::activity().callMethod("hideSplashScreen", duration); } /*! diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 9f44a2ffe01..2cbd35e019a 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -45,9 +45,6 @@ static jmethodID m_loadClassMethodID = nullptr; static AAssetManager *m_assetManager = nullptr; static jobject m_assets = nullptr; static jobject m_resourcesObj = nullptr; -static jmethodID m_createSurfaceMethodID = nullptr; -static jmethodID m_setSurfaceGeometryMethodID = nullptr; -static jmethodID m_destroySurfaceMethodID = nullptr; static QtJniTypes::QtActivityDelegate m_activityDelegate = nullptr; static QtJniTypes::QtInputDelegate m_inputDelegate = nullptr; @@ -165,7 +162,7 @@ namespace QtAndroid // TODO move calls from here to where they logically belong void setSystemUiVisibility(SystemUiVisibility uiVisibility) { - QJniObject::callStaticMethod(m_applicationClass, "setSystemUiVisibility", "(I)V", jint(uiVisibility)); + qtActivityDelegate().callMethod("setSystemUiVisibility", jint(uiVisibility)); } // FIXME: avoid direct access to QtActivityDelegate @@ -218,7 +215,7 @@ namespace QtAndroid void notifyQtAndroidPluginRunning(bool running) { - QJniObject::callStaticMethod(m_applicationClass, "notifyQtAndroidPluginRunning","(Z)V", running); + qtActivityDelegate().callMethod("notifyQtAndroidPluginRunning", running); } jobject createBitmap(QImage img, JNIEnv *env) @@ -338,12 +335,8 @@ namespace QtAndroid w = std::max(geometry.width(), 1); h = std::max(geometry.height(), 1); } - env->CallStaticVoidMethod(m_applicationClass, - m_createSurfaceMethodID, - surfaceId, - jboolean(onTop), - x, y, w, h, - imageDepth); + qtActivityDelegate().callMethod("createSurface", surfaceId, jboolean(onTop), + x, y, w, h, imageDepth); return surfaceId; } @@ -358,9 +351,7 @@ namespace QtAndroid if (!geometry.isNull()) geometry.getRect(&x, &y, &w, &h); - QJniObject::callStaticMethod(m_applicationClass, - "insertNativeView", - "(ILandroid/view/View;IIII)V", + qtActivityDelegate().callMethod("insertNativeView", surfaceId, view, x, @@ -395,10 +386,7 @@ namespace QtAndroid w = geometry.width(); h = geometry.height(); } - env->CallStaticVoidMethod(m_applicationClass, - m_setSurfaceGeometryMethodID, - surfaceId, - x, y, w, h); + qtActivityDelegate().callMethod("setSurfaceGeometry", surfaceId, x, y, w, h); } @@ -414,11 +402,7 @@ namespace QtAndroid m_surfaces.erase(it); } - QJniEnvironment env; - if (env.jniEnv()) - env->CallStaticVoidMethod(m_applicationClass, - m_destroySurfaceMethodID, - surfaceId); + qtActivityDelegate().callMethod("destroySurface", surfaceId); } void bringChildToFront(int surfaceId) @@ -426,10 +410,7 @@ namespace QtAndroid if (surfaceId == -1) return; - QJniObject::callStaticMethod(m_applicationClass, - "bringChildToFront", - "(I)V", - surfaceId); + qtActivityDelegate().callMethod("bringChildToFront", surfaceId); } void bringChildToBack(int surfaceId) @@ -437,10 +418,7 @@ namespace QtAndroid if (surfaceId == -1) return; - QJniObject::callStaticMethod(m_applicationClass, - "bringChildToBack", - "(I)V", - surfaceId); + qtActivityDelegate().callMethod("bringChildToBack", surfaceId); } bool blockEventLoopsWhenSuspended() @@ -893,10 +871,6 @@ static bool registerNatives(QJniEnvironment &env) return JNI_FALSE; } - GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIIII)V"); - GET_AND_CHECK_STATIC_METHOD(m_setSurfaceGeometryMethodID, m_applicationClass, "setSurfaceGeometry", "(IIIII)V"); - GET_AND_CHECK_STATIC_METHOD(m_destroySurfaceMethodID, m_applicationClass, "destroySurface", "(I)V"); - jmethodID methodID; GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "activity", "()Landroid/app/Activity;"); jobject contextObject = env->CallStaticObjectMethod(m_applicationClass, methodID); diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp index a8af3feeb5c..8bf37d1af21 100644 --- a/src/plugins/platforms/android/androidjnimenu.cpp +++ b/src/plugins/platforms/android/androidjnimenu.cpp @@ -31,8 +31,6 @@ namespace QtAndroidMenu static QWindow *activeTopLevelWindow = nullptr; Q_CONSTINIT static QRecursiveMutex menuBarMutex; - static jmethodID openContextMenuMethodID = 0; - static jmethodID clearMenuMethodID = 0; static jmethodID addMenuItemMethodID = 0; static int menuNoneValue = 0; @@ -46,29 +44,31 @@ namespace QtAndroidMenu void resetMenuBar() { - QJniObject::callStaticMethod(applicationClass(), "resetOptionsMenu"); + qtActivityDelegate().callMethod("resetOptionsMenu"); } void openOptionsMenu() { - QJniObject::callStaticMethod(applicationClass(), "openOptionsMenu"); + qtActivityDelegate().callMethod("openOptionsMenu"); } - void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env) + void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect) { QMutexLocker lock(&visibleMenuMutex); if (visibleMenu) pendingContextMenus.append(visibleMenu); visibleMenu = menu; menu->aboutToShow(); - env->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); + qtActivityDelegate().callMethod("openContextMenu", + anchorRect.x(), anchorRect.y(), + anchorRect.width(), anchorRect.height()); } void hideContextMenu(QAndroidPlatformMenu *menu) { QMutexLocker lock(&visibleMenuMutex); if (visibleMenu == menu) { - QJniObject::callStaticMethod(applicationClass(), "closeContextMenu"); + qtActivityDelegate().callMethod("closeContextMenu"); pendingContextMenus.clear(); } else { pendingContextMenus.removeOne(menu); @@ -211,8 +211,10 @@ namespace QtAndroidMenu return order; } - static jboolean onPrepareOptionsMenu(JNIEnv *env, jobject /*thiz*/, jobject menu) + static jboolean onPrepareOptionsMenu(JNIEnv *env, jobject thiz, jobject menu) { + Q_UNUSED(thiz) + env->CallVoidMethod(menu, clearMenuMethodID); QMutexLocker lock(&menuBarMutex); if (!visibleMenuBar) @@ -249,8 +251,11 @@ namespace QtAndroidMenu return order ? JNI_TRUE : JNI_FALSE; } - static jboolean onOptionsItemSelected(JNIEnv *env, jobject /*thiz*/, jint menuId, jboolean checked) + static jboolean onOptionsItemSelected(JNIEnv *env, jobject thiz, jint menuId, jboolean checked) { + Q_UNUSED(env) + Q_UNUSED(thiz) + QMutexLocker lock(&menuBarMutex); if (!visibleMenuBar) return JNI_FALSE; @@ -260,7 +265,7 @@ namespace QtAndroidMenu QAndroidPlatformMenuItem *item = static_cast(menus.front()->menuItemForId(menuId)); if (item) { if (item->menu()) { - showContextMenu(item->menu(), QRect(), env); + showContextMenu(item->menu(), QRect()); } else { if (item->isCheckable()) item->setChecked(checked); @@ -270,18 +275,23 @@ namespace QtAndroidMenu } else { QAndroidPlatformMenu *menu = static_cast(visibleMenuBar->menuForId(menuId)); if (menu) - showContextMenu(menu, QRect(), env); + showContextMenu(menu, QRect()); } return JNI_TRUE; } - static void onOptionsMenuClosed(JNIEnv */*env*/, jobject /*thiz*/, jobject /*menu*/) + static void onOptionsMenuClosed(JNIEnv *env, jobject thiz, jobject menu) { + Q_UNUSED(env) + Q_UNUSED(thiz) + Q_UNUSED(menu) } - static void onCreateContextMenu(JNIEnv *env, jobject /*thiz*/, jobject menu) + static void onCreateContextMenu(JNIEnv *env, jobject thiz, jobject menu) { + Q_UNUSED(thiz) + env->CallVoidMethod(menu, clearMenuMethodID); QMutexLocker lock(&visibleMenuMutex); if (!visibleMenu) @@ -295,8 +305,9 @@ namespace QtAndroidMenu addAllMenuItemsToMenu(env, menu, visibleMenu); } - static void fillContextMenu(JNIEnv *env, jobject /*thiz*/, jobject menu) + static void fillContextMenu(JNIEnv *env, jobject thiz, jobject menu) { + Q_UNUSED(thiz) env->CallVoidMethod(menu, clearMenuMethodID); QMutexLocker lock(&visibleMenuMutex); if (!visibleMenu) @@ -305,13 +316,16 @@ namespace QtAndroidMenu addAllMenuItemsToMenu(env, menu, visibleMenu); } - static jboolean onContextItemSelected(JNIEnv *env, jobject /*thiz*/, jint menuId, jboolean checked) + static jboolean onContextItemSelected(JNIEnv *env, jobject thiz, jint menuId, jboolean checked) { + Q_UNUSED(env) + Q_UNUSED(thiz) + QMutexLocker lock(&visibleMenuMutex); QAndroidPlatformMenuItem * item = static_cast(visibleMenu->menuItemForId(menuId)); if (item) { if (item->menu()) { - showContextMenu(item->menu(), QRect(), env); + showContextMenu(item->menu(), QRect()); } else { if (item->isCheckable()) item->setChecked(checked); @@ -328,8 +342,12 @@ namespace QtAndroidMenu return JNI_TRUE; } - static void onContextMenuClosed(JNIEnv *env, jobject /*thiz*/, jobject /*menu*/) + static void onContextMenuClosed(JNIEnv *env, jobject thiz, jobject menu) { + Q_UNUSED(env) + Q_UNUSED(thiz) + Q_UNUSED(menu) + QMutexLocker lock(&visibleMenuMutex); if (!visibleMenu) return; @@ -337,7 +355,7 @@ namespace QtAndroidMenu visibleMenu->aboutToHide(); visibleMenu = 0; if (!pendingContextMenus.empty()) - showContextMenu(pendingContextMenus.takeLast(), QRect(), env); + showContextMenu(pendingContextMenus.takeLast(), QRect()); } static JNINativeMethod methods[] = { @@ -387,8 +405,6 @@ namespace QtAndroidMenu return false; } - GET_AND_CHECK_STATIC_METHOD(openContextMenuMethodID, appClass, "openContextMenu", "(IIII)V"); - jclass clazz; FIND_AND_CHECK_CLASS("android/view/Menu"); GET_AND_CHECK_METHOD(clearMenuMethodID, clazz, "clear", "()V"); diff --git a/src/plugins/platforms/android/androidjnimenu.h b/src/plugins/platforms/android/androidjnimenu.h index 308f34867cc..e10ad930d93 100644 --- a/src/plugins/platforms/android/androidjnimenu.h +++ b/src/plugins/platforms/android/androidjnimenu.h @@ -21,7 +21,7 @@ namespace QtAndroidMenu { // Menu support void openOptionsMenu(); - void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env); + void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect); void hideContextMenu(QAndroidPlatformMenu *menu); void syncMenu(QAndroidPlatformMenu *menu); void androidPlatformMenuDestroyed(QAndroidPlatformMenu *menu); diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp index 4ddd6ea29a1..e59fd2089dc 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp @@ -119,7 +119,7 @@ void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &t Q_UNUSED(parentWindow); Q_UNUSED(item); setVisible(true); - QtAndroidMenu::showContextMenu(this, targetRect, QJniEnvironment().jniEnv()); + QtAndroidMenu::showContextMenu(this, targetRect); } QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const diff --git a/tests/auto/corelib/platform/android/tst_android.cpp b/tests/auto/corelib/platform/android/tst_android.cpp index 1be12e0c33e..8d0bf1e72cc 100644 --- a/tests/auto/corelib/platform/android/tst_android.cpp +++ b/tests/auto/corelib/platform/android/tst_android.cpp @@ -199,11 +199,14 @@ void tst_Android::testRunOnAndroidMainThread() } } +Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate") + void setSystemUiVisibility(int visibility) { QNativeInterface::QAndroidApplication::runOnAndroidMainThread([visibility] { - QJniObject::callStaticMethod("org/qtproject/qt/android/QtNative", - "setSystemUiVisibility", "(I)V", visibility); + auto context = QNativeInterface::QAndroidApplication::context(); + auto activityDelegate = context.callMethod("getActivityDelegate"); + activityDelegate.callMethod("setSystemUiVisibility", jint(visibility)); }).waitForFinished(); }