diff options
Diffstat (limited to 'src/android')
-rw-r--r-- | src/android/jar/bundledjar.pro | 3 | ||||
-rw-r--r-- | src/android/jar/distributedjar.pro | 2 | ||||
-rw-r--r-- | src/android/jar/jar.pri | 26 | ||||
-rw-r--r-- | src/android/jar/jar.pro | 31 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java | 37 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtNative.java | 156 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java | 1 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java | 12 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtThread.java | 112 | ||||
-rw-r--r-- | src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java | 79 | ||||
-rw-r--r-- | src/android/templates/AndroidManifest.xml | 2 |
11 files changed, 351 insertions, 110 deletions
diff --git a/src/android/jar/bundledjar.pro b/src/android/jar/bundledjar.pro deleted file mode 100644 index e82c01c51b..0000000000 --- a/src/android/jar/bundledjar.pro +++ /dev/null @@ -1,3 +0,0 @@ -TARGET = QtAndroid-bundled -CONFIG += bundled_jar_file -include(jar.pri) diff --git a/src/android/jar/distributedjar.pro b/src/android/jar/distributedjar.pro deleted file mode 100644 index 15f362f629..0000000000 --- a/src/android/jar/distributedjar.pro +++ /dev/null @@ -1,2 +0,0 @@ -TARGET = QtAndroid -include(jar.pri) diff --git a/src/android/jar/jar.pri b/src/android/jar/jar.pri deleted file mode 100644 index 4535880536..0000000000 --- a/src/android/jar/jar.pri +++ /dev/null @@ -1,26 +0,0 @@ -CONFIG += java -DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar -API_VERSION = android-16 - -PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/ - -JAVACLASSPATH += $$PWD/src/ -JAVASOURCES += \ - $$PATHPREFIX/accessibility/QtAccessibilityDelegate.java \ - $$PATHPREFIX/accessibility/QtNativeAccessibility.java \ - $$PATHPREFIX/QtActivityDelegate.java \ - $$PATHPREFIX/QtEditText.java \ - $$PATHPREFIX/QtInputConnection.java \ - $$PATHPREFIX/QtLayout.java \ - $$PATHPREFIX/QtMessageDialogHelper.java \ - $$PATHPREFIX/QtNative.java \ - $$PATHPREFIX/QtNativeLibrariesDir.java \ - $$PATHPREFIX/QtSurface.java \ - $$PATHPREFIX/ExtractStyle.java \ - $$PATHPREFIX/EditMenu.java \ - $$PATHPREFIX/EditPopupMenu.java \ - $$PATHPREFIX/CursorHandle.java - -# install -target.path = $$[QT_INSTALL_PREFIX]/jar -INSTALLS += target diff --git a/src/android/jar/jar.pro b/src/android/jar/jar.pro index 8d19c1b7d6..683866a345 100644 --- a/src/android/jar/jar.pro +++ b/src/android/jar/jar.pro @@ -1,2 +1,29 @@ -TEMPLATE = subdirs -SUBDIRS += bundledjar.pro distributedjar.pro +TARGET = QtAndroid + +CONFIG += java +DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar +API_VERSION = android-16 + +PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/ + +JAVACLASSPATH += $$PWD/src/ +JAVASOURCES += \ + $$PATHPREFIX/accessibility/QtAccessibilityDelegate.java \ + $$PATHPREFIX/accessibility/QtNativeAccessibility.java \ + $$PATHPREFIX/QtActivityDelegate.java \ + $$PATHPREFIX/QtEditText.java \ + $$PATHPREFIX/QtInputConnection.java \ + $$PATHPREFIX/QtLayout.java \ + $$PATHPREFIX/QtMessageDialogHelper.java \ + $$PATHPREFIX/QtNative.java \ + $$PATHPREFIX/QtNativeLibrariesDir.java \ + $$PATHPREFIX/QtSurface.java \ + $$PATHPREFIX/ExtractStyle.java \ + $$PATHPREFIX/EditMenu.java \ + $$PATHPREFIX/EditPopupMenu.java \ + $$PATHPREFIX/CursorHandle.java \ + $$PATHPREFIX/QtThread.java + +# install +target.path = $$[QT_INSTALL_PREFIX]/jar +INSTALLS += target diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 952bf04971..6b8577116e 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -63,6 +63,9 @@ import android.util.Base64; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.KeyCharacterMap; @@ -918,6 +921,7 @@ public class QtActivityDelegate public void onTerminate() { QtNative.terminateQt(); + QtNative.m_qtThread.exit(); } public void onCreate(Bundle savedInstanceState) @@ -1002,10 +1006,36 @@ public class QtActivityDelegate public void hideSplashScreen() { + hideSplashScreen(0); + } + + public void hideSplashScreen(final int duration) + { if (m_splashScreen == null) return; - m_layout.removeView(m_splashScreen); - m_splashScreen = null; + + if (duration <= 0) { + m_layout.removeView(m_splashScreen); + m_splashScreen = null; + return; + } + + final Animation fadeOut = new AlphaAnimation(1, 0); + fadeOut.setInterpolator(new AccelerateInterpolator()); + fadeOut.setDuration(duration); + + fadeOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationEnd(Animation animation) { hideSplashScreen(0); } + + @Override + public void onAnimationRepeat(Animation animation) {} + + @Override + public void onAnimationStart(Animation animation) {} + }); + + m_splashScreen.startAnimation(fadeOut); } @@ -1047,7 +1077,8 @@ public class QtActivityDelegate QtNative.setActivity(null, null); if (m_debuggerProcess != null) m_debuggerProcess.destroy(); - System.exit(0);// FIXME remove it or find a better way + QtNative.m_qtThread.exit(); + System.exit(0); } } 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 ab6d556768..3db3453263 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -49,12 +49,14 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.content.pm.ActivityInfo; import android.net.Uri; +import android.os.Build; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.content.ClipboardManager; import android.content.ClipboardManager.OnPrimaryClipChangedListener; -import android.os.Build; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; @@ -96,6 +98,7 @@ public class QtNative private static ClipboardManager m_clipboardManager = null; private static Method m_checkSelfPermissionMethod = null; private static Boolean m_tabletEventSupported = null; + public static QtThread m_qtThread = new QtThread(); private static final Runnable runPendingCppRunnablesRunnable = new Runnable() { @Override public void run() { @@ -162,41 +165,64 @@ public class QtNative } // this method loads full path libs - public static void loadQtLibraries(ArrayList<String> libraries) + public static void loadQtLibraries(final ArrayList<String> libraries) { - if (libraries == null) - return; - - for (String libName : libraries) { - try { - File f = new File(libName); - if (f.exists()) - System.load(libName); - } catch (SecurityException e) { - Log.i(QtTAG, "Can't load '" + libName + "'", e); - } catch (Exception e) { - Log.i(QtTAG, "Can't load '" + libName + "'", e); + m_qtThread.run(new Runnable() { + @Override + public void run() { + if (libraries == null) + return; + for (String libName : libraries) { + try { + File f = new File(libName); + if (f.exists()) + System.load(libName); + } catch (SecurityException e) { + Log.i(QtTAG, "Can't load '" + libName + "'", e); + } catch (Exception e) { + Log.i(QtTAG, "Can't load '" + libName + "'", e); + } + } } - } + }); } // this method loads bundled libs by name. - public static void loadBundledLibraries(ArrayList<String> libraries, String nativeLibraryDir) + public static void loadBundledLibraries(final ArrayList<String> libraries, final String nativeLibraryDir) { - if (libraries == null) - return; + m_qtThread.run(new Runnable() { + @Override + public void run() { + if (libraries == null) + return; + + for (String libName : libraries) { + try { + String libNameTemplate = "lib" + libName + ".so"; + File f = new File(nativeLibraryDir + libNameTemplate); + if (!f.exists()) { + Log.i(QtTAG, "Can't find '" + f.getAbsolutePath()); + try { + ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), + PackageManager.GET_META_DATA); + String systemLibraryDir = QtNativeLibrariesDir.systemLibrariesDir; + if (info.metaData.containsKey("android.app.system_libs_prefix")) + systemLibraryDir = info.metaData.getString("android.app.system_libs_prefix"); + f = new File(systemLibraryDir + libNameTemplate); + } catch (Exception e) { - for (String libName : libraries) { - try { - File f = new File(nativeLibraryDir+"lib"+libName+".so"); - if (f.exists()) - System.load(f.getAbsolutePath()); - else - Log.i(QtTAG, "Can't find '" + f.getAbsolutePath()); - } catch (Exception e) { - Log.i(QtTAG, "Can't load '" + libName + "'", e); + } + } + if (f.exists()) + System.load(f.getAbsolutePath()); + else + Log.i(QtTAG, "Can't find '" + f.getAbsolutePath()); + } catch (Exception e) { + Log.i(QtTAG, "Can't load '" + libName + "'", e); + } + } } - } + }); } public static void setActivity(Activity qtMainActivity, QtActivityDelegate qtActivityDelegate) @@ -277,34 +303,66 @@ public class QtNative } public static boolean startApplication(String params, - String environment, + final String environment, String mainLibrary, String nativeLibraryDir) throws Exception { - File f = new File(nativeLibraryDir + "lib" + mainLibrary + ".so"); + String mainLibNameTemplate = "lib" + mainLibrary + ".so"; + File f = new File(nativeLibraryDir + mainLibNameTemplate); + if (!f.exists()) { + try { + ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), + PackageManager.GET_META_DATA); + String systemLibraryDir = QtNativeLibrariesDir.systemLibrariesDir; + if (info.metaData.containsKey("android.app.system_libs_prefix")) + systemLibraryDir = info.metaData.getString("android.app.system_libs_prefix"); + f = new File(systemLibraryDir + mainLibNameTemplate); + } catch (Exception e) { + + } + } if (!f.exists()) throw new Exception("Can't find main library '" + mainLibrary + "'"); if (params == null) params = "-platform\tandroid"; - boolean res = false; + final String mainLibraryPath = f.getAbsolutePath(); + final boolean[] res = new boolean[1]; + res[0] = false; synchronized (m_mainActivityMutex) { - res = startQtAndroidPlugin(); - setDisplayMetrics(m_displayMetricsScreenWidthPixels, - m_displayMetricsScreenHeightPixels, - m_displayMetricsDesktopWidthPixels, - m_displayMetricsDesktopHeightPixels, - m_displayMetricsXDpi, - m_displayMetricsYDpi, - m_displayMetricsScaledDensity, - m_displayMetricsDensity); if (params.length() > 0 && !params.startsWith("\t")) params = "\t" + params; - startQtApplication(f.getAbsolutePath() + params, environment); + final String qtParams = f.getAbsolutePath() + params; + m_qtThread.run(new Runnable() { + @Override + public void run() { + try { + System.load(mainLibraryPath); + } catch (Exception e) { + Log.i(QtTAG, "Can't load '" + mainLibraryPath + "'", e); + } + res[0] = startQtAndroidPlugin(qtParams, environment); + setDisplayMetrics(m_displayMetricsScreenWidthPixels, + m_displayMetricsScreenHeightPixels, + m_displayMetricsDesktopWidthPixels, + m_displayMetricsDesktopHeightPixels, + m_displayMetricsXDpi, + m_displayMetricsYDpi, + m_displayMetricsScaledDensity, + m_displayMetricsDensity); + } + }); + m_qtThread.post(new Runnable() { + @Override + public void run() { + startQtApplication(); + } + }); + waitForServiceSetup(); m_started = true; } - return res; + return res[0]; } public static void setApplicationDisplayMetrics(int screenWidthPixels, @@ -348,8 +406,9 @@ public class QtNative // application methods - public static native void startQtApplication(String params, String env); - public static native boolean startQtAndroidPlugin(); + public static native boolean startQtAndroidPlugin(String params, String env); + public static native void startQtApplication(); + public static native void waitForServiceSetup(); public static native void quitQtCoreApplication(); public static native void quitQtAndroidPlugin(); public static native void terminateQt(); @@ -787,13 +846,13 @@ public class QtNative }); } - private static void hideSplashScreen() + private static void hideSplashScreen(final int duration) { runAction(new Runnable() { @Override public void run() { if (m_activityDelegate != null) - m_activityDelegate.hideSplashScreen(); + m_activityDelegate.hideSplashScreen(duration); } }); } @@ -881,4 +940,9 @@ public class QtNative private static native void setNativeActivity(Activity activity); private static native void setNativeService(Service service); + // activity methods + + // service methods + public static native IBinder onBind(Intent intent); + // service methods } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java b/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java index ff3bf19383..4a732f7f7f 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java @@ -45,6 +45,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; public class QtNativeLibrariesDir { + public static final String systemLibrariesDir = "/system/lib/"; public static String nativeLibrariesDir(Context context) { String m_nativeLibraryDir = null; diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java index 035a65a84c..ae06fa6268 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java @@ -53,6 +53,7 @@ import android.net.LocalSocket; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.ResultReceiver; import android.text.method.MetaKeyKeyListener; import android.util.Base64; @@ -186,5 +187,16 @@ public class QtServiceDelegate public void onDestroy() { QtNative.quitQtCoreApplication(); + QtNative.terminateQt(); + QtNative.setService(null, null); + QtNative.m_qtThread.exit(); + System.exit(0); + } + + public IBinder onBind(Intent intent) + { + synchronized (this) { + return QtNative.onBind(intent); + } } } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtThread.java b/src/android/jar/src/org/qtproject/qt5/android/QtThread.java new file mode 100644 index 0000000000..975e787345 --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt5/android/QtThread.java @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2018 BogDan Vatra <bogdan@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Android port of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt5.android; + +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +public class QtThread { + private ArrayList<Runnable> m_pendingRunnables = new ArrayList<Runnable>(); + private boolean m_exit = false; + private Thread m_qtThread = new Thread(new Runnable() { + @Override + public void run() { + while (!m_exit) { + try { + ArrayList<Runnable> pendingRunnables; + synchronized (m_qtThread) { + if (m_pendingRunnables.size() == 0) + m_qtThread.wait(); + pendingRunnables = new ArrayList<Runnable>(m_pendingRunnables); + m_pendingRunnables.clear(); + } + for (Runnable runnable : pendingRunnables) + runnable.run(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }); + + QtThread() { + m_qtThread.setName("qtMainLoopThread"); + m_qtThread.start(); + } + + public void post(final Runnable runnable) { + synchronized (m_qtThread) { + m_pendingRunnables.add(runnable); + m_qtThread.notify(); + } + } + + public void run(final Runnable runnable) { + final Semaphore sem = new Semaphore(0); + synchronized (m_qtThread) { + m_pendingRunnables.add(new Runnable() { + @Override + public void run() { + runnable.run(); + sem.release(); + } + }); + m_qtThread.notify(); + } + try { + sem.acquire(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void exit() + { + m_exit = true; + synchronized (m_qtThread) { + m_qtThread.notify(); + } + try { + m_qtThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} 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 69f351033d..fb6f61e31e 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 @@ -84,6 +84,7 @@ 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"; @@ -92,6 +93,10 @@ public abstract class QtLoader { 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[] SYSTEM_APP_PATHS = {"/system/priv-app/", "/system/app/"}; + /// Ministro server parameter keys public static final String REQUIRED_MODULES_KEY = "required.modules"; public static final String APPLICATION_TITLE_KEY = "application.title"; @@ -106,7 +111,6 @@ public abstract class QtLoader { public static final String REPOSITORY_KEY = "repository"; // use this key to overwrite the default ministro repsitory public static final String ANDROID_THEMES_KEY = "android.themes"; // themes that your application uses - 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" @@ -210,11 +214,11 @@ 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") ) + 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")))); String libName = null; - if ( m_contextInfo.metaData.containsKey("android.app.lib_name") ) { + if (m_contextInfo.metaData.containsKey("android.app.lib_name")) { libName = m_contextInfo.metaData.getString("android.app.lib_name"); loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function } @@ -239,10 +243,6 @@ public abstract class QtLoader { QtApplication.setQtContextDelegate(m_delegateClass, qtLoader); - // now load the application library so it's accessible from this class loader - if (libName != null) - System.loadLibrary(libName); - Method startAppMethod=qtLoader.getClass().getMethod("startApplication"); if (!(Boolean)startAppMethod.invoke(qtLoader)) throw new Exception(""); @@ -408,13 +408,9 @@ public abstract class QtLoader { } } - private void extractBundledPluginsAndImports(String pluginsPrefix) + private void extractBundledPluginsAndImports(String pluginsPrefix, String libsDir) throws IOException { - ArrayList<String> libs = new ArrayList<String>(); - - String libsDir = m_context.getApplicationInfo().nativeLibraryDir + "/"; - long packageVersion = -1; try { PackageInfo packageInfo = m_context.getPackageManager().getPackageInfo(m_context.getPackageName(), 0); @@ -530,6 +526,35 @@ public abstract class QtLoader { && m_contextInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) { ArrayList<String> libraryList = new ArrayList<String>(); + boolean apkDeployFromSystem = false; + String apkPath = m_context.getApplicationInfo().publicSourceDir; + File apkFile = new File(apkPath); + if (apkFile.exists() && Arrays.asList(SYSTEM_APP_PATHS).contains(apkFile.getParentFile().getAbsolutePath() + "/")) + apkDeployFromSystem = true; + + String libsDir = null; + if (apkDeployFromSystem) { + String systemLibsPrefix = SYSTEM_LIB_PATH; + if (m_contextInfo.metaData.containsKey("android.app.system_libs_prefix")) { + systemLibsPrefix = m_contextInfo.metaData.getString("android.app.system_libs_prefix"); + } else { + Log.e(QtApplication.QtTAG, "It looks like app deployed as system app. " + + "It may be necessary to specify path to system lib directory using " + + "android.app.system_libs_prefix metadata variable in your AndroidManifest.xml"); + 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; + } else { + String nativeLibraryPrefix = m_context.getApplicationInfo().nativeLibraryDir + "/"; + File nativeLibraryDir = new File(nativeLibraryPrefix); + if (nativeLibraryDir.exists() && nativeLibraryDir.isDirectory() && nativeLibraryDir.list().length > 0) + libsDir = nativeLibraryPrefix; + } + + if (apkDeployFromSystem && libsDir == null) + throw new Exception(""); String localPrefix = "/data/local/tmp/qt/"; if (m_contextInfo.metaData.containsKey("android.app.libs_prefix")) @@ -540,35 +565,33 @@ public abstract class QtLoader { boolean bundlingQtLibs = false; if (m_contextInfo.metaData.containsKey("android.app.bundle_local_qt_libs") && m_contextInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) { - localPrefix = m_context.getApplicationInfo().dataDir + "/"; + File dataDir = new File(m_context.getApplicationInfo().dataDir); + localPrefix = dataDir.getCanonicalPath() + "/"; pluginsPrefix = localPrefix + "qt-reserved-files/"; + + if (libsDir == null) + throw new Exception(""); + cleanOldCacheIfNecessary(localPrefix, pluginsPrefix); - extractBundledPluginsAndImports(pluginsPrefix); + extractBundledPluginsAndImports(pluginsPrefix, libsDir); + bundlingQtLibs = true; } if (m_qtLibs != null) { - for (int i=0;i<m_qtLibs.length;i++) { - libraryList.add(localPrefix - + "lib/lib" - + m_qtLibs[i] - + ".so"); - } + String libPrefix = apkDeployFromSystem ? libsDir + "lib" : localPrefix + "lib/lib"; + for (int i = 0; i < m_qtLibs.length; i++) + libraryList.add(libPrefix + m_qtLibs[i] + ".so"); } if (m_contextInfo.metaData.containsKey("android.app.load_local_libs")) { String[] extraLibs = m_contextInfo.metaData.getString("android.app.load_local_libs").split(":"); for (String lib : extraLibs) { - if (lib.length() > 0) { - if (lib.startsWith("lib/")) - libraryList.add(localPrefix + lib); - else - libraryList.add(pluginsPrefix + lib); - } - } + if (lib.length() > 0) + libraryList.add((lib.startsWith("lib/") ? localPrefix : pluginsPrefix) + lib); + } } - String dexPaths = new String(); String pathSeparator = System.getProperty("path.separator", ":"); if (!bundlingQtLibs && m_contextInfo.metaData.containsKey("android.app.load_local_jars")) { diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml index 066ec0a63c..62e9d0f11c 100644 --- a/src/android/templates/AndroidManifest.xml +++ b/src/android/templates/AndroidManifest.xml @@ -30,6 +30,8 @@ <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_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 --> + <!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> --> <!-- Messages maps --> <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/> <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/> |