summaryrefslogtreecommitdiffstats
path: root/src/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/android')
-rw-r--r--src/android/jar/bundledjar.pro3
-rw-r--r--src/android/jar/distributedjar.pro2
-rw-r--r--src/android/jar/jar.pri26
-rw-r--r--src/android/jar/jar.pro31
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java37
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java156
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java1
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java12
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtThread.java112
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java79
-rw-r--r--src/android/templates/AndroidManifest.xml2
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"/>