Android: Add support for multiple embedded views in Android Service

To enable adding and managing multiple QtQuickViews,
QtServiceEmbeddedDelegate now hosts a set of QtViews instead of a
single one.

To avoid crashing if the QML view has a TextField, do not allow
QtWindow to create a QtEditText if the service usecase is detected.

Fixes: QTBUG-129412
Task-number: QTBUG-127422
Task-number: QTBUG-128563
Change-Id: I70784657ed6cb2aa853160605f4663e517f0e6db
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 1656a2f58c759c25e6a89435a65c1d0fceba8a09)
This commit is contained in:
Petri Virkkunen 2024-09-02 15:40:49 +03:00
parent 46dbb74249
commit 9cd561f355
2 changed files with 19 additions and 25 deletions

View File

@ -13,6 +13,8 @@ import android.view.Display;
import android.view.View;
import android.util.DisplayMetrics;
import java.util.HashSet;
/**
* QtServiceEmbeddedDelegate is used for embedding QML into Android Service contexts. Implements
* {@link QtEmbeddedViewInterface} so it can be used by QtView to communicate with the Qt layer.
@ -20,8 +22,7 @@ import android.util.DisplayMetrics;
class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.AppStateDetailsListener
{
private final Service m_service;
private QtView m_view;
private boolean m_windowLoaded = false;
private HashSet<QtView> m_views = new HashSet<QtView>();
QtServiceEmbeddedDelegate(Service service)
{
@ -38,17 +39,14 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
synchronized (this) {
if (ready) {
QtNative.runAction(() -> {
if (m_view == null)
return;
final DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
final int maxWidth = m_view.getWidth();
final int maxHeight = m_view.getHeight();
final int maxWidth = metrics.widthPixels;
final int maxHeight = metrics.heightPixels;
final int width = maxWidth;
final int height = maxHeight;
final int insetLeft = m_view.getLeft();
final int insetTop = m_view.getTop();
final int insetLeft = 0;
final int insetTop = 0;
final DisplayManager dm = m_service.getSystemService(DisplayManager.class);
QtDisplayManager.setDisplayMetrics(
@ -58,7 +56,6 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
QtDisplayManager.getRefreshRate(
dm.getDisplay(Display.DEFAULT_DISPLAY)));
});
createRootWindow();
}
}
}
@ -73,30 +70,25 @@ class QtServiceEmbeddedDelegate implements QtEmbeddedViewInterface, QtNative.App
@Override
public void addView(QtView view)
{
m_view = view;
QtNative.runAction(() -> {
createRootWindow();
});
if (m_views.add(view)) {
QtNative.runAction(() -> createRootWindow(view));
}
}
@Override
public void removeView(QtView view)
{
if (m_view == view) {
m_view = null;
m_windowLoaded = false;
// If the embedded view is destroyed, do cleanup:
m_views.remove(view);
if (m_views.isEmpty())
cleanup();
}
}
// QtEmbeddedViewInterface implementation end
private void createRootWindow()
private void createRootWindow(QtView view)
{
if (m_view != null && !m_windowLoaded) {
QtView.createRootWindow(m_view, m_view.getLeft(), m_view.getTop(), m_view.getWidth(),
m_view.getHeight());
m_windowLoaded = true;
if (m_views.contains(view)) {
QtView.createRootWindow(view, view.getLeft(), view.getTop(), view.getWidth(),
view.getHeight());
}
}

View File

@ -3,6 +3,7 @@
package org.qtproject.qt.android;
import android.app.Activity;
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
@ -42,7 +43,8 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
// to QAndroidPlatformWindow::setVisible().
setVisible(false);
if (!isForeignWindow) {
if (!isForeignWindow && context instanceof Activity) {
// TODO QTBUG-122552 - Service keyboard input not implemented
m_editText = new QtEditText(context, listener);
m_editText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
QtNative.runAction(() -> {