diff options
Diffstat (limited to 'src/android')
-rw-r--r-- | src/android/jar/jar.pro | 1 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtNative.java | 19 | ||||
-rw-r--r-- | src/android/java/java.pro | 2 | ||||
-rw-r--r-- | src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java | 306 | ||||
-rw-r--r-- | src/android/templates/AndroidManifest.xml | 7 | ||||
-rw-r--r-- | src/android/templates/build.gradle | 9 | ||||
-rw-r--r-- | src/android/templates/res/values/libs.xml | 15 | ||||
-rw-r--r-- | src/android/templates/templates.pro | 2 |
8 files changed, 97 insertions, 264 deletions
diff --git a/src/android/jar/jar.pro b/src/android/jar/jar.pro index ac6fc79968..24a83d56a1 100644 --- a/src/android/jar/jar.pro +++ b/src/android/jar/jar.pro @@ -1,6 +1,7 @@ TARGET = QtAndroid CONFIG += java + DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/ diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index c33d5016ce..7db16002ff 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -1013,6 +1013,25 @@ public class QtNative }); } + private static String[] listAssetContent(android.content.res.AssetManager asset, String path) { + String [] list; + ArrayList<String> res = new ArrayList<String>(); + try { + list = asset.list(path); + if (list.length > 0) { + for (String file : list) { + try { + String[] isDir = asset.list(path.length() > 0 ? path + "/" + file : file); + if (isDir != null && isDir.length > 0) + file += "/"; + res.add(file); + } catch (Exception e) {} + } + } + } catch (Exception e) {} + return res.toArray(new String[res.size()]); + } + // screen methods public static native void setDisplayMetrics(int screenWidthPixels, int screenHeightPixels, diff --git a/src/android/java/java.pro b/src/android/java/java.pro index 9d37eb1026..7f0dfa8a1b 100644 --- a/src/android/java/java.pro +++ b/src/android/java/java.pro @@ -1,3 +1,5 @@ +CONFIG += single_arch + CONFIG -= qt android_install javaresources.files = \ 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(); diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml index aed8a3c888..6d0f4e0d45 100644 --- a/src/android/templates/AndroidManifest.xml +++ b/src/android/templates/AndroidManifest.xml @@ -12,7 +12,7 @@ <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> - <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --"> + <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:extractNativeLibs="true"> <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" @@ -34,12 +34,11 @@ <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/> <!-- Deploy Qt libs as part of package --> <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/> - <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/> - <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/> + <!-- Run with local libs --> <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/> <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/> - <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/> + <meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/> <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/> <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/> <!-- Used to specify custom system library path to run with local system libs --> diff --git a/src/android/templates/build.gradle b/src/android/templates/build.gradle index ed704c4957..3087d08c83 100644 --- a/src/android/templates/build.gradle +++ b/src/android/templates/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.2.0' + classpath 'com.android.tools.build:gradle:3.5.0' } } @@ -44,7 +44,7 @@ android { java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] res.srcDirs = [qt5AndroidDir + '/res', 'res'] - resources.srcDirs = ['src'] + resources.srcDirs = ['resources'] renderscript.srcDirs = ['src'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] @@ -54,4 +54,9 @@ android { lintOptions { abortOnError false } + + // Do not compress Qt binary resources file + aaptOptions { + noCompress 'rcc' + } } diff --git a/src/android/templates/res/values/libs.xml b/src/android/templates/res/values/libs.xml index 4009a7785a..6b1a4a2a02 100644 --- a/src/android/templates/res/values/libs.xml +++ b/src/android/templates/res/values/libs.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='utf-8'?> <resources> <array name="qt_sources"> - <item>https://download.qt.io/ministro/android/qt5/qt-5.9</item> + <item>https://download.qt.io/ministro/android/qt5/qt-5.14</item> </array> <!-- The following is handled automatically by the deployment tool. It should @@ -11,15 +11,12 @@ <!-- %%INSERT_EXTRA_LIBS%% --> </array> - <array name="qt_libs"> - <!-- %%INSERT_QT_LIBS%% --> - </array> - - <array name="bundled_in_lib"> - <!-- %%INSERT_BUNDLED_IN_LIB%% --> + <array name="qt_libs"> + <!-- %%INSERT_QT_LIBS%% --> </array> - <array name="bundled_in_assets"> - <!-- %%INSERT_BUNDLED_IN_ASSETS%% --> + + <array name="load_local_libs"> + <!-- %%INSERT_LOCAL_LIBS%% --> </array> </resources> diff --git a/src/android/templates/templates.pro b/src/android/templates/templates.pro index 55387f3af7..9a64251ee3 100644 --- a/src/android/templates/templates.pro +++ b/src/android/templates/templates.pro @@ -1,3 +1,5 @@ +CONFIG += single_arch + CONFIG -= qt android_install templates.files = \ |