summaryrefslogtreecommitdiffstats
path: root/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java')
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java306
1 files changed, 57 insertions, 249 deletions
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
index 9d5578ed6d..1e72aa3841 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
+ Copyright (c) 2019, BogDan Vatra <bogdan@kde.org>
Contact: http://www.qt.io/licensing/
Commercial License Usage
@@ -44,8 +44,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ComponentInfo;
-import android.content.pm.PackageInfo;
-import android.content.res.AssetManager;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
@@ -55,17 +53,13 @@ import android.util.Log;
import org.kde.necessitas.ministro.IMinistro;
import org.kde.necessitas.ministro.IMinistroCallback;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
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;
@@ -85,9 +79,6 @@ public abstract class QtLoader {
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 QT_LIBS_RESOURCE_ID_KEY = "android.app.qt_libs_resource_id";
- public static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id";
- public static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id";
public static final String MAIN_LIBRARY_KEY = "main.library";
public static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
public static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
@@ -139,7 +130,6 @@ public abstract class QtLoader {
public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme.
public static final int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded.
- public static final int BUFFER_SIZE = 1024;
public String[] m_sources = {"https://download.qt-project.org/ministro/android/qt5/qt-5.7"}; // Make sure you are using ONLY secure locations
public String m_repository = "default"; // Overwrites the default Ministro repository
@@ -153,12 +143,15 @@ public abstract class QtLoader {
// this repository is used to push a new release, and should be used to test your application.
// * unstable - unstable repository, DO NOT use this repository in production,
// this repository is used to push Qt snapshots.
- public String[] m_qtLibs = null; // required qt libs
+ 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;
@@ -188,6 +181,36 @@ public abstract class QtLoader {
}
// 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)
@@ -215,12 +238,14 @@ public abstract class QtLoader {
// add all bundled Qt libs to loader params
ArrayList<String> libs = new ArrayList<String>();
- if (m_contextInfo.metaData.containsKey("android.app.bundled_libs_resource_id"))
- libs.addAll(Arrays.asList(m_context.getResources().getStringArray(m_contextInfo.metaData.getInt("android.app.bundled_libs_resource_id"))));
+ if (m_contextInfo.metaData.containsKey("android.app.bundled_libs_resource_id")) {
+ int resourceId = m_contextInfo.metaData.getInt("android.app.bundled_libs_resource_id");
+ libs.addAll(prefferedAbiLibs(m_context.getResources().getStringArray(resourceId)));
+ }
String libName = null;
if (m_contextInfo.metaData.containsKey("android.app.lib_name")) {
- libName = m_contextInfo.metaData.getString("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
}
@@ -275,7 +300,7 @@ public abstract class QtLoader {
try {
if (m_service != null) {
Bundle parameters = new Bundle();
- parameters.putStringArray(REQUIRED_MODULES_KEY, m_qtLibs);
+ parameters.putStringArray(REQUIRED_MODULES_KEY, (String[]) m_qtLibs.toArray());
parameters.putString(APPLICATION_TITLE_KEY, getTitle());
parameters.putInt(MINIMUM_MINISTRO_API_KEY, MINISTRO_API_LEVEL);
parameters.putInt(MINIMUM_QT_VERSION_KEY, QT_VERSION);
@@ -331,215 +356,6 @@ public abstract class QtLoader {
errorDialog.show();
}
- static private void copyFile(InputStream inputStream, OutputStream outputStream)
- throws IOException
- {
- byte[] buffer = new byte[BUFFER_SIZE];
-
- int count;
- while ((count = inputStream.read(buffer)) > 0)
- outputStream.write(buffer, 0, count);
- }
-
- private void copyAsset(String source, String destination)
- throws IOException
- {
- // Already exists, we don't have to do anything
- File destinationFile = new File(destination);
- if (destinationFile.exists())
- return;
-
- File parentDirectory = destinationFile.getParentFile();
- if (!parentDirectory.exists())
- parentDirectory.mkdirs();
-
- destinationFile.createNewFile();
-
- AssetManager assetsManager = m_context.getAssets();
- InputStream inputStream = null;
- OutputStream outputStream = null;
- try {
- inputStream = assetsManager.open(source);
- outputStream = new FileOutputStream(destinationFile);
- copyFile(inputStream, outputStream);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (inputStream != null)
- inputStream.close();
-
- if (outputStream != null)
- outputStream.close();
- }
- }
-
- private static void createBundledBinary(String source, String destination)
- throws IOException
- {
- // Already exists, we don't have to do anything
- File destinationFile = new File(destination);
- if (destinationFile.exists())
- return;
-
- File parentDirectory = destinationFile.getParentFile();
- if (!parentDirectory.exists())
- parentDirectory.mkdirs();
-
- destinationFile.createNewFile();
-
- InputStream inputStream = null;
- OutputStream outputStream = null;
- try {
- inputStream = new FileInputStream(source);
- outputStream = new FileOutputStream(destinationFile);
- copyFile(inputStream, outputStream);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (inputStream != null)
- inputStream.close();
-
- if (outputStream != null)
- outputStream.close();
- }
- }
-
- private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion)
- {
- File versionFile = new File(pluginsPrefix + "cache.version");
-
- long cacheVersion = 0;
- if (versionFile.exists() && versionFile.canRead()) {
- DataInputStream inputStream = null;
- try {
- inputStream = new DataInputStream(new FileInputStream(versionFile));
- cacheVersion = inputStream.readLong();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- if (cacheVersion != packageVersion) {
- deleteRecursively(new File(pluginsPrefix));
- return true;
- } else {
- return false;
- }
- }
-
- private void extractBundledPluginsAndImports(String pluginsPrefix, String libsDir)
- throws IOException
- {
- long packageVersion = -1;
- try {
- PackageInfo packageInfo = m_context.getPackageManager().getPackageInfo(m_context.getPackageName(), 0);
- packageVersion = packageInfo.lastUpdateTime;
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion))
- return;
-
- {
- File versionFile = new File(pluginsPrefix + "cache.version");
-
- File parentDirectory = versionFile.getParentFile();
- if (!parentDirectory.exists())
- parentDirectory.mkdirs();
-
- versionFile.createNewFile();
-
- DataOutputStream outputStream = null;
- try {
- outputStream = new DataOutputStream(new FileOutputStream(versionFile));
- outputStream.writeLong(packageVersion);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (outputStream != null)
- outputStream.close();
- }
- }
-
- {
- // why can't we load the plugins directly from libs ?!?!
- String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
- if (m_contextInfo.metaData.containsKey(key)) {
- String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key));
-
- for (String bundledImportBinary : list) {
- String[] split = bundledImportBinary.split(":");
- String sourceFileName = libsDir + split[0];
- String destinationFileName = pluginsPrefix + split[1];
- createBundledBinary(sourceFileName, destinationFileName);
- }
- }
- }
-
- {
- String key = BUNDLED_IN_ASSETS_RESOURCE_ID_KEY;
- if (m_contextInfo.metaData.containsKey(key)) {
- String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key));
-
- for (String fileName : list) {
- String[] split = fileName.split(":");
- String sourceFileName = split[0];
- String destinationFileName = pluginsPrefix + split[1];
- copyAsset(sourceFileName, destinationFileName);
- }
- }
-
- }
- }
-
- private void deleteRecursively(File directory)
- {
- File[] files = directory.listFiles();
- if (files != null) {
- for (File file : files) {
- if (file.isDirectory())
- deleteRecursively(file);
- else
- file.delete();
- }
-
- directory.delete();
- }
- }
-
- private void cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix)
- {
- File newCache = new File(localPrefix);
- if (!newCache.exists()) {
- {
- File oldPluginsCache = new File(oldLocalPrefix + "plugins/");
- if (oldPluginsCache.exists() && oldPluginsCache.isDirectory())
- deleteRecursively(oldPluginsCache);
- }
-
- {
- File oldImportsCache = new File(oldLocalPrefix + "imports/");
- if (oldImportsCache.exists() && oldImportsCache.isDirectory())
- deleteRecursively(oldImportsCache);
- }
-
- {
- File oldQmlCache = new File(oldLocalPrefix + "qml/");
- if (oldQmlCache.exists() && oldQmlCache.isDirectory())
- deleteRecursively(oldQmlCache);
- }
- }
- }
-
public void startApp(final boolean firstStart)
{
try {
@@ -553,7 +369,7 @@ public abstract class QtLoader {
if (m_contextInfo.metaData.containsKey("android.app.qt_libs_resource_id")) {
int resourceId = m_contextInfo.metaData.getInt("android.app.qt_libs_resource_id");
- m_qtLibs = m_context.getResources().getStringArray(resourceId);
+ m_qtLibs = prefferedAbiLibs(m_context.getResources().getStringArray(resourceId));
}
if (m_contextInfo.metaData.containsKey("android.app.use_local_qt_libs")
@@ -567,6 +383,7 @@ public abstract class QtLoader {
apkDeployFromSystem = true;
String libsDir = null;
+ String bundledLibsDir = null;
if (apkDeployFromSystem) {
String systemLibsPrefix = SYSTEM_LIB_PATH;
if (m_contextInfo.metaData.containsKey("android.app.system_libs_prefix")) {
@@ -583,8 +400,11 @@ public abstract class QtLoader {
} else {
String nativeLibraryPrefix = m_context.getApplicationInfo().nativeLibraryDir + "/";
File nativeLibraryDir = new File(nativeLibraryPrefix);
- if (nativeLibraryDir.exists() && nativeLibraryDir.isDirectory() && nativeLibraryDir.list().length > 0)
+ if (nativeLibraryDir.exists() && nativeLibraryDir.isDirectory() && nativeLibraryDir.list().length > 0) {
libsDir = nativeLibraryPrefix;
+ bundledLibsDir = nativeLibraryPrefix;
+ }
+
}
if (apkDeployFromSystem && libsDir == null)
@@ -593,33 +413,21 @@ public abstract class QtLoader {
if (m_qtLibs != null) {
String libPrefix = libsDir + "lib";
- for (int i = 0; i < m_qtLibs.length; i++)
- libraryList.add(libPrefix + m_qtLibs[i] + ".so");
+ for (String lib : m_qtLibs)
+ libraryList.add(libPrefix + lib + ".so");
}
if (m_contextInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
&& m_contextInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
- File dataDir = new File(m_context.getApplicationInfo().dataDir);
- String dataPath = dataDir.getCanonicalPath() + "/";
- String pluginsPrefix = dataPath + "qt-reserved-files/";
-
- if (libsDir == null)
- throw new Exception("");
-
- cleanOldCacheIfNecessary(dataPath, pluginsPrefix);
- extractBundledPluginsAndImports(pluginsPrefix, libsDir);
-
- if (m_contextInfo.metaData.containsKey(BUNDLED_IN_LIB_RESOURCE_ID_KEY)) {
- String[] extraLibs = m_contextInfo.metaData.getString("android.app.load_local_libs").split(":");
- for (String lib : extraLibs) {
+ int resourceId = m_contextInfo.metaData.getInt("android.app.load_local_libs_resource_id");
+ for (String libs : prefferedAbiLibs(m_context.getResources().getStringArray(resourceId))) {
+ for (String lib : libs.split(":")) {
if (!lib.isEmpty())
- libraryList.add(pluginsPrefix + lib);
+ libraryList.add(libsDir + lib);
}
}
-
- ENVIRONMENT_VARIABLES += "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml"
- + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports"
- + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins";
+ if (bundledLibsDir != null)
+ ENVIRONMENT_VARIABLES += "\tQT_BUNDLED_LIBS_PATH=" + bundledLibsDir;
}
Bundle loaderParams = new Bundle();