diff options
Diffstat (limited to 'src')
12 files changed, 539 insertions, 951 deletions
diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt index 31e09458d0..dd6a1dacba 100644 --- a/src/android/jar/CMakeLists.txt +++ b/src/android/jar/CMakeLists.txt @@ -8,7 +8,11 @@ set(java_sources src/org/qtproject/qt/android/EditContextView.java src/org/qtproject/qt/android/EditPopupMenu.java src/org/qtproject/qt/android/ExtractStyle.java + src/org/qtproject/qt/android/QtApplicationBase.java + 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/QtLoader.java src/org/qtproject/qt/android/QtActivityLoader.java src/org/qtproject/qt/android/QtServiceLoader.java @@ -20,7 +24,6 @@ set(java_sources src/org/qtproject/qt/android/QtNativeLibrariesDir.java src/org/qtproject/qt/android/QtSurface.java src/org/qtproject/qt/android/QtThread.java - src/org/qtproject/qt/android/QtServiceDelegate.java src/org/qtproject/qt/android/extras//QtAndroidBinder.java src/org/qtproject/qt/android/extras/QtAndroidServiceConnection.java src/org/qtproject/qt/android/extras/QtNative.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 new file mode 100644 index 0000000000..fe2eaf0b9d --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java @@ -0,0 +1,349 @@ +// 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.Activity; +import android.content.Intent; +import android.content.res.Configuration; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.provider.Browser; +import android.text.method.MetaKeyKeyListener; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; + +public class QtActivityBase extends Activity +{ + private long m_metaState; + public boolean m_backKeyPressedSent = false; + + private boolean m_optionsMenuIsVisible = false; + + // use this variable to pass any parameters to your application, + // the parameters must not contain any white spaces + // and must be separated with "\t" + // e.g "-param1\t-param2=value2\t-param3\tvalue3" + public String APPLICATION_PARAMETERS = null; + + // use this variable to add any environment variables to your application. + // the env vars must be separated with "\t" + // e.g. "ENV_VAR1=1\tENV_VAR2=2\t" + // Currently the following vars are used by the android plugin: + // * QT_USE_ANDROID_NATIVE_DIALOGS - 1 to use the android native dialogs. + public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1"; + + // A list with all themes that your application want to use. + // The name of the theme must be the same with any theme from + // http://developer.android.com/reference/android/R.style.html + // The most used themes are: + // * "Theme_Light" - (default for API <=10) check http://developer.android.com/reference/android/R.style.html#Theme_Light + // * "Theme_Holo" - check http://developer.android.com/reference/android/R.style.html#Theme_Holo + // * "Theme_Holo_Light" - (default for API 11-13) check http://developer.android.com/reference/android/R.style.html#Theme_Holo_Light + public String[] QT_ANDROID_THEMES = null; + + public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme. + + private final QtActivityLoader m_loader = new QtActivityLoader(this); + + private final QtActivityDelegate m_delegate = new QtActivityDelegate(); + + protected void onCreateHook(Bundle savedInstanceState) { + m_loader.APPLICATION_PARAMETERS = APPLICATION_PARAMETERS; + m_loader.ENVIRONMENT_VARIABLES = ENVIRONMENT_VARIABLES; + m_loader.QT_ANDROID_THEMES = QT_ANDROID_THEMES; + m_loader.QT_ANDROID_DEFAULT_THEME = QT_ANDROID_DEFAULT_THEME; + m_loader.onCreate(savedInstanceState); + } + + public static final String EXTRA_SOURCE_INFO = "org.qtproject.qt.android.sourceInfo"; + + private void addReferrer(Intent intent) + { + if (intent.getExtras() != null && intent.getExtras().getString(EXTRA_SOURCE_INFO) != null) + return; + + String browserApplicationId = ""; + if (intent.getExtras() != null) + browserApplicationId = intent.getExtras().getString(Browser.EXTRA_APPLICATION_ID); + + String sourceInformation = ""; + if (browserApplicationId != null && !browserApplicationId.isEmpty()) { + sourceInformation = browserApplicationId; + } else { + Uri referrer = getReferrer(); + if (referrer != null) + sourceInformation = referrer.toString().replaceFirst("android-app://", ""); + } + + intent.putExtra(EXTRA_SOURCE_INFO, sourceInformation); + } + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + onCreateHook(savedInstanceState); + addReferrer(getIntent()); + } + + @Override + protected void onStart() + { + super.onStart(); + } + + @Override + protected void onRestart() + { + super.onRestart(); + } + + @Override + protected void onPause() + { + super.onPause(); + if (Build.VERSION.SDK_INT < 24 || !isInMultiWindowMode()) + QtNative.setApplicationState(QtConstants.ApplicationState.ApplicationInactive); + } + + @Override + protected void onResume() + { + super.onResume(); + QtNative.setApplicationState(QtConstants.ApplicationState.ApplicationActive); + if (m_delegate.isStarted()) { + QtNative.updateWindow(); + m_delegate.updateFullScreen(); // Suspending the app clears the immersive mode, so we need to set it again. + } + } + + @Override + protected void onStop() + { + super.onStop(); + QtNative.setApplicationState(QtConstants.ApplicationState.ApplicationSuspended); + } + + @Override + protected void onDestroy() + { + super.onDestroy(); + if (m_delegate.isQuitApp()) { + QtNative.terminateQt(); + QtNative.setActivity(null, null); + QtNative.m_qtThread.exit(); + System.exit(0); + } + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) + { + if (m_delegate.isStarted() + && event.getAction() == KeyEvent.ACTION_MULTIPLE + && event.getCharacters() != null + && event.getCharacters().length() == 1 + && event.getKeyCode() == 0) { + QtNative.keyDown(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0); + QtNative.keyUp(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0); + } + + if (QtNative.dispatchKeyEvent(event)) + return true; + + return super.dispatchKeyEvent(event); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) + { + super.onConfigurationChanged(newConfig); + m_delegate.handleUiModeChange(newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK); + } + + @Override + public boolean onContextItemSelected(MenuItem item) + { + m_delegate.setContextMenuVisible(false); + return QtNative.onContextItemSelected(item.getItemId(), item.isChecked()); + } + + @Override + public void onContextMenuClosed(Menu menu) + { + if (!m_delegate.isContextMenuVisible()) + return; + m_delegate.setContextMenuVisible(false); + QtNative.onContextMenuClosed(menu); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) + { + menu.clearHeader(); + QtNative.onCreateContextMenu(menu); + m_delegate.setContextMenuVisible(true); + } + + private int m_lastChar = 0; + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + if (!m_delegate.isStarted() || !m_delegate.isPluginRunning()) + return false; + + m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event); + int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState) | event.getMetaState()); + int lc = c; + m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState); + + if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) { + c = c & KeyCharacterMap.COMBINING_ACCENT_MASK; + c = KeyEvent.getDeadChar(m_lastChar, c); + } + + if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP + || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN + || keyCode == KeyEvent.KEYCODE_MUTE) + && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) { + return false; + } + + m_lastChar = lc; + if (keyCode == KeyEvent.KEYCODE_BACK) { + m_backKeyPressedSent = !m_delegate.isKeyboardVisible(); + if (!m_backKeyPressedSent) + return true; + } + QtNative.keyDown(keyCode, c, event.getMetaState(), event.getRepeatCount() > 0); + + return true; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) + { + if (!m_delegate.isStarted() || !m_delegate.isPluginRunning()) + return false; + + if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP + || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN + || keyCode == KeyEvent.KEYCODE_MUTE) + && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) { + return false; + } + + if (keyCode == KeyEvent.KEYCODE_BACK && !m_backKeyPressedSent) { + m_delegate.hideSoftwareKeyboard(); + m_delegate.setKeyboardVisibility(false, System.nanoTime()); + return true; + } + + m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode, event); + QtNative.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState(), event.getRepeatCount() > 0); + return true; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + menu.clear(); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) + { + m_optionsMenuIsVisible = true; + boolean res = QtNative.onPrepareOptionsMenu(menu); + m_delegate.setActionBarVisibility(res && menu.size() > 0); + return res; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + return QtNative.onOptionsItemSelected(item.getItemId(), item.isChecked()); + } + + @Override + public void onOptionsMenuClosed(Menu menu) + { + m_optionsMenuIsVisible = false; + QtNative.onOptionsMenuClosed(menu); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) + { + super.onRestoreInstanceState(savedInstanceState); + m_delegate.setStarted(savedInstanceState.getBoolean("Started")); + // FIXME restore all surfaces + } + + @Override + public Object onRetainNonConfigurationInstance() + { + super.onRetainNonConfigurationInstance(); + m_delegate.setQuitApp(false); + return true; + + } + + @Override + protected void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + outState.putInt("SystemUiVisibility", m_delegate.systemUiVisibility()); + outState.putBoolean("Started", m_delegate.isStarted()); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) + { + super.onWindowFocusChanged(hasFocus); + if (hasFocus) + m_delegate.updateFullScreen(); + } + + @Override + public boolean dispatchGenericMotionEvent(MotionEvent ev) + { + if (m_delegate.isStarted() && QtNative.dispatchGenericMotionEvent(ev)) + return true; + + return super.dispatchGenericMotionEvent(ev); + } + + @Override + protected void onNewIntent(Intent intent) + { + QtNative.onNewIntent(intent); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + super.onActivityResult(requestCode, resultCode, data); + QtNative.onActivityResult(requestCode, resultCode, data); + } + + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) + { + QtNative.sendRequestPermissionsResult(requestCode, permissions, grantResults); + } + + 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 cc6aed569f..b180685af5 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -1,5 +1,5 @@ // Copyright (C) 2017 BogDan Vatra <bogdan@kde.org> -// Copyright (C) 2022 The Qt Company Ltd. +// 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 @@ -71,16 +71,6 @@ import static org.qtproject.qt.android.QtConstants.*; public class QtActivityDelegate { private Activity m_activity = null; - private Method m_super_dispatchKeyEvent = null; - private Method m_super_onRestoreInstanceState = null; - private Method m_super_onRetainNonConfigurationInstance = null; - private Method m_super_onSaveInstanceState = null; - private Method m_super_onKeyDown = null; - private Method m_super_onKeyUp = null; - private Method m_super_onConfigurationChanged = null; - private Method m_super_onActivityResult = null; - private Method m_super_dispatchGenericMotionEvent = null; - private Method m_super_onWindowFocusChanged = null; // Keep in sync with QtAndroid::SystemUiVisibility in androidjnimain.h public static final int SYSTEM_UI_VISIBILITY_NORMAL = 0; @@ -93,8 +83,6 @@ public class QtActivityDelegate private int m_nativeOrientation = Configuration.ORIENTATION_UNDEFINED; private String m_mainLib; - private long m_metaState; - private int m_lastChar = 0; private int m_softInputMode = 0; private int m_systemUiVisibility = SYSTEM_UI_VISIBILITY_NORMAL; private boolean m_started = false; @@ -108,7 +96,6 @@ public class QtActivityDelegate private boolean m_quitApp = true; private View m_dummyView = null; private boolean m_keyboardIsVisible = false; - public boolean m_backKeyPressedSent = false; private long m_showHideTimeStamp = System.nanoTime(); private int m_portraitKeyboardHeight = 0; private int m_landscapeKeyboardHeight = 0; @@ -122,6 +109,9 @@ public class QtActivityDelegate private QtAccessibilityDelegate m_accessibilityDelegate = null; + QtActivityDelegate() { } + + public void setSystemUiVisibility(int systemUiVisibility) { if (m_systemUiVisibility == systemUiVisibility) @@ -442,6 +432,46 @@ public class QtActivityDelegate }); } + void setStarted(boolean started) + { + m_started = started; + } + + boolean isStarted() + { + return m_started; + } + + void setQuitApp(boolean quitApp) + { + m_quitApp = quitApp; + } + + boolean isQuitApp() + { + return m_quitApp; + } + + boolean isPluginRunning() + { + return m_isPluginRunning; + } + + int systemUiVisibility() + { + return m_systemUiVisibility; + } + + void setContextMenuVisible(boolean contextMenuVisible) + { + m_contextMenuVisible = contextMenuVisible; + } + + boolean isContextMenuVisible() + { + return m_contextMenuVisible; + } + int getAppIconSize(Activity a) { int size = a.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size); @@ -625,28 +655,6 @@ public class QtActivityDelegate QtNative.setActivity(m_activity, this); setActionBarVisibility(false); - Class<?> activityClass = m_activity.getClass(); - m_super_dispatchKeyEvent = - activityClass.getMethod("super_dispatchKeyEvent", KeyEvent.class); - m_super_onRestoreInstanceState = - activityClass.getMethod("super_onRestoreInstanceState", Bundle.class); - m_super_onRetainNonConfigurationInstance = - activityClass.getMethod("super_onRetainNonConfigurationInstance"); - m_super_onSaveInstanceState = - activityClass.getMethod("super_onSaveInstanceState", Bundle.class); - m_super_onKeyDown = - activityClass.getMethod("super_onKeyDown", Integer.TYPE, KeyEvent.class); - m_super_onKeyUp = - activityClass.getMethod("super_onKeyUp", Integer.TYPE, KeyEvent.class); - m_super_onConfigurationChanged = - activityClass.getMethod("super_onConfigurationChanged", Configuration.class); - m_super_onActivityResult = - activityClass.getMethod("super_onActivityResult", Integer.TYPE, Integer.TYPE, Intent.class); - m_super_onWindowFocusChanged = - activityClass.getMethod("super_onWindowFocusChanged", Boolean.TYPE); - m_super_dispatchGenericMotionEvent = - activityClass.getMethod("super_dispatchGenericMotionEvent", MotionEvent.class); - m_softInputMode = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), 0).softInputMode; DisplayManager displayManager = (DisplayManager)m_activity.getSystemService(Context.DISPLAY_SERVICE); @@ -948,7 +956,6 @@ public class QtActivityDelegate m_accessibilityDelegate.notifyScrolledEvent(viewId); } - public void notifyQtAndroidPluginRunning(boolean running) { m_isPluginRunning = running; @@ -959,22 +966,12 @@ public class QtActivityDelegate m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity, m_layout, this); } - public void onWindowFocusChanged(boolean hasFocus) { - try { - m_super_onWindowFocusChanged.invoke(m_activity, hasFocus); - } catch (Exception e) { - e.printStackTrace(); - } - if (hasFocus) - updateFullScreen(); - } - boolean isUiModeDark(Configuration config) { return (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; } - private void handleUiModeChange(int uiMode) + void handleUiModeChange(int uiMode) { // QTBUG-108365 if (Build.VERSION.SDK_INT >= 30) { @@ -1001,215 +998,12 @@ public class QtActivityDelegate } } - public void onConfigurationChanged(Configuration configuration) - { - try { - m_super_onConfigurationChanged.invoke(m_activity, configuration); - } catch (Exception e) { - e.printStackTrace(); - } - handleUiModeChange(configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK); - } - - public void onDestroy() - { - if (m_quitApp) { - QtNative.terminateQt(); - QtNative.setActivity(null, null); - QtNative.m_qtThread.exit(); - System.exit(0); - } - } - - public void onPause() - { - if (Build.VERSION.SDK_INT < 24 || !m_activity.isInMultiWindowMode()) - QtNative.setApplicationState(ApplicationState.ApplicationInactive); - } - - public void onResume() - { - QtNative.setApplicationState(ApplicationState.ApplicationActive); - if (m_started) { - QtNative.updateWindow(); - updateFullScreen(); // Suspending the app clears the immersive mode, so we need to set it again. - } - } - - public void onNewIntent(Intent data) - { - QtNative.onNewIntent(data); - } - - public void onActivityResult(int requestCode, int resultCode, Intent data) - { - try { - m_super_onActivityResult.invoke(m_activity, requestCode, resultCode, data); - } catch (Exception e) { - e.printStackTrace(); - } - - QtNative.onActivityResult(requestCode, resultCode, data); - } - - - public void onStop() - { - QtNative.setApplicationState(ApplicationState.ApplicationSuspended); - } - - public Object onRetainNonConfigurationInstance() - { - try { - m_super_onRetainNonConfigurationInstance.invoke(m_activity); - } catch (Exception e) { - e.printStackTrace(); - } - m_quitApp = false; - return true; - } - - public void onSaveInstanceState(Bundle outState) { - try { - m_super_onSaveInstanceState.invoke(m_activity, outState); - } catch (Exception e) { - e.printStackTrace(); - } - outState.putInt("SystemUiVisibility", m_systemUiVisibility); - outState.putBoolean("Started", m_started); - // It should never - } - - public void onRestoreInstanceState(Bundle savedInstanceState) - { - try { - m_super_onRestoreInstanceState.invoke(m_activity, savedInstanceState); - } catch (Exception e) { - e.printStackTrace(); - } - m_started = savedInstanceState.getBoolean("Started"); - // FIXME restore all surfaces - - } - - public boolean onKeyDown(int keyCode, KeyEvent event) - { - if (!m_started || !m_isPluginRunning) - return false; - - m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event); - int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState) | event.getMetaState()); - int lc = c; - m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState); - - if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) { - c = c & KeyCharacterMap.COMBINING_ACCENT_MASK; - int composed = KeyEvent.getDeadChar(m_lastChar, c); - c = composed; - } - - if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP - || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN - || keyCode == KeyEvent.KEYCODE_MUTE) - && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) { - return false; - } - - m_lastChar = lc; - if (keyCode == KeyEvent.KEYCODE_BACK) { - m_backKeyPressedSent = !m_keyboardIsVisible; - if (!m_backKeyPressedSent) - return true; - } - QtNative.keyDown(keyCode, c, event.getMetaState(), event.getRepeatCount() > 0); - - return true; - } - - public boolean onKeyUp(int keyCode, KeyEvent event) - { - if (!m_started || !m_isPluginRunning) - return false; - - if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP - || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN - || keyCode == KeyEvent.KEYCODE_MUTE) - && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) { - return false; - } - - if (keyCode == KeyEvent.KEYCODE_BACK && !m_backKeyPressedSent) { - hideSoftwareKeyboard(); - setKeyboardVisibility(false, System.nanoTime()); - return true; - } - - m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode, event); - QtNative.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState(), event.getRepeatCount() > 0); - return true; - } - - public boolean dispatchKeyEvent(KeyEvent event) - { - if (m_started - && event.getAction() == KeyEvent.ACTION_MULTIPLE - && event.getCharacters() != null - && event.getCharacters().length() == 1 - && event.getKeyCode() == 0) { - QtNative.keyDown(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0); - QtNative.keyUp(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0); - } - - if (QtNative.dispatchKeyEvent(event)) - return true; - - try { - return (Boolean) m_super_dispatchKeyEvent.invoke(m_activity, event); - } catch (Exception e) { - e.printStackTrace(); - } - return false; - } - - private boolean m_optionsMenuIsVisible = false; - public boolean onCreateOptionsMenu(Menu menu) - { - menu.clear(); - return true; - } - public boolean onPrepareOptionsMenu(Menu menu) - { - m_optionsMenuIsVisible = true; - boolean res = QtNative.onPrepareOptionsMenu(menu); - setActionBarVisibility(res && menu.size() > 0); - return res; - } - - public boolean onOptionsItemSelected(MenuItem item) - { - return QtNative.onOptionsItemSelected(item.getItemId(), item.isChecked()); - } - - public void onOptionsMenuClosed(Menu menu) - { - m_optionsMenuIsVisible = false; - QtNative.onOptionsMenuClosed(menu); - } - public void resetOptionsMenu() { m_activity.invalidateOptionsMenu(); } private boolean m_contextMenuVisible = false; - public void onCreateContextMenu(ContextMenu menu, - View v, - ContextMenuInfo menuInfo) - { - menu.clearHeader(); - QtNative.onCreateContextMenu(menu); - m_contextMenuVisible = true; - } public void onCreatePopupMenu(Menu menu) { @@ -1217,20 +1011,6 @@ public class QtActivityDelegate m_contextMenuVisible = true; } - public void onContextMenuClosed(Menu menu) - { - if (!m_contextMenuVisible) - return; - m_contextMenuVisible = false; - QtNative.onContextMenuClosed(menu); - } - - public boolean onContextItemSelected(MenuItem item) - { - m_contextMenuVisible = false; - return QtNative.onContextItemSelected(item.getItemId(), item.isChecked()); - } - public void openContextMenu(final int x, final int y, final int w, final int h) { m_layout.postDelayed(new Runnable() { @@ -1242,13 +1022,13 @@ public class QtActivityDelegate popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { - return QtActivityDelegate.this.onContextItemSelected(menuItem); + return m_activity.onContextItemSelected(menuItem); } }); popup.setOnDismissListener(new PopupMenu.OnDismissListener() { @Override public void onDismiss(PopupMenu popupMenu) { - QtActivityDelegate.this.onContextMenuClosed(popupMenu.getMenu()); + m_activity.onContextMenuClosed(popupMenu.getMenu()); } }); popup.show(); @@ -1261,7 +1041,7 @@ public class QtActivityDelegate m_activity.closeContextMenu(); } - private void setActionBarVisibility(boolean visible) + void setActionBarVisibility(boolean visible) { if (m_activity.getActionBar() == null) return; @@ -1398,22 +1178,4 @@ public class QtActivityDelegate m_layout.moveChild(view, index); } } - - public boolean dispatchGenericMotionEvent (MotionEvent ev) - { - if (m_started && QtNative.dispatchGenericMotionEvent(ev)) - return true; - - try { - return (Boolean) m_super_dispatchGenericMotionEvent.invoke(m_activity, ev); - } catch (Exception e) { - e.printStackTrace(); - } - return false; - } - - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) - { - QtNative.sendRequestPermissionsResult(requestCode, permissions, grantResults); - } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java index 1c8cc99950..d9cfa2f79d 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityLoader.java @@ -16,23 +16,13 @@ import java.lang.reflect.Field; public class QtActivityLoader extends QtLoader { Activity m_activity; - public QtActivityLoader(Activity activity, Class<?> clazz) + public QtActivityLoader(Activity activity) { - super(activity, clazz); + super(activity); m_activity = activity; } @Override - protected String loaderClassName() { - return "org.qtproject.qt.android.QtActivityDelegate"; - } - - @Override - protected Class<?> contextClassName() { - return android.app.Activity.class; - } - - @Override protected void finish() { m_activity.finish(); } @@ -88,9 +78,7 @@ public class QtActivityLoader extends QtLoader { Runtime.getRuntime().exit(0); } - // there can only be a valid delegate object if the QtNative was started. - if (m_delegateObject != null && onCreate != null) - invokeDelegateMethod(onCreate, savedInstanceState); + ((QtActivityBase)m_activity).getActivityDelegate().onCreate(savedInstanceState); return; } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtApplicationBase.java b/src/android/jar/src/org/qtproject/qt/android/QtApplicationBase.java new file mode 100644 index 0000000000..5ecb1597fe --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt/android/QtApplicationBase.java @@ -0,0 +1,17 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +package org.qtproject.qt.android; + +import android.app.Application; + +public class QtApplicationBase extends Application { + public final static String QtTAG = "Qt"; + + @Override + public void onTerminate() { + QtNative.terminateQt(); + QtNative.m_qtThread.exit(); + super.onTerminate(); + } +} diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtLoader.java index 168ce15ea3..74cc2e29c8 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtLoader.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtLoader.java @@ -36,71 +36,18 @@ public abstract class QtLoader { // These parameters matter in case of deploying application as system (embedded into firmware) public static final String SYSTEM_LIB_PATH = "/system/lib/"; - public String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application, - // the parameters must not contain any white spaces - // and must be separated with "\t" - // e.g "-param1\t-param2=value2\t-param3\tvalue3" - + public String APPLICATION_PARAMETERS = null; public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1"; - // use this variable to add any environment variables to your application. - // the env vars must be separated with "\t" - // e.g. "ENV_VAR1=1\tENV_VAR2=2\t" - // Currently the following vars are used by the android plugin: - // * QT_USE_ANDROID_NATIVE_DIALOGS -1 to use the android native dialogs. - - public String[] QT_ANDROID_THEMES = null; // A list with all themes that your application want to use. - // The name of the theme must be the same with any theme from - // http://developer.android.com/reference/android/R.style.html - // The most used themes are: - // * "Theme" - (fallback) check http://developer.android.com/reference/android/R.style.html#Theme - // * "Theme_Black" - check http://developer.android.com/reference/android/R.style.html#Theme_Black - // * "Theme_Light" - (default for API <=10) check http://developer.android.com/reference/android/R.style.html#Theme_Light - // * "Theme_Holo" - check http://developer.android.com/reference/android/R.style.html#Theme_Holo - // * "Theme_Holo_Light" - (default for API 11-13) check http://developer.android.com/reference/android/R.style.html#Theme_Holo_Light - // * "Theme_DeviceDefault" - check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault - // * "Theme_DeviceDefault_Light" - (default for API 14+) check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault_Light - + public String[] QT_ANDROID_THEMES = null; public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme. public ArrayList<String> m_qtLibs = null; // required qt libs public int m_displayDensity = -1; private ContextWrapper m_context; protected ComponentInfo m_contextInfo; - private Class<?> m_delegateClass; - - private static ArrayList<FileOutputStream> m_fileOutputStreams = new ArrayList<FileOutputStream>(); - // List of open file streams associated with files copied during installation. - - public static Object m_delegateObject = null; - public static HashMap<String, ArrayList<Method>> m_delegateMethods= new HashMap<String, ArrayList<Method>>(); - public static Method dispatchKeyEvent = null; - public static Method dispatchPopulateAccessibilityEvent = null; - public static Method dispatchTouchEvent = null; - public static Method dispatchTrackballEvent = null; - public static Method onKeyDown = null; - public static Method onKeyMultiple = null; - public static Method onKeyUp = null; - public static Method onTouchEvent = null; - public static Method onTrackballEvent = null; - public static Method onActivityResult = null; - public static Method onCreate = null; - public static Method onKeyLongPress = null; - public static Method dispatchKeyShortcutEvent = null; - public static Method onKeyShortcut = null; - public static Method dispatchGenericMotionEvent = null; - public static Method onGenericMotionEvent = null; - public static Method onRequestPermissionsResult = null; - private static String activityClassName; - private static Class qtApplicationClass = null; - - public QtLoader(ContextWrapper context, Class<?> clazz) { - m_context = context; - m_delegateClass = clazz; - } - public static void setQtApplicationClass(Class qtAppClass) - { - qtApplicationClass = qtAppClass; + public QtLoader(ContextWrapper context) { + m_context = context; } public static void setQtTAG(String tag) @@ -108,93 +55,6 @@ public abstract class QtLoader { QtTAG = tag; } - public static void setQtContextDelegate(Class<?> clazz, Object listener) - { - m_delegateObject = listener; - activityClassName = clazz.getCanonicalName(); - - ArrayList<Method> delegateMethods = new ArrayList<Method>(); - for (Method m : listener.getClass().getMethods()) { - if (m.getDeclaringClass().getName().startsWith("org.qtproject.qt.android")) - delegateMethods.add(m); - } - - ArrayList<Field> applicationFields = new ArrayList<Field>(); - for (Field f : qtApplicationClass.getFields()) { - if (f.getDeclaringClass().getName().equals(qtApplicationClass.getName())) - applicationFields.add(f); - } - - for (Method delegateMethod : delegateMethods) { - try { - clazz.getDeclaredMethod(delegateMethod.getName(), delegateMethod.getParameterTypes()); - if (m_delegateMethods.containsKey(delegateMethod.getName())) { - m_delegateMethods.get(delegateMethod.getName()).add(delegateMethod); - } else { - ArrayList<Method> delegateSet = new ArrayList<Method>(); - delegateSet.add(delegateMethod); - m_delegateMethods.put(delegateMethod.getName(), delegateSet); - } - for (Field applicationField:applicationFields) { - if (applicationField.getName().equals(delegateMethod.getName())) { - try { - applicationField.set(null, delegateMethod); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } catch (Exception e) { } - } - } - - public static class InvokeResult - { - public boolean invoked = false; - public Object methodReturns = null; - } - - private static int stackDeep=-1; - public static InvokeResult invokeDelegate(Object... args) - { - InvokeResult result = new InvokeResult(); - if (m_delegateObject == null) - return result; - StackTraceElement[] elements = Thread.currentThread().getStackTrace(); - if (-1 == stackDeep) { - for (int it=0;it<elements.length;it++) - if (elements[it].getClassName().equals(activityClassName)) { - stackDeep = it; - break; - } - } - if (-1 == stackDeep) - return result; - - final String methodName=elements[stackDeep].getMethodName(); - if (!m_delegateMethods.containsKey(methodName)) - return result; - - for (Method m : m_delegateMethods.get(methodName)) { - if (m.getParameterTypes().length == args.length) { - result.methodReturns = invokeDelegateMethod(m, args); - result.invoked = true; - return result; - } - } - return result; - } - - public static Object invokeDelegateMethod(Method m, Object... args) - { - try { - return m.invoke(m_delegateObject, args); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - // Implement in subclass protected void finish() {} @@ -206,9 +66,6 @@ public abstract class QtLoader { run.run(); } - protected abstract String loaderClassName(); - protected abstract Class<?> contextClassName(); - Intent getIntent() { return null; @@ -288,21 +145,21 @@ public abstract class QtLoader { loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists) m_context.getClassLoader()); // parent loader - Class<?> loaderClass = classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class - Object qtLoader = loaderClass.newInstance(); // create an instance - Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication", - contextClassName(), - ClassLoader.class, - Bundle.class); - if (!(Boolean)prepareAppMethod.invoke(qtLoader, m_context, classLoader, loaderParams)) - throw new Exception(""); - - setQtContextDelegate(m_delegateClass, qtLoader); - - Method startAppMethod=qtLoader.getClass().getMethod("startApplication"); - if (!(Boolean)startAppMethod.invoke(qtLoader)) - throw new Exception(""); - + if (m_context instanceof QtActivityBase) { + QtActivityBase activityBase = (QtActivityBase)m_context; + QtActivityDelegate activityDelegate = activityBase.getActivityDelegate(); + if (!activityDelegate.loadApplication(activityBase, classLoader, loaderParams)) + throw new Exception(""); + if (!activityDelegate.startApplication()) + throw new Exception(""); + } else if (m_context instanceof QtServiceBase) { + QtServiceBase serviceBase = (QtServiceBase)m_context; + QtServiceDelegate serviceDelegate = serviceBase.getServiceDelegate(); + if (!serviceDelegate.loadApplication(serviceBase, classLoader, loaderParams)) + throw new Exception(""); + if (!serviceDelegate.startApplication()) + throw new Exception(""); + } } catch (Exception e) { e.printStackTrace(); AlertDialog errorDialog = new AlertDialog.Builder(m_context).create(); @@ -412,7 +269,6 @@ public abstract class QtLoader { Bundle loaderParams = new Bundle(); loaderParams.putInt(ERROR_CODE_KEY, 0); loaderParams.putString(DEX_PATH_KEY, new String()); - loaderParams.putString(LOADER_CLASS_NAME_KEY, loaderClassName()); id = resources.getIdentifier("static_init_classes", "string", packageName); loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY, resources.getString(id) diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java new file mode 100644 index 0000000000..f35db6436a --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceBase.java @@ -0,0 +1,58 @@ +// 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; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; + +public class QtServiceBase extends Service { + + private final QtServiceDelegate m_delegate = new QtServiceDelegate(this); + QtServiceLoader m_loader = new QtServiceLoader(this); + protected void onCreateHook() { + // the application has already started + // do not reload everything again + if (QtNative.isStarted()) { + m_loader = null; + Log.w(QtNative.QtTAG, + "A QtService tried to start in the same process as an initiated " + + "QtActivity. That is not supported. This results in the service " + + "functioning as an Android Service detached from Qt."); + } else { + m_loader.onCreate(); + } + } + + @Override + public void onCreate() + { + super.onCreate(); + onCreateHook(); + } + + @Override + public void onDestroy() + { + super.onDestroy(); + QtNative.quitQtCoreApplication(); + QtNative.terminateQt(); + QtNative.setService(null, null); + QtNative.m_qtThread.exit(); + System.exit(0); + } + + @Override + public IBinder onBind(Intent intent) { + synchronized (this) { + 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 index 0670f66756..1b6a8c9a8c 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java @@ -1,5 +1,5 @@ // Copyright (C) 2016 BogDan Vatra <bogdan@kde.org> -// Copyright (C) 2016 The Qt Company Ltd. +// 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; @@ -58,6 +58,11 @@ public class QtServiceDelegate private Service m_service = null; private static String m_applicationParameters = null; + QtServiceDelegate(Service service) + { + m_service = service; + } + public boolean loadApplication(Service service, ClassLoader classLoader, Bundle loaderParams) { /// check parameters integrity @@ -136,20 +141,4 @@ public class QtServiceDelegate return false; } } - - public void onDestroy() - { - QtNative.quitQtCoreApplication(); - QtNative.terminateQt(); - QtNative.setService(null, null); - QtNative.m_qtThread.exit(); - System.exit(0); - } - - public IBinder onBind(Intent intent) - { - synchronized (this) { - return QtNative.onBind(intent); - } - } } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java index d5f7167b7a..f6add928e1 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceLoader.java @@ -14,8 +14,8 @@ import java.security.Provider; public class QtServiceLoader extends QtLoader { Service m_service; - public QtServiceLoader(Service service, Class<?> clazz) { - super(service, clazz); + public QtServiceLoader(Service service) { + super(service); m_service = service; } @@ -29,10 +29,6 @@ public class QtServiceLoader extends QtLoader { return; } - if (m_delegateObject != null && onCreate != null) { - Bundle bundle = null; - invokeDelegateMethod(onCreate, bundle); - } startApp(true); } @@ -40,14 +36,4 @@ public class QtServiceLoader extends QtLoader { protected void finish() { m_service.stopSelf(); } - - @Override - protected String loaderClassName() { - return "org.qtproject.qt.android.QtServiceDelegate"; - } - - @Override - protected Class<?> contextClassName() { - return android.app.Service.class; - } } diff --git a/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java index 438fd403a6..9fa8d3ffae 100644 --- a/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java @@ -4,11 +4,6 @@ package org.qtproject.qt.android.bindings; -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.provider.Browser; import android.view.ContextMenu; @@ -18,373 +13,48 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.os.Build; -import org.qtproject.qt.android.QtActivityLoader; -import org.qtproject.qt.android.QtLoader; +import org.qtproject.qt.android.QtActivityBase; -public class QtActivity extends Activity +public class QtActivity extends QtActivityBase { - public static final String EXTRA_SOURCE_INFO = "org.qtproject.qt.android.sourceInfo"; - - public String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application, - // the parameters must not contain any white spaces - // and must be separated with "\t" - // e.g "-param1\t-param2=value2\t-param3\tvalue3" - - public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1"; - // use this variable to add any environment variables to your application. - // the env vars must be separated with "\t" - // e.g. "ENV_VAR1=1\tENV_VAR2=2\t" - // Currently the following vars are used by the android plugin: - // * QT_USE_ANDROID_NATIVE_DIALOGS - 1 to use the android native dialogs. - - public String[] QT_ANDROID_THEMES = null; // A list with all themes that your application want to use. - // The name of the theme must be the same with any theme from - // http://developer.android.com/reference/android/R.style.html - // The most used themes are: - // * "Theme" - (fallback) check http://developer.android.com/reference/android/R.style.html#Theme - // * "Theme_Black" - check http://developer.android.com/reference/android/R.style.html#Theme_Black - // * "Theme_Light" - (default for API <=10) check http://developer.android.com/reference/android/R.style.html#Theme_Light - // * "Theme_Holo" - check http://developer.android.com/reference/android/R.style.html#Theme_Holo - // * "Theme_Holo_Light" - (default for API 11-13) check http://developer.android.com/reference/android/R.style.html#Theme_Holo_Light - // * "Theme_DeviceDefault" - check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault - // * "Theme_DeviceDefault_Light" - (default for API 14+) check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault_Light - - public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme. - - private QtActivityLoader m_loader; - public QtActivity() - { - m_loader = new QtActivityLoader(this, QtActivity.class); - - if (Build.VERSION.SDK_INT < 29) { - QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"}; - QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light"; - } else { - QT_ANDROID_THEMES = new String[] {"Theme_DeviceDefault_DayNight"}; - QT_ANDROID_DEFAULT_THEME = "Theme_DeviceDefault_DayNight"; - } - } - - - /////////////////////////// forward all notifications //////////////////////////// - /////////////////////////// Super class calls //////////////////////////////////// - /////////////// PLEASE DO NOT CHANGE THE FOLLOWING CODE ////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - protected void onCreateHook(Bundle savedInstanceState) { - m_loader.APPLICATION_PARAMETERS = APPLICATION_PARAMETERS; - m_loader.ENVIRONMENT_VARIABLES = ENVIRONMENT_VARIABLES; - m_loader.QT_ANDROID_THEMES = QT_ANDROID_THEMES; - m_loader.QT_ANDROID_DEFAULT_THEME = QT_ANDROID_DEFAULT_THEME; - m_loader.onCreate(savedInstanceState); - } - - private void addReferrer(Intent intent) - { - if (intent.getExtras() != null && intent.getExtras().getString(EXTRA_SOURCE_INFO) != null) - return; - - String browserApplicationId = ""; - if (intent.getExtras() != null) - browserApplicationId = intent.getExtras().getString(Browser.EXTRA_APPLICATION_ID); - - String sourceInformation = ""; - if (browserApplicationId != null && !browserApplicationId.isEmpty()) { - sourceInformation = browserApplicationId; - } else { - Uri referrer = getReferrer(); - if (referrer != null) - sourceInformation = referrer.toString().replaceFirst("android-app://", ""); - } - - intent.putExtra(EXTRA_SOURCE_INFO, sourceInformation); - } - @Override public void onCreate(Bundle savedInstanceState) { + setAppDetails(); super.onCreate(savedInstanceState); - QtLoader.setQtApplicationClass(QtApplication.class); - onCreateHook(savedInstanceState); - addReferrer(getIntent()); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) - { - if (QtLoader.m_delegateObject != null && QtLoader.dispatchKeyEvent != null) - return (Boolean) QtLoader.invokeDelegateMethod(QtLoader.dispatchKeyEvent, event); - else - return super.dispatchKeyEvent(event); - } - public boolean super_dispatchKeyEvent(KeyEvent event) - { - return super.dispatchKeyEvent(event); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) - { - - if (QtLoader.m_delegateObject != null && QtLoader.onActivityResult != null) { - QtLoader.invokeDelegateMethod(QtLoader.onActivityResult, requestCode, resultCode, data); - return; - } - super.onActivityResult(requestCode, resultCode, data); - } - public void super_onActivityResult(int requestCode, int resultCode, Intent data) - { - super.onActivityResult(requestCode, resultCode, data); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) - { - if (!QtLoader.invokeDelegate(newConfig).invoked) - super.onConfigurationChanged(newConfig); - } - public void super_onConfigurationChanged(Configuration newConfig) - { - super.onConfigurationChanged(newConfig); - } - - @Override - public boolean onContextItemSelected(MenuItem item) - { - QtLoader.InvokeResult res = QtLoader.invokeDelegate(item); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onContextItemSelected(item); - } - public boolean super_onContextItemSelected(MenuItem item) - { - return super.onContextItemSelected(item); - } - - @Override - public void onContextMenuClosed(Menu menu) - { - if (!QtLoader.invokeDelegate(menu).invoked) - super.onContextMenuClosed(menu); - } - public void super_onContextMenuClosed(Menu menu) - { - super.onContextMenuClosed(menu); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) - { - if (!QtLoader.invokeDelegate(menu, v, menuInfo).invoked) - super.onCreateContextMenu(menu, v, menuInfo); - } - public void super_onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) - { - super.onCreateContextMenu(menu, v, menuInfo); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) - { - QtLoader.InvokeResult res = QtLoader.invokeDelegate(menu); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onCreateOptionsMenu(menu); - } - public boolean super_onCreateOptionsMenu(Menu menu) - { - return super.onCreateOptionsMenu(menu); - } - - @Override - protected void onDestroy() - { - super.onDestroy(); - QtLoader.invokeDelegate(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) - { - if (QtLoader.m_delegateObject != null && QtLoader.onKeyDown != null) - return (Boolean) QtLoader.invokeDelegateMethod(QtLoader.onKeyDown, keyCode, event); - else - return super.onKeyDown(keyCode, event); - } - public boolean super_onKeyDown(int keyCode, KeyEvent event) - { - return super.onKeyDown(keyCode, event); } - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) - { - if (QtLoader.m_delegateObject != null && QtLoader.onKeyUp != null) - return (Boolean) QtLoader.invokeDelegateMethod(QtLoader.onKeyUp, keyCode, event); - else - return super.onKeyUp(keyCode, event); - } - public boolean super_onKeyUp(int keyCode, KeyEvent event) - { - return super.onKeyUp(keyCode, event); - } - - @Override - protected void onNewIntent(Intent intent) - { - addReferrer(intent); - if (!QtLoader.invokeDelegate(intent).invoked) - super.onNewIntent(intent); - } - public void super_onNewIntent(Intent intent) - { - super.onNewIntent(intent); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) - { - QtLoader.InvokeResult res = QtLoader.invokeDelegate(item); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onOptionsItemSelected(item); - } - public boolean super_onOptionsItemSelected(MenuItem item) - { - return super.onOptionsItemSelected(item); - } - - @Override - public void onOptionsMenuClosed(Menu menu) - { - if (!QtLoader.invokeDelegate(menu).invoked) - super.onOptionsMenuClosed(menu); - } - public void super_onOptionsMenuClosed(Menu menu) - { - super.onOptionsMenuClosed(menu); - } - - @Override - protected void onPause() - { - super.onPause(); - QtLoader.invokeDelegate(); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) - { - QtLoader.InvokeResult res = QtLoader.invokeDelegate(menu); - if (res.invoked) - return (Boolean)res.methodReturns; - else - return super.onPrepareOptionsMenu(menu); - } - public boolean super_onPrepareOptionsMenu(Menu menu) - { - return super.onPrepareOptionsMenu(menu); - } - - @Override - protected void onRestart() - { - super.onRestart(); - QtLoader.invokeDelegate(); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) - { - if (!QtLoader.invokeDelegate(savedInstanceState).invoked) - super.onRestoreInstanceState(savedInstanceState); - } - public void super_onRestoreInstanceState(Bundle savedInstanceState) - { - super.onRestoreInstanceState(savedInstanceState); - } - - @Override - protected void onResume() - { - super.onResume(); - QtLoader.invokeDelegate(); - } - - @Override - public Object onRetainNonConfigurationInstance() - { - QtLoader.InvokeResult res = QtLoader.invokeDelegate(); - if (res.invoked) - return res.methodReturns; - else - return super.onRetainNonConfigurationInstance(); - } - public Object super_onRetainNonConfigurationInstance() - { - return super.onRetainNonConfigurationInstance(); - } - - @Override - protected void onSaveInstanceState(Bundle outState) - { - if (!QtLoader.invokeDelegate(outState).invoked) - super.onSaveInstanceState(outState); - } - public void super_onSaveInstanceState(Bundle outState) - { - super.onSaveInstanceState(outState); - - } - - @Override - protected void onStart() - { - super.onStart(); - QtLoader.invokeDelegate(); - } - - @Override - protected void onStop() + private void setAppDetails() { - super.onStop(); - QtLoader.invokeDelegate(); - } + // use this variable to pass any parameters to your application, + // the parameters must not contain any white spaces + // and must be separated with "\t" + // e.g "-param1\t-param2=value2\t-param3\tvalue3" + APPLICATION_PARAMETERS = ""; - @Override - public void onWindowFocusChanged(boolean hasFocus) - { - if (!QtLoader.invokeDelegate(hasFocus).invoked) - super.onWindowFocusChanged(hasFocus); - } - public void super_onWindowFocusChanged(boolean hasFocus) - { - super.onWindowFocusChanged(hasFocus); - } + // Use this variable to add any environment variables to your application. + // the env vars must be separated with "\t" + // e.g. "ENV_VAR1=1\tENV_VAR2=2\t" + // Currently the following vars are used by the android plugin: + // * QT_USE_ANDROID_NATIVE_DIALOGS - 1 to use the android native dialogs. + ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1"; - @Override - public boolean dispatchGenericMotionEvent(MotionEvent ev) - { - if (QtLoader.m_delegateObject != null && QtLoader.dispatchGenericMotionEvent != null) - return (Boolean) QtLoader.invokeDelegateMethod(QtLoader.dispatchGenericMotionEvent, ev); - else - return super.dispatchGenericMotionEvent(ev); - } - public boolean super_dispatchGenericMotionEvent(MotionEvent event) - { - return super.dispatchGenericMotionEvent(event); - } + // A list with all themes that your application want to use. + // The name of the theme must be the same with any theme from + // http://developer.android.com/reference/android/R.style.html + // The most used themes are: + // * "Theme_Light" + // * "Theme_Holo" + // * "Theme_Holo_Light" - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) - { - if (QtLoader.m_delegateObject != null && QtLoader.onRequestPermissionsResult != null) { - QtLoader.invokeDelegateMethod(QtLoader.onRequestPermissionsResult, requestCode , - permissions, grantResults); + if (Build.VERSION.SDK_INT < 29) { + QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"}; + QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light"; + } else { + QT_ANDROID_THEMES = new String[] {"Theme_DeviceDefault_DayNight"}; + QT_ANDROID_DEFAULT_THEME = "Theme_DeviceDefault_DayNight"; } } - //--------------------------------------------------------------------------- } diff --git a/src/android/java/src/org/qtproject/qt/android/bindings/QtApplication.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtApplication.java index b89946b9a5..d1330565c1 100644 --- a/src/android/java/src/org/qtproject/qt/android/bindings/QtApplication.java +++ b/src/android/java/src/org/qtproject/qt/android/bindings/QtApplication.java @@ -4,30 +4,12 @@ package org.qtproject.qt.android.bindings; -import android.app.Application; -import org.qtproject.qt.android.QtLoader; +import org.qtproject.qt.android.QtApplicationBase; -public class QtApplication extends Application +public class QtApplication extends QtApplicationBase { - public final static String QtTAG = "Qt"; - @Override public void onTerminate() { - if (QtLoader.m_delegateObject != null && QtLoader.m_delegateMethods.containsKey("onTerminate")) - QtLoader.invokeDelegateMethod(QtLoader.m_delegateMethods.get("onTerminate").get(0)); super.onTerminate(); } - - // TODO: only keep around for avoid build errors, will be removed. - public static class InvokeResult - { - public boolean invoked = false; - public Object methodReturns = null; - } - - public static InvokeResult invokeDelegate(Object... args) - { - InvokeResult result = new InvokeResult(); - return result; - } } diff --git a/src/android/java/src/org/qtproject/qt/android/bindings/QtService.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtService.java index 8322af2ae7..6569446901 100644 --- a/src/android/java/src/org/qtproject/qt/android/bindings/QtService.java +++ b/src/android/java/src/org/qtproject/qt/android/bindings/QtService.java @@ -4,85 +4,13 @@ package org.qtproject.qt.android.bindings; -import android.app.Service; -import android.util.Log; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.IBinder; +import org.qtproject.qt.android.QtServiceBase; -import org.qtproject.qt.android.QtNative; -import org.qtproject.qt.android.QtServiceLoader; -import org.qtproject.qt.android.QtLoader; - -public class QtService extends Service +public class QtService extends QtServiceBase { - QtServiceLoader m_loader = new QtServiceLoader(this, QtService.class); - - /////////////////////////// forward all notifications //////////////////////////// - /////////////////////////// Super class calls //////////////////////////////////// - /////////////// PLEASE DO NOT CHANGE THE FOLLOWING CODE ////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - - protected void onCreateHook() { - // the application has already started - // do not reload everything again - if (QtNative.isStarted()) { - m_loader = null; - Log.w(QtNative.QtTAG, - "A QtService tried to start in the same process as an initiated " + - "QtActivity. That is not supported. This results in the service " + - "functioning as an Android Service detached from Qt."); - } else { - m_loader.onCreate(); - } - } @Override public void onCreate() { super.onCreate(); - onCreateHook(); - } - - @Override - public void onDestroy() - { - super.onDestroy(); - QtLoader.invokeDelegate(); - } - - @Override - public IBinder onBind(Intent intent) - { - QtLoader.InvokeResult res = QtLoader.invokeDelegate(intent); - if (res.invoked) - return (IBinder)res.methodReturns; - else - return null; - } - - @Override - public void onConfigurationChanged(Configuration newConfig) - { - if (!QtLoader.invokeDelegate(newConfig).invoked) - super.onConfigurationChanged(newConfig); - } - public void super_onConfigurationChanged(Configuration newConfig) - { - super.onConfigurationChanged(newConfig); - } - - @Override - public boolean onUnbind(Intent intent) - { - QtLoader.InvokeResult res = QtLoader.invokeDelegate(intent); - if (res.invoked) - return (Boolean) res.methodReturns; - else - return super.onUnbind(intent); - } - public boolean super_onUnbind(Intent intent) - { - return super.onUnbind(intent); } - //--------------------------------------------------------------------------- } |