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 0ae4c2e731a..4b680c1e174 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java @@ -32,7 +32,7 @@ public class QtActivityBase extends Activity private boolean m_retainNonConfigurationInstance = false; private Configuration m_prevConfig; - private QtActivityDelegate m_delegate; + private final QtActivityDelegate m_delegate; public static final String EXTRA_SOURCE_INFO = "org.qtproject.qt.android.sourceInfo"; @@ -83,6 +83,11 @@ public class QtActivityBase extends Activity Runtime.getRuntime().exit(0); } + public QtActivityBase() + { + m_delegate = new QtActivityDelegate(this); + } + @Override protected void onCreate(Bundle savedInstanceState) { @@ -102,8 +107,6 @@ public class QtActivityBase extends Activity restartApplication(); } - m_delegate = new QtActivityDelegate(this); - QtNative.registerAppStateListener(m_delegate); addReferrer(getIntent()); 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 fae6a3fbac1..cca26fb31e3 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -48,7 +48,12 @@ class QtActivityDelegate extends QtActivityDelegateBase QtActivityDelegate(Activity activity) { super(activity); + } + @Override + void initMembers() + { + super.initMembers(); setActionBarVisibility(false); setActivityBackgroundDrawable(); } @@ -82,10 +87,15 @@ class QtActivityDelegate extends QtActivityDelegateBase @Override public void setSystemUiVisibility(int systemUiVisibility) { + if (m_layout == null) + return; + QtNative.runAction(() -> { - m_displayManager.setSystemUiVisibility(systemUiVisibility); - m_layout.requestLayout(); - QtNative.updateWindow(); + if (m_layout != null) { + m_displayManager.setSystemUiVisibility(systemUiVisibility); + m_layout.requestLayout(); + QtNative.updateWindow(); + } }); } @@ -101,12 +111,19 @@ class QtActivityDelegate extends QtActivityDelegateBase @Override void startNativeApplicationImpl(String appParams, String mainLib) { + if (m_layout == null) { + Log.e(QtTAG, "Unable to start native application with a null layout"); + return; + } + m_layout.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - QtNative.startApplication(appParams, mainLib); - m_layout.getViewTreeObserver().removeOnGlobalLayoutListener(this); + if (m_layout != null) { + QtNative.startApplication(appParams, mainLib); + m_layout.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } } }); } @@ -114,9 +131,11 @@ class QtActivityDelegate extends QtActivityDelegateBase @Override protected void setUpLayout() { - int orientation = m_activity.getResources().getConfiguration().orientation; + // This should be assigned only once, otherwise, we'd have to check + // for null everywhere including before and inside runAction() Runnables. m_layout = new QtRootLayout(m_activity); + int orientation = m_activity.getResources().getConfiguration().orientation; setUpSplashScreen(orientation); m_activity.registerForContextMenu(m_layout); m_activity.setContentView(m_layout, @@ -155,6 +174,11 @@ class QtActivityDelegate extends QtActivityDelegateBase @Override protected void setUpSplashScreen(int orientation) { + if (m_layout == null) { + Log.e(QtTAG, "Unable to setup splash screen with a null layout"); + return; + } + try { ActivityInfo info = m_activity.getPackageManager().getActivityInfo( m_activity.getComponentName(), @@ -192,7 +216,7 @@ class QtActivityDelegate extends QtActivityDelegateBase if (m_splashScreen == null) return; - if (duration <= 0) { + if (m_layout != null && duration <= 0) { m_layout.removeView(m_splashScreen); m_splashScreen = null; return; @@ -303,7 +327,16 @@ class QtActivityDelegate extends QtActivityDelegateBase @Override public void openContextMenu(final int x, final int y, final int w, final int h) { + if (m_layout == null) { + Log.e(QtTAG, "Unable to open context menu with a null layout"); + return; + } + m_layout.postDelayed(() -> { + if (m_layout == null) { + Log.w(QtTAG, "Unable to open context menu on null layout"); + return; + } final QtEditText focusedEditText = m_inputDelegate.getCurrentQtEditText(); if (focusedEditText == null) { Log.w(QtTAG, "No focused view when trying to open context menu"); @@ -350,10 +383,13 @@ class QtActivityDelegate extends QtActivityDelegateBase @Override public void addTopLevelWindow(final QtWindow window) { - if (window == null) + if (m_layout == null || window == null) return; QtNative.runAction(()-> { + if (m_layout == null) + return; + if (m_topLevelWindows.size() == 0) { if (m_dummyView != null) { m_layout.removeView(m_dummyView); @@ -379,7 +415,7 @@ class QtActivityDelegate extends QtActivityDelegateBase // Keep last frame in stack until it is replaced to get correct // shutdown transition m_dummyView = window; - } else { + } else if (m_layout != null) { m_layout.removeView(window); } } @@ -390,22 +426,26 @@ class QtActivityDelegate extends QtActivityDelegateBase @Override public void bringChildToFront(final int id) { - QtNative.runAction(() -> { - QtWindow window = m_topLevelWindows.get(id); - if (window != null) - m_layout.moveChild(window, m_topLevelWindows.size() - 1); - }); + if (m_layout != null) { + QtNative.runAction(() -> { + QtWindow window = m_topLevelWindows.get(id); + if (window != null && m_layout != null) + m_layout.moveChild(window, m_topLevelWindows.size() - 1); + }); + } } @UsedFromNativeCode @Override public void bringChildToBack(int id) { - QtNative.runAction(() -> { - QtWindow window = m_topLevelWindows.get(id); - if (window != null) - m_layout.moveChild(window, 0); - }); + if (m_layout != null) { + QtNative.runAction(() -> { + QtWindow window = m_topLevelWindows.get(id); + if (window != null && m_layout != null) + m_layout.moveChild(window, 0); + }); + } } private void setActivityBackgroundDrawable() @@ -429,6 +469,9 @@ class QtActivityDelegate extends QtActivityDelegateBase @UsedFromNativeCode void insertNativeView(int id, View view, int x, int y, int w, int h) { + if (m_layout == null) + return; + QtNative.runAction(()-> { if (m_dummyView != null) { m_layout.removeView(m_dummyView); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java index c99695e6dde..bd5568fb93f 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java @@ -31,14 +31,16 @@ import android.view.WindowInsetsController; import android.widget.ImageView; import android.widget.PopupMenu; +import org.qtproject.qt.android.QtInputDelegate.KeyboardVisibilityListener; + import java.util.HashMap; abstract class QtActivityDelegateBase { - protected Activity m_activity; - protected HashMap m_topLevelWindows; - protected QtDisplayManager m_displayManager = null; - protected QtInputDelegate m_inputDelegate = null; + protected final Activity m_activity; + protected final HashMap m_topLevelWindows = new HashMap<>(); + protected final QtDisplayManager m_displayManager; + protected final QtInputDelegate m_inputDelegate; private boolean m_membersInitialized = false; private boolean m_contextMenuVisible = false; @@ -55,8 +57,9 @@ abstract class QtActivityDelegateBase QtActivityDelegateBase(Activity activity) { m_activity = activity; - // Set native context QtNative.setActivity(m_activity); + m_displayManager = new QtDisplayManager(m_activity); + m_inputDelegate = new QtInputDelegate(m_displayManager::updateFullScreen); } QtDisplayManager displayManager() { @@ -88,14 +91,9 @@ abstract class QtActivityDelegateBase void initMembers() { m_membersInitialized = true; - m_topLevelWindows = new HashMap(); - - m_displayManager = new QtDisplayManager(m_activity); + m_topLevelWindows.clear(); m_displayManager.registerDisplayListener(); - - QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener = - () -> m_displayManager.updateFullScreen(); - m_inputDelegate = new QtInputDelegate(m_activity, keyboardVisibilityListener); + m_inputDelegate.initInputMethodManager(m_activity); try { PackageManager pm = m_activity.getPackageManager(); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java index e4de2434e22..6c8fbfd50bf 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java @@ -46,16 +46,12 @@ class QtDisplayManager { private static int m_previousRotation = -1; - private DisplayManager.DisplayListener m_displayListener = null; + private final DisplayManager.DisplayListener m_displayListener; private final Activity m_activity; QtDisplayManager(Activity activity) { m_activity = activity; - initDisplayListener(); - } - - private void initDisplayListener() { m_displayListener = new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) { 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 c1ebeeee47d..1fb25b5fe98 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java @@ -43,7 +43,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt // handle methods private QtEditText m_currentEditText = null; - private final InputMethodManager m_imm; + private InputMethodManager m_imm; private boolean m_keyboardIsVisible = false; private boolean m_isKeyboardHidingAnimationOngoing = false; @@ -72,9 +72,13 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt private final KeyboardVisibilityListener m_keyboardVisibilityListener; - QtInputDelegate(Activity activity, KeyboardVisibilityListener listener) + QtInputDelegate(KeyboardVisibilityListener listener) + { + m_keyboardVisibilityListener = listener; + } + + void initInputMethodManager(Activity activity) { - this.m_keyboardVisibilityListener = listener; m_imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); } @@ -84,10 +88,10 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt final int candidatesStart, final int candidatesEnd) { QtNative.runAction(() -> { - if (m_imm == null) - return; - - m_imm.updateSelection(m_currentEditText, selStart, selEnd, candidatesStart, candidatesEnd); + if (m_imm != null) { + m_imm.updateSelection(m_currentEditText, selStart, selEnd, + candidatesStart, candidatesEnd); + } }); } @@ -104,12 +108,11 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt return; m_currentEditText.setEditTextOptions(enterKeyType, inputHints); - m_currentEditText.setLayoutParams(new QtLayout.LayoutParams(width, height, x, y)); - m_currentEditText.requestFocus(); - m_currentEditText.postDelayed(() -> { + if (m_imm == null) + return; m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -269,7 +272,8 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt if (!visibility) { // Hiding the keyboard clears the immersive mode, so we need to set it again. m_keyboardVisibilityListener.onKeyboardVisibilityChange(); - m_currentEditText.clearFocus(); + if (m_currentEditText != null) + m_currentEditText.clearFocus(); } }