Android: Simplify Qt for Android hierarchy, less Java reflection!
This changes takes Qt for Android Java code away from the Delegate classes that uses heavily Java reflection to invoke Activity/Service calls and overrides. So instead of that, now, we have a QtActivityBase and a QtServiceBase classes which handle the override logic needed for Qt directly without reflection. These Base classes extend Android's Activity and Service directly, and are inside the internal Qt android package (under Qt6Android.jar). For example, to handle onConfigurationChanged, instead of the current way where we need this in 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); } And then this in QtActivity: @Override public void onConfigurationChanged(Configuration newConfig) { if (!QtLoader.invokeDelegate(newConfig).invoked) super.onConfigurationChanged(newConfig); } public void super_onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } And having to keep it's Method handles around and then use Java reflection to call the override behavior done by Qt and the superclass methods. instead of that, we can do it now in QtActivityBase like: @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); handleUiModeChange(newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK); } Then, we would still have our user facing QtActivity class which extends QtActivityBase and benefit from the same implementation of Qt logic done in the base class. An additional benefit to this approach is that now QtActivity will be very lightweight and doesn't need to have all the boilerplate code as before. [ChangeLog][Android] Simplify Qt for Android public bindings (QActivity, QtService and QtApplication) by implementing base classes which use the delegate implementions directly and avoid reflection. Task-number: QTBUG-115014 Task-number: QTBUG-114593 Change-Id: Ie1eca74f989627be4468786a27e30b16209fc521 Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
This commit is contained in:
parent
beac5a6d72
commit
3b6d288e3b
@ -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
|
||||
|
349
src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
Normal file
349
src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -16,22 +16,12 @@ 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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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) {
|
||||
public QtLoader(ContextWrapper context) {
|
||||
m_context = context;
|
||||
m_delegateClass = clazz;
|
||||
}
|
||||
|
||||
public static void setQtApplicationClass(Class qtAppClass)
|
||||
{
|
||||
qtApplicationClass = qtAppClass;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,44 +13,41 @@ 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()
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
m_loader = new QtActivityLoader(this, QtActivity.class);
|
||||
setAppDetails();
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
private void setAppDetails()
|
||||
{
|
||||
// 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 = "";
|
||||
|
||||
// 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";
|
||||
|
||||
// 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"
|
||||
|
||||
if (Build.VERSION.SDK_INT < 29) {
|
||||
QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"};
|
||||
@ -65,326 +57,4 @@ public class QtActivity extends Activity
|
||||
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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
super.onStop();
|
||||
QtLoader.invokeDelegate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus)
|
||||
{
|
||||
if (!QtLoader.invokeDelegate(hasFocus).invoked)
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
}
|
||||
public void super_onWindowFocusChanged(boolean hasFocus)
|
||||
{
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
|
||||
{
|
||||
if (QtLoader.m_delegateObject != null && QtLoader.onRequestPermissionsResult != null) {
|
||||
QtLoader.invokeDelegateMethod(QtLoader.onRequestPermissionsResult, requestCode ,
|
||||
permissions, grantResults);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ public class QtJniObjectTestClass
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
final int INT_FIELD = 123;
|
||||
final boolean BOOL_FIELD = true;
|
||||
|
||||
byte BYTE_VAR;
|
||||
short SHORT_VAR;
|
||||
int INT_VAR;
|
||||
|
@ -1034,19 +1034,19 @@ void tst_QJniObject::getStaticCharField()
|
||||
|
||||
void tst_QJniObject::getBooleanField()
|
||||
{
|
||||
QJniObject obj("org/qtproject/qt/android/QtActivityDelegate");
|
||||
QJniObject obj(testClassName);
|
||||
|
||||
QVERIFY(obj.isValid());
|
||||
QVERIFY(!obj.getField<jboolean>("m_backKeyPressedSent"));
|
||||
QVERIFY(obj.getField<jboolean>("BOOL_FIELD"));
|
||||
}
|
||||
|
||||
void tst_QJniObject::getIntField()
|
||||
{
|
||||
QJniObject obj("org/qtproject/qt/android/QtActivityDelegate");
|
||||
QJniObject obj(testClassName);
|
||||
|
||||
QVERIFY(obj.isValid());
|
||||
jint res = obj.getField<jint>("m_currentRotation");
|
||||
QCOMPARE(res, -1);
|
||||
jint res = obj.getField<jint>("INT_FIELD");
|
||||
QCOMPARE(res, 123);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
Loading…
x
Reference in New Issue
Block a user