Android: Add a context delegate for embedding QML to native Android

When we are embedding a QML view to a non-Qt Android app, there are a lot
of functionalities that are shared with the refular Qt Android app, but
some are not. We should not, for example, try to control the hosting
Activity.
Create a base class that both the QtActivityDelegate, used for the
standard Qt for Android app, and the delegate for the embedding case
can extend.

In this commit, the QtEmbeddedDelegate is very simple, the
biggest difference to QtActivityDelegate being it does not create
a QtLayout or instantiate a QtAccessibilityDelegate.
It does start the Qt app, without waiting for a layout, and register
to listen for changes in the state of the Qt app.

Taking the embedded delegate into use, loading the embedded QML
views and their handling is added in a follow up commit.

Task-number: QTBUG-118872
Change-Id: Id390a2b35c70b35880523886bf6fcf59d420cb42
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 06d2aa91eb4faafc0e52faafeb184d6d3da671ab)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tinja Paavoseppä 2024-01-10 16:21:57 +02:00 committed by Qt Cherry-pick Bot
parent 66b732244a
commit 03ca126bb6
8 changed files with 455 additions and 150 deletions

View File

@ -33,6 +33,8 @@ set(java_sources
src/org/qtproject/qt/android/UsedFromNativeCode.java
src/org/qtproject/qt/android/QtRootLayout.java
src/org/qtproject/qt/android/QtWindow.java
src/org/qtproject/qt/android/QtActivityDelegateBase.java
src/org/qtproject/qt/android/QtEmbeddedDelegate.java
)
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android

View File

@ -318,7 +318,7 @@ public class QtActivityBase extends Activity
}
@UsedFromNativeCode
QtActivityDelegate getActivityDelegate()
QtActivityDelegateBase getActivityDelegate()
{
return m_delegate;
}

View File

