diff options
Diffstat (limited to 'src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java')
-rw-r--r-- | src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java | 411 |
1 files changed, 0 insertions, 411 deletions
diff --git a/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java deleted file mode 100644 index 71595fb9fd..0000000000 --- a/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java +++ /dev/null @@ -1,411 +0,0 @@ -/* - Copyright (C) 2021 The Qt Company Ltd. - Copyright (c) 2019, BogDan Vatra <bogdan@kde.org> - Contact: http://www.qt.io/licensing/ - - Commercial License Usage - Licensees holding valid commercial Qt licenses may use this file in - accordance with the commercial license agreement provided with the - Software or, alternatively, in accordance with the terms contained in - a written agreement between you and The Qt Company. For licensing terms - and conditions see http://www.qt.io/terms-conditions. For further - information use the contact form at http://www.qt.io/contact-us. - - BSD License Usage - Alternatively, this file may be used under the BSD license as follows: - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package org.qtproject.qt.android.bindings; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.ComponentInfo; -import android.content.res.Resources; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; - -import java.io.File; -import java.io.FileOutputStream; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -import dalvik.system.DexClassLoader; - -public abstract class QtLoader { - - public static final String ERROR_CODE_KEY = "error.code"; - public static final String ERROR_MESSAGE_KEY = "error.message"; - public static final String DEX_PATH_KEY = "dex.path"; - public static final String LIB_PATH_KEY = "lib.path"; - public static final String LOADER_CLASS_NAME_KEY = "loader.class.name"; - public static final String NATIVE_LIBRARIES_KEY = "native.libraries"; - public static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables"; - public static final String APPLICATION_PARAMETERS_KEY = "application.parameters"; - public static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries"; - public static final String MAIN_LIBRARY_KEY = "main.library"; - public static final String STATIC_INIT_CLASSES_KEY = "static.init.classes"; - public static final String EXTRACT_STYLE_KEY = "extract.android.style"; - private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option"; - - // 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 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. - - 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. - - QtLoader(ContextWrapper context, Class<?> clazz) { - m_context = context; - m_delegateClass = clazz; - } - - // Implement in subclass - protected void finish() {} - - protected String getTitle() { - return "Qt"; - } - - protected void runOnUiThread(Runnable run) { - run.run(); - } - - protected abstract String loaderClassName(); - protected abstract Class<?> contextClassName(); - - Intent getIntent() - { - return null; - } - // Implement in subclass - - private final List<String> supportedAbis = Arrays.asList(Build.SUPPORTED_ABIS); - private String preferredAbi = null; - - private ArrayList<String> prefferedAbiLibs(String []libs) - { - HashMap<String, ArrayList<String>> abisLibs = new HashMap<>(); - for (String lib : libs) { - String[] archLib = lib.split(";", 2); - if (preferredAbi != null && !archLib[0].equals(preferredAbi)) - continue; - if (!abisLibs.containsKey(archLib[0])) - abisLibs.put(archLib[0], new ArrayList<String>()); - abisLibs.get(archLib[0]).add(archLib[1]); - } - - if (preferredAbi != null) { - if (abisLibs.containsKey(preferredAbi)) { - return abisLibs.get(preferredAbi); - } - return new ArrayList<String>(); - } - - for (String abi: supportedAbis) { - if (abisLibs.containsKey(abi)) { - preferredAbi = abi; - return abisLibs.get(abi); - } - } - return new ArrayList<String>(); - } - - // this function is used to load and start the loader - private void loadApplication(Bundle loaderParams) - { - final Resources resources = m_context.getResources(); - final String packageName = m_context.getPackageName(); - try { - final int errorCode = loaderParams.getInt(ERROR_CODE_KEY); - if (errorCode != 0) { - // fatal error, show the error and quit - AlertDialog errorDialog = new AlertDialog.Builder(m_context).create(); - errorDialog.setMessage(loaderParams.getString(ERROR_MESSAGE_KEY)); - errorDialog.setButton(resources.getString(android.R.string.ok), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); - errorDialog.show(); - return; - } - - // add all bundled Qt libs to loader params - int id = resources.getIdentifier("bundled_libs", "array", packageName); - final String[] bundledLibs = resources.getStringArray(id); - ArrayList<String> libs = new ArrayList<>(prefferedAbiLibs(bundledLibs)); - - String libName = null; - if (m_contextInfo.metaData.containsKey("android.app.lib_name")) { - libName = m_contextInfo.metaData.getString("android.app.lib_name") + "_" + preferredAbi; - loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function - } - - loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs); - - // load and start QtLoader class - DexClassLoader classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files - m_context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written. - 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(""); - - QtApplication.setQtContextDelegate(m_delegateClass, qtLoader); - - Method startAppMethod=qtLoader.getClass().getMethod("startApplication"); - if (!(Boolean)startAppMethod.invoke(qtLoader)) - throw new Exception(""); - - } catch (Exception e) { - e.printStackTrace(); - AlertDialog errorDialog = new AlertDialog.Builder(m_context).create(); - int id = resources.getIdentifier("fatal_error_msg", "string", - packageName); - errorDialog.setMessage(resources.getString(id)); - errorDialog.setButton(resources.getString(android.R.string.ok), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - finish(); - } - }); - errorDialog.show(); - } - } - - public void startApp(final boolean firstStart) - { - try { - final Resources resources = m_context.getResources(); - final String packageName = m_context.getPackageName(); - int id = resources.getIdentifier("qt_libs", "array", packageName); - m_qtLibs = prefferedAbiLibs(resources.getStringArray(id)); - - id = resources.getIdentifier("use_local_qt_libs", "string", packageName); - final int useLocalLibs = Integer.parseInt(resources.getString(id)); - - if (useLocalLibs == 1) { - ArrayList<String> libraryList = new ArrayList<>(); - String libsDir = null; - String bundledLibsDir = null; - - id = resources.getIdentifier("bundle_local_qt_libs", "string", packageName); - final int bundleLocalLibs = Integer.parseInt(resources.getString(id)); - if (bundleLocalLibs == 0) { - String systemLibsPrefix; - final String systemLibsKey = "android.app.system_libs_prefix"; - // First check if user has provided system libs prefix in AndroidManifest - if (m_contextInfo.applicationInfo.metaData != null && - m_contextInfo.applicationInfo.metaData.containsKey(systemLibsKey)) { - systemLibsPrefix = m_contextInfo.applicationInfo.metaData.getString(systemLibsKey); - } else { - // If not, check if it's provided by androiddeployqt in libs.xml - id = resources.getIdentifier("system_libs_prefix","string", - packageName); - systemLibsPrefix = resources.getString(id); - } - if (systemLibsPrefix.isEmpty()) { - systemLibsPrefix = SYSTEM_LIB_PATH; - Log.e(QtApplication.QtTAG, "It looks like app deployed using Unbundled " - + "deployment. It may be necessary to specify path to directory " - + "where Qt libraries are installed using either " - + "android.app.system_libs_prefix metadata variable in your " - + "AndroidManifest.xml or QT_ANDROID_SYSTEM_LIBS_PATH in your " - + "CMakeLists.txt"); - Log.e(QtApplication.QtTAG, "Using " + SYSTEM_LIB_PATH + " as default path"); - } - - File systemLibraryDir = new File(systemLibsPrefix); - if (systemLibraryDir.exists() && systemLibraryDir.isDirectory() - && systemLibraryDir.list().length > 0) { - libsDir = systemLibsPrefix; - bundledLibsDir = systemLibsPrefix; - } else { - Log.e(QtApplication.QtTAG, - "System library directory " + systemLibsPrefix - + " does not exist or is empty."); - } - } else { - String nativeLibraryPrefix = m_context.getApplicationInfo().nativeLibraryDir + "/"; - File nativeLibraryDir = new File(nativeLibraryPrefix); - if (nativeLibraryDir.exists() && nativeLibraryDir.isDirectory() && nativeLibraryDir.list().length > 0) { - libsDir = nativeLibraryPrefix; - bundledLibsDir = nativeLibraryPrefix; - } else { - Log.e(QtApplication.QtTAG, - "Native library directory " + nativeLibraryPrefix - + " does not exist or is empty."); - } - } - - if (libsDir == null) - throw new Exception(""); - - - if (m_qtLibs != null) { - String libPrefix = libsDir + "lib"; - for (String lib : m_qtLibs) - libraryList.add(libPrefix + lib + ".so"); - } - - id = resources.getIdentifier("load_local_libs", "array", packageName); - ArrayList<String> localLibs = prefferedAbiLibs(resources.getStringArray(id)); - for (String libs : localLibs) { - for (String lib : libs.split(":")) { - if (!lib.isEmpty()) - libraryList.add(libsDir + lib); - } - } - if (bundledLibsDir != null) { - ENVIRONMENT_VARIABLES += "\tQT_PLUGIN_PATH=" + bundledLibsDir; - ENVIRONMENT_VARIABLES += "\tQML_PLUGIN_PATH=" + bundledLibsDir; - } - - 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) - .split(":")); - - loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList); - - - String themePath = m_context.getApplicationInfo().dataDir + "/qt-reserved-files/android-style/"; - String stylePath = themePath + m_displayDensity + "/"; - - String extractOption = "default"; - if (m_contextInfo.metaData.containsKey("android.app.extract_android_style")) { - extractOption = m_contextInfo.metaData.getString("android.app.extract_android_style"); - if (!extractOption.equals("default") && !extractOption.equals("full") && !extractOption.equals("minimal") && !extractOption.equals("none")) { - Log.e(QtApplication.QtTAG, "Invalid extract_android_style option \"" + extractOption + "\", defaulting to \"default\""); - extractOption = "default"; - } - } - - // QTBUG-69810: The extraction code will trigger compatibility warnings on Android SDK version >= 28 - // when the target SDK version is set to something lower then 28, so default to "none" and issue a warning - // if that is the case. - if (extractOption.equals("default")) { - final int targetSdkVersion = m_context.getApplicationInfo().targetSdkVersion; - if (targetSdkVersion < 28 && Build.VERSION.SDK_INT >= 28) { - Log.e(QtApplication.QtTAG, "extract_android_style option set to \"none\" when targetSdkVersion is less then 28"); - extractOption = "none"; - } - } - - if (!(new File(stylePath)).exists() && !extractOption.equals("none")) { - loaderParams.putString(EXTRACT_STYLE_KEY, stylePath); - loaderParams.putBoolean(EXTRACT_STYLE_MINIMAL_KEY, extractOption.equals("minimal")); - } - - if (extractOption.equals("full")) - ENVIRONMENT_VARIABLES += "\tQT_USE_ANDROID_NATIVE_STYLE=1"; - - ENVIRONMENT_VARIABLES += "\tANDROID_STYLE_PATH=" + stylePath; - - loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES); - - String appParams = null; - if (APPLICATION_PARAMETERS != null) - appParams = APPLICATION_PARAMETERS; - - Intent intent = getIntent(); - if (intent != null) { - String parameters = intent.getStringExtra("applicationArguments"); - if (parameters != null) - if (appParams == null) - appParams = parameters; - else - appParams += '\t' + parameters; - } - - if (m_contextInfo.metaData.containsKey("android.app.arguments")) { - String parameters = m_contextInfo.metaData.getString("android.app.arguments"); - if (appParams == null) - appParams = parameters; - else - appParams += '\t' + parameters; - } - - if (appParams != null) - loaderParams.putString(APPLICATION_PARAMETERS_KEY, appParams); - - loadApplication(loaderParams); - return; - } - } catch (Exception e) { - Log.e(QtApplication.QtTAG, "Can't create main activity", e); - } - } -} |