diff options
Diffstat (limited to 'src/android/jar/src/org/qtproject/qt5/android')
4 files changed, 201 insertions, 53 deletions
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 0e28b964e8..6b8577116e 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -921,6 +921,7 @@ public class QtActivityDelegate public void onTerminate() { QtNative.terminateQt(); + QtNative.m_qtThread.exit(); } public void onCreate(Bundle savedInstanceState) @@ -1076,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 1cf3bca5f7..3db3453263 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -98,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() { @@ -164,55 +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()); + for (String libName : libraries) { 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) { + 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) { + } + } + 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) @@ -293,7 +303,7 @@ public class QtNative } public static boolean startApplication(String params, - String environment, + final String environment, String mainLibrary, String nativeLibraryDir) throws Exception { @@ -317,23 +327,42 @@ public class QtNative 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, @@ -377,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(); 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 195ec376c9..ae06fa6268 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java @@ -187,6 +187,10 @@ 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) 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(); + } + } +} |