@ -33,48 +33,36 @@ import android.widget.PopupMenu;
import java.util.HashMap;
class QtActivityDelegate
class QtActivityDelegate extends QtActivityDelegateBase
{
private Activity m_activity;
private static final String QtTAG = "QtActivityDelegate";
private QtRootLayout m_layout = null;
private HashMap<Integer, QtWindow> m_topLevelWindows;
private ImageView m_splashScreen = null;
private boolean m_splashScreenSticky = false;
private View m_dummyView = null;
private QtAccessibilityDelegate m_accessibilityDelegate = null;
private QtDisplayManager m_displayManager = null;
private QtInputDelegate m_inputDelegate = null;
private boolean m_membersInitialized = false;
QtActivityDelegate(Activity activity)
{
m_activity = activity;
QtNative.setActivity(m_activity);
super(activity);
setActionBarVisibility(false);
setActivityBackgroundDrawable();
}
QtDisplayManager displayManager() {
return m_displayManager;
}
@UsedFromNativeCode
QtInputDelegate getInputDelegate() {
return m_inputDelegate;
}
@UsedFromNativeCode
@Override
QtLayout getQtLayout()
{
return m_layout;
}
@UsedFromNativeCode
public void setSystemUiVisibility(int systemUiVisibility)
@Override
void setSystemUiVisibility(int systemUiVisibility)
{
QtNative.runAction(() -> {
m_displayManager.setSystemUiVisibility(systemUiVisibility);
@ -83,45 +71,24 @@ class QtActivityDelegate
});
}
void setContextMenuVisible(boolean contextMenuVisible)
{
m_contextMenuVisible = contextMenuVisible;
}
boolean isContextMenuVisible()
{
return m_contextMenuVisible;
}
@Override
public boolean updateActivityAfterRestart(Activity activity) {
try {
// set new activity
m_activity = activity;
QtNative.setActivity(m_activity);
boolean updated = super.updateActivityAfterRestart(activity);
// TODO verify whether this is even needed, the last I checked the initMembers
// recreates the layout anyway
// update the new activity content view to old layout
ViewGroup layoutParent = (ViewGroup)m_layout.getParent();
if (layoutParent != null)
layoutParent.removeView(m_layout);
// update the new activity content view to old layout
ViewGroup layoutParent = (ViewGroup) m_layout.getParent();
if (layoutParent != null)
layoutParent.removeView(m_layout);
m_activity.setContentView(m_layout);
m_activity.setContentView(m_layout);
// force c++ native activity object to update
return QtNative.updateNativeActivity();
} catch (Exception e) {
Log.w(QtNative.QtTAG, "Failed to update the activity.");
e.printStackTrace();
return false;
}
return updated;
}
public void startNativeApplication(String appParams, String mainLib)
@Override
void startNativeApplicationImpl(String appParams, String mainLib)
{
if (m_membersInitialized)
return;
initMembers();
m_layout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
@ -132,50 +99,13 @@ class QtActivityDelegate
});
}
private void initMembers()
@Override
protected void setUpLayout()
{
m_layout = new QtRootLayout(m_activity);
m_membersInitialized = true;
m_topLevelWindows = new HashMap<Integer, QtWindow>();
m_displayManager = new QtDisplayManager(m_activity);
m_displayManager.registerDisplayListener();
QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener =
() -> m_displayManager.updateFullScreen();
m_inputDelegate = new QtInputDelegate(m_activity, keyboardVisibilityListener);
try {
PackageManager pm = m_activity.getPackageManager();
ActivityInfo activityInfo = pm.getActivityInfo(m_activity.getComponentName(), 0);
m_inputDelegate.setSoftInputMode(activityInfo.softInputMode);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
int orientation = m_activity.getResources().getConfiguration().orientation;
m_layout = new QtRootLayout(m_activity);
try {
ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA);
String splashScreenKey = "android.app.splash_screen_drawable_"
+ (orientation == Configuration.ORIENTATION_LANDSCAPE ? "landscape" : "portrait");
if (!info.metaData.containsKey(splashScreenKey))
splashScreenKey = "android.app.splash_screen_drawable";
if (info.metaData.containsKey(splashScreenKey)) {
m_splashScreenSticky = info.metaData.containsKey("android.app.splash_screen_sticky") && info.metaData.getBoolean("android.app.splash_screen_sticky");
int id = info.metaData.getInt(splashScreenKey);
m_splashScreen = new ImageView(m_activity);
m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(id, m_activity.getTheme()));
m_splashScreen.setScaleType(ImageView.ScaleType.FIT_XY);
m_splashScreen.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
m_layout.addView(m_splashScreen);
}
} catch (Exception e) {
e.printStackTrace();
}
setUpSplashScreen(orientation);
m_activity.registerForContextMenu(m_layout);
m_activity.setContentView(m_layout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
@ -211,12 +141,41 @@ class QtActivityDelegate
m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_layout));
}
public void hideSplashScreen()
@Override
protected void setUpSplashScreen(int orientation)
{
hideSplashScreen(0);
try {
ActivityInfo info = m_activity.getPackageManager().getActivityInfo(
m_activity.getComponentName(),
PackageManager.GET_META_DATA);
String splashScreenKey = "android.app.splash_screen_drawable_"
+ (orientation == Configuration.ORIENTATION_LANDSCAPE ? "landscape" : "portrait");
if (!info.metaData.containsKey(splashScreenKey))
splashScreenKey = "android.app.splash_screen_drawable";
if (info.metaData.containsKey(splashScreenKey)) {
m_splashScreenSticky =
info.metaData.containsKey("android.app.splash_screen_sticky") &&
info.metaData.getBoolean("android.app.splash_screen_sticky");
int id = info.metaData.getInt(splashScreenKey);
m_splashScreen = new ImageView(m_activity);
m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(
id, m_activity.getTheme()));
m_splashScreen.setScaleType(ImageView.ScaleType.FIT_XY);
m_splashScreen.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
m_layout.addView(m_splashScreen);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void hideSplashScreen(final int duration)
@Override
protected void hideSplashScreen(final int duration)
{
QtNative.runAction(() -> {
if (m_splashScreen == null)
@ -251,50 +210,16 @@ class QtActivityDelegate
});
}
@UsedFromNativeCode
public void notifyLocationChange(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyLocationChange(viewId);
}
@UsedFromNativeCode
public void notifyObjectHide(int viewId, int parentId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyObjectHide(viewId, parentId);
}
@UsedFromNativeCode
public void notifyObjectFocus(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyObjectFocus(viewId);
}
@UsedFromNativeCode
public void notifyValueChanged(int viewId, String value)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyValueChanged(viewId, value);
}
@UsedFromNativeCode
public void notifyScrolledEvent(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyScrolledEvent(viewId);
}
@UsedFromNativeCode
public void initializeAccessibility()
{
QtNative.runAction(() -> m_accessibilityDelegate = new QtAccessibilityDelegate(m_layout));
QtNative.runAction(() -> {
// FIXME make QtAccessibilityDelegate window based
if (m_layout != null)
m_accessibilityDelegate = new QtAccessibilityDelegate(m_layout);
else
Log.w(QtTAG, "Null layout, failed to initialize accessibility delegate.");
});
}
void handleUiModeChange(int uiMode)
@ -345,6 +270,7 @@ class QtActivityDelegate
}
@UsedFromNativeCode
@Override
public void openContextMenu(final int x, final int y, final int w, final int h)
{
m_layout.postDelayed(() -> {
@ -365,6 +291,7 @@ class QtActivityDelegate
QtNative.runAction(() -> m_activity.closeContextMenu());
}
@Override
void setActionBarVisibility(boolean visible)
{
if (m_activity.getActionBar() == null)
@ -376,8 +303,12 @@ class QtActivityDelegate
}
@UsedFromNativeCode
@Override
public void addTopLevelWindow(final QtWindow window)
{
if (window == null)
return;
QtNative.runAction(()-> {
if (m_topLevelWindows.size() == 0) {
if (m_dummyView != null) {
@ -398,7 +329,8 @@ class QtActivityDelegate
}
@UsedFromNativeCode
public void removeTopLevelWindow(final int id)
@Override
void removeTopLevelWindow(final int id)
{
QtNative.runAction(()-> {
if (m_topLevelWindows.containsKey(id)) {
@ -415,18 +347,19 @@ class QtActivityDelegate
}
@UsedFromNativeCode
public void bringChildToFront(final int id)
@Override
void bringChildToFront(final int id)
{
QtNative.runAction(() -> {
QtWindow window = m_topLevelWindows.get(id);
if (window != null) {
if (window != null)
m_layout.moveChild(window.getLayout(), m_topLevelWindows.size() - 1);
}
});
}
@UsedFromNativeCode
public void bringChildToBack(int id)
@Override
void bringChildToBack(int id)
{
QtNative.runAction(() -> {
QtWindow window = m_topLevelWindows.get(id);
@ -435,6 +368,16 @@ class QtActivityDelegate
});
}
@Override
QtAccessibilityDelegate createAccessibilityDelegate()
{
if (m_layout != null)
return new QtAccessibilityDelegate(m_layout);
Log.w(QtTAG, "Null layout, failed to initialize accessibility delegate.");
return null;
}
private void setActivityBackgroundDrawable()
{
TypedValue attr = new TypedValue();

View File

@ -0,0 +1,240 @@
// Copyright (C) 2017 BogDan Vatra <bogdan@kde.org>
// Copyright (C) 2023 The Qt Company Ltd.
// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
// 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.Activity;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.Rect;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.Menu;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsetsController;
import android.widget.ImageView;
import android.widget.PopupMenu;
import java.util.HashMap;
abstract class QtActivityDelegateBase
{
protected Activity m_activity;
protected HashMap<Integer, QtWindow> m_topLevelWindows;
protected QtAccessibilityDelegate m_accessibilityDelegate = null;
protected QtDisplayManager m_displayManager = null;
protected QtInputDelegate m_inputDelegate = null;
private boolean m_membersInitialized = false;
private boolean m_contextMenuVisible = false;
// Subclass must implement these
abstract void startNativeApplicationImpl(String appParams, String mainLib);
abstract QtAccessibilityDelegate createAccessibilityDelegate();
abstract QtLayout getQtLayout();
// With these we are okay with default implementation doing nothing
void setUpLayout() {}
void setUpSplashScreen(int orientation) {}
void hideSplashScreen(final int duration) {}
void openContextMenu(final int x, final int y, final int w, final int h) {}
void setActionBarVisibility(boolean visible) {}
void addTopLevelWindow(final QtWindow window) {}
void removeTopLevelWindow(final int id) {}
void bringChildToFront(final int id) {}
void bringChildToBack(int id) {}
void setSystemUiVisibility(int systemUiVisibility) {}
QtActivityDelegateBase(Activity activity)
{
m_activity = activity;
// Set native context
QtNative.setActivity(m_activity);
}
QtDisplayManager displayManager() {
return m_displayManager;
}
@UsedFromNativeCode
QtInputDelegate getInputDelegate() {
return m_inputDelegate;
}
void setContextMenuVisible(boolean contextMenuVisible)
{
m_contextMenuVisible = contextMenuVisible;
}
boolean isContextMenuVisible()
{
return m_contextMenuVisible;
}
public boolean updateActivityAfterRestart(Activity activity) {
try {
// set new activity
m_activity = activity;
QtNative.setActivity(m_activity);
// force c++ native activity object to update
return QtNative.updateNativeActivity();
} catch (Exception e) {
Log.w(QtNative.QtTAG, "Failed to update the activity.");
e.printStackTrace();
return false;
}
}
public void startNativeApplication(String appParams, String mainLib)
{
if (m_membersInitialized)
return;
initMembers();
startNativeApplicationImpl(appParams, mainLib);
}
void initMembers()
{
m_membersInitialized = true;
m_topLevelWindows = new HashMap<Integer, QtWindow>();
m_displayManager = new QtDisplayManager(m_activity);
m_displayManager.registerDisplayListener();
QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener =
() -> m_displayManager.updateFullScreen();
m_inputDelegate = new QtInputDelegate(m_activity, keyboardVisibilityListener);
try {
PackageManager pm = m_activity.getPackageManager();
ActivityInfo activityInfo = pm.getActivityInfo(m_activity.getComponentName(), 0);
m_inputDelegate.setSoftInputMode(activityInfo.softInputMode);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
setUpLayout();
}
public void hideSplashScreen()
{
hideSplashScreen(0);
}
@UsedFromNativeCode
public void notifyLocationChange(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyLocationChange(viewId);
}
@UsedFromNativeCode
public void notifyObjectHide(int viewId, int parentId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyObjectHide(viewId, parentId);
}
@UsedFromNativeCode
public void notifyObjectFocus(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyObjectFocus(viewId);
}
@UsedFromNativeCode
public void notifyValueChanged(int viewId, String value)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyValueChanged(viewId, value);
}
@UsedFromNativeCode
public void notifyScrolledEvent(int viewId)
{
if (m_accessibilityDelegate == null)
return;
m_accessibilityDelegate.notifyScrolledEvent(viewId);
}
@UsedFromNativeCode
public void initializeAccessibility()
{
QtNative.runAction(() -> {
m_accessibilityDelegate = createAccessibilityDelegate();
});
}
void handleUiModeChange(int uiMode)
{
// QTBUG-108365
if (Build.VERSION.SDK_INT >= 30) {
// Since 29 version we are using Theme_DeviceDefault_DayNight
Window window = m_activity.getWindow();
WindowInsetsController controller = window.getInsetsController();
if (controller != null) {
// set APPEARANCE_LIGHT_STATUS_BARS if needed
int appearanceLight = Color.luminance(window.getStatusBarColor()) > 0.5 ?
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS : 0;
controller.setSystemBarsAppearance(appearanceLight,
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
}
}
switch (uiMode) {
case Configuration.UI_MODE_NIGHT_NO:
ExtractStyle.runIfNeeded(m_activity, false);
QtDisplayManager.handleUiDarkModeChanged(0);
break;
case Configuration.UI_MODE_NIGHT_YES:
ExtractStyle.runIfNeeded(m_activity, true);
QtDisplayManager.handleUiDarkModeChanged(1);
break;
}
}
@UsedFromNativeCode
public void resetOptionsMenu()
{
QtNative.runAction(() -> m_activity.invalidateOptionsMenu());
}
@UsedFromNativeCode
public void openOptionsMenu()
{
QtNative.runAction(() -> m_activity.openOptionsMenu());
}
public void onCreatePopupMenu(Menu menu)
{
QtNative.fillContextMenu(menu);
m_contextMenuVisible = true;
}
@UsedFromNativeCode
public void closeContextMenu()
{
QtNative.runAction(() -> m_activity.closeContextMenu());
}
}

View File

@ -0,0 +1,121 @@
// 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 static org.qtproject.qt.android.QtNative.ApplicationState.*;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.HashMap;
class QtEmbeddedDelegate extends QtActivityDelegateBase implements QtNative.AppStateDetailsListener {
private QtNative.ApplicationStateDetails m_stateDetails;
public QtEmbeddedDelegate(Activity context) {
super(context);
m_stateDetails = QtNative.getStateDetails();
QtNative.registerAppStateListener(this);
m_activity.getApplication().registerActivityLifecycleCallbacks(
new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
@Override
public void onActivityStarted(Activity activity) {}
@Override
public void onActivityResumed(Activity activity) {
if (m_activity == activity && m_stateDetails.isStarted) {
QtNative.setApplicationState(ApplicationActive);
QtNative.updateWindow();
}
}
@Override
public void onActivityPaused(Activity activity) {
if (m_activity == activity && m_stateDetails.isStarted) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N ||
!activity.isInMultiWindowMode()) {
QtNative.setApplicationState(ApplicationInactive);
}
}
}
@Override
public void onActivityStopped(Activity activity) {
if (m_activity == activity && m_stateDetails.isStarted) {
QtNative.setApplicationState(ApplicationSuspended);
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
@Override
public void onActivityDestroyed(Activity activity) {
if (m_activity == activity && m_stateDetails.isStarted) {
m_activity.getApplication().unregisterActivityLifecycleCallbacks(this);
QtNative.unregisterAppStateListener(QtEmbeddedDelegate.this);
QtNative.terminateQt();
QtNative.setActivity(null);
QtNative.getQtThread().exit();
onDestroy();
}
}
});
}
@Override
public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) {
m_stateDetails = details;
if (m_stateDetails.nativePluginIntegrationReady) {
QtNative.runAction(() -> {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
QtDisplayManager.setApplicationDisplayMetrics(m_activity,
metrics.widthPixels,
metrics.heightPixels);
});
}
}
@Override
void startNativeApplicationImpl(String appParams, String mainLib)
{
QtNative.startApplication(appParams, mainLib);
}
@Override
QtAccessibilityDelegate createAccessibilityDelegate()
{
// FIXME make QtAccessibilityDelegate window based or verify current way works
// also for child windows: QTBUG-120685
return null;
}
@UsedFromNativeCode
@Override
QtLayout getQtLayout()
{
// TODO could probably use QtView here when it's added?
return null;
}
public void onDestroy() {
// TODO delete the window once it's added
}
}

View File

@ -53,7 +53,7 @@ static jobject m_resourcesObj = nullptr;
static jclass m_qtActivityClass = nullptr;
static jclass m_qtServiceClass = nullptr;
static QtJniTypes::QtActivityDelegate m_activityDelegate = nullptr;
static QtJniTypes::QtActivityDelegateBase m_activityDelegate = nullptr;
static QtJniTypes::QtInputDelegate m_inputDelegate = nullptr;
static int m_pendingApplicationState = -1;
@ -185,11 +185,11 @@ namespace QtAndroid
}
// FIXME: avoid direct access to QtActivityDelegate
QtJniTypes::QtActivityDelegate qtActivityDelegate()
QtJniTypes::QtActivityDelegateBase qtActivityDelegate()
{
if (!m_activityDelegate.isValid()) {
auto activity = QtAndroidPrivate::activity();
m_activityDelegate = activity.callMethod<QtJniTypes::QtActivityDelegate>(
m_activityDelegate = activity.callMethod<QtJniTypes::QtActivityDelegateBase>(
"getActivityDelegate");
}

View File

@ -26,7 +26,7 @@ class QWindow;
class QAndroidPlatformWindow;
class QBasicMutex;
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
Q_DECLARE_JNI_CLASS(QtActivityDelegateBase, "org/qtproject/qt/android/QtActivityDelegateBase")
Q_DECLARE_JNI_CLASS(QtInputDelegate, "org/qtproject/qt/android/QtInputDelegate")
namespace QtAndroid
@ -48,7 +48,7 @@ namespace QtAndroid
AAssetManager *assetManager();
jclass applicationClass();
QtJniTypes::QtActivityDelegate qtActivityDelegate();
QtJniTypes::QtActivityDelegateBase qtActivityDelegate();
QtJniTypes::QtInputDelegate qtInputDelegate();
// Keep synchronized with flags in ActivityDelegate.java

View File

@ -203,13 +203,13 @@ void tst_Android::testRunOnAndroidMainThread()
}
}
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
Q_DECLARE_JNI_CLASS(QtActivityDelegateBase, "org/qtproject/qt/android/QtActivityDelegateBase")
void setSystemUiVisibility(int visibility)
{
QNativeInterface::QAndroidApplication::runOnAndroidMainThread([visibility] {
auto context = QNativeInterface::QAndroidApplication::context();
auto activityDelegate = context.callMethod<QtJniTypes::QtActivityDelegate>("getActivityDelegate");
auto activityDelegate = context.callMethod<QtJniTypes::QtActivityDelegateBase>("getActivityDelegate");
activityDelegate.callMethod<void>("setSystemUiVisibility", jint(visibility));
}).waitForFinished();
}
@ -342,4 +342,3 @@ void tst_Android::orientationChange()
QTEST_MAIN(tst_Android)
#include "tst_android.moc"