summaryrefslogtreecommitdiffstats
path: root/src/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/android')
-rw-r--r--src/android/accessibility/accessibility.pro2
-rw-r--r--src/android/accessibility/jar/AndroidManifest.xml7
-rw-r--r--src/android/accessibility/jar/bundledjar.pro3
-rw-r--r--src/android/accessibility/jar/distributedjar.pro2
-rw-r--r--src/android/accessibility/jar/jar.pri15
-rw-r--r--src/android/accessibility/jar/jar.pro2
-rw-r--r--src/android/android.pro2
-rw-r--r--src/android/jar/jar.pri5
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java64
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java231
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtEditText.java34
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java34
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtLayout.java34
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java113
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java206
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java42
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu.java66
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu14.java69
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java190
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtSurface.java37
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java (renamed from src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java)34
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java (renamed from src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java)34
-rw-r--r--src/android/java/res/values-ro/strings.xml1
-rw-r--r--src/android/java/res/values/strings.xml1
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java670
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java184
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java21
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java671
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtService.java153
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java77
-rw-r--r--src/android/templates/AndroidManifest.xml27
-rw-r--r--src/android/templates/res/values/libs.xml2
32 files changed, 1813 insertions, 1220 deletions
diff --git a/src/android/accessibility/accessibility.pro b/src/android/accessibility/accessibility.pro
deleted file mode 100644
index df5846945d..0000000000
--- a/src/android/accessibility/accessibility.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = jar
diff --git a/src/android/accessibility/jar/AndroidManifest.xml b/src/android/accessibility/jar/AndroidManifest.xml
deleted file mode 100644
index dc8343a55a..0000000000
--- a/src/android/accessibility/jar/AndroidManifest.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- android:versionCode="1"
- android:versionName="1.0"
- package="org.qtproject.qt5.android.accessibility">
- <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
-</manifest>
diff --git a/src/android/accessibility/jar/bundledjar.pro b/src/android/accessibility/jar/bundledjar.pro
deleted file mode 100644
index 85ba810310..0000000000
--- a/src/android/accessibility/jar/bundledjar.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TARGET = QtAndroidAccessibility-bundled
-CONFIG += bundled_jar_file
-include(jar.pri)
diff --git a/src/android/accessibility/jar/distributedjar.pro b/src/android/accessibility/jar/distributedjar.pro
deleted file mode 100644
index d161cf0cf6..0000000000
--- a/src/android/accessibility/jar/distributedjar.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = QtAndroidAccessibility
-include(jar.pri)
diff --git a/src/android/accessibility/jar/jar.pri b/src/android/accessibility/jar/jar.pri
deleted file mode 100644
index 3ae9fed59d..0000000000
--- a/src/android/accessibility/jar/jar.pri
+++ /dev/null
@@ -1,15 +0,0 @@
-CONFIG += java
-DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
-API_VERSION = android-16
-
-PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/accessibility
-
-JAVACLASSPATH += $$PWD/src/ \
- $$DESTDIR/QtAndroid-bundled.jar
-JAVASOURCES += \
- $$PATHPREFIX/QtAccessibilityDelegate.java \
- $$PATHPREFIX/QtNativeAccessibility.java
-
-# install
-target.path = $$[QT_INSTALL_PREFIX]/jar
-INSTALLS += target \ No newline at end of file
diff --git a/src/android/accessibility/jar/jar.pro b/src/android/accessibility/jar/jar.pro
deleted file mode 100644
index 8d19c1b7d6..0000000000
--- a/src/android/accessibility/jar/jar.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS += bundledjar.pro distributedjar.pro
diff --git a/src/android/android.pro b/src/android/android.pro
index b17dd15cd4..1174084591 100644
--- a/src/android/android.pro
+++ b/src/android/android.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS = jar java templates accessibility
+SUBDIRS = jar java templates
diff --git a/src/android/jar/jar.pri b/src/android/jar/jar.pri
index a962af18ab..58caacb837 100644
--- a/src/android/jar/jar.pri
+++ b/src/android/jar/jar.pri
@@ -6,6 +6,8 @@ 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 \
@@ -15,8 +17,7 @@ JAVASOURCES += \
$$PATHPREFIX/QtNativeLibrariesDir.java \
$$PATHPREFIX/QtSurface.java \
$$PATHPREFIX/ExtractStyle.java \
- $$PATHPREFIX/QtPopupMenu.java \
- $$PATHPREFIX/QtPopupMenu14.java
+ $$PATHPREFIX/QtServiceDelegate.java
# install
target.path = $$[QT_INSTALL_PREFIX]/jar
diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
index 22e2c7a85b..3f74383a82 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java
@@ -1,31 +1,37 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -264,6 +270,7 @@ public class ExtractStyle {
Context m_context;
final int defaultBackgroundColor;
final int defaultTextColor;
+ final boolean m_minimal;
class SimpleJsonWriter
{
@@ -985,7 +992,7 @@ public class ExtractStyle {
public JSONObject getDrawable(Object drawable, String filename, Rect padding)
{
- if (drawable == null)
+ if (drawable == null || m_minimal)
return null;
DrawableCache dc = m_drawableCache.get(filename);
@@ -1820,11 +1827,7 @@ public class ExtractStyle {
jsonWriter.name("simple_spinner_item").value(extractItemStyle(android.R.layout.simple_spinner_item, "simple_spinner_item", -1));
jsonWriter.name("simple_spinner_dropdown_item").value(extractItemStyle(android.R.layout.simple_spinner_dropdown_item, "simple_spinner_dropdown_item",android.R.style.TextAppearance_Large));
jsonWriter.name("simple_dropdown_item_1line").value(extractItemStyle(android.R.layout.simple_dropdown_item_1line, "simple_dropdown_item_1line",android.R.style.TextAppearance_Large));
- if (Build.VERSION.SDK_INT > 10) {
- Class<?> layoutClass = Class.forName("android.R$layout");
- int styleId = layoutClass.getDeclaredField("simple_selectable_list_item").getInt(null);
- jsonWriter.name("simple_selectable_list_item").value(extractItemStyle(styleId, "simple_selectable_list_item",android.R.style.TextAppearance_Large));
- }
+ jsonWriter.name("simple_selectable_list_item").value(extractItemStyle(android.R.layout.simple_selectable_list_item, "simple_selectable_list_item",android.R.style.TextAppearance_Large));
} catch (Exception e) {
e.printStackTrace();
}
@@ -1991,9 +1994,10 @@ public class ExtractStyle {
return json;
}
- public ExtractStyle(Context context, String extractPath)
+ public ExtractStyle(Context context, String extractPath, boolean minimal)
{
// Log.i(MinistroService.TAG, "Extract " + extractPath);
+ m_minimal = minimal;
m_extractPath = extractPath + "/";
new File(m_extractPath).mkdirs();
// MinistroActivity.nativeChmode(m_extractPath, 0755);
@@ -2025,9 +2029,7 @@ public class ExtractStyle {
extractProgressBar(jsonWriter, "progressBarStyleSmall", null);
extractProgressBar(jsonWriter, "progressBarStyle", null);
extractAbsSeekBar(jsonWriter, "seekBarStyle", "QSlider");
- if (Build.VERSION.SDK_INT > 13) {
- extractSwitch(jsonWriter, "switchStyle", null);
- }
+ extractSwitch(jsonWriter, "switchStyle", null);
extractCompoundButton(jsonWriter, "checkboxStyle", "QCheckBox");
jsonWriter.name("editTextStyle").value(extractTextAppearanceInformations("editTextStyle", "QLineEdit", null, -1));
extractCompoundButton(jsonWriter, "radioButtonStyle", "QRadioButton");
@@ -2037,15 +2039,13 @@ public class ExtractStyle {
jsonWriter.name("listSeparatorTextViewStyle").value(extractTextAppearanceInformations("listSeparatorTextViewStyle", null, null, -1));
extractItemsStyle(jsonWriter);
extractCompoundButton(jsonWriter, "buttonStyleToggle", null);
- if (Build.VERSION.SDK_INT > 10) {
- extractCalendar(jsonWriter, "calendarViewStyle", "QCalendarWidget");
- extractToolBar(jsonWriter, "actionBarStyle", "QToolBar");
- jsonWriter.name("actionButtonStyle").value(extractTextAppearanceInformations("actionButtonStyle", "QToolButton", null, -1));
- jsonWriter.name("actionBarTabTextStyle").value(extractTextAppearanceInformations("actionBarTabTextStyle", null, null, -1));
- jsonWriter.name("actionBarTabStyle").value(extractTextAppearanceInformations("actionBarTabStyle", null, null, -1));
- jsonWriter.name("actionOverflowButtonStyle").value(extractImageViewInformations("actionOverflowButtonStyle", null));
- extractTabBar(jsonWriter, "actionBarTabBarStyle", "QTabBar");
- }
+ extractCalendar(jsonWriter, "calendarViewStyle", "QCalendarWidget");
+ extractToolBar(jsonWriter, "actionBarStyle", "QToolBar");
+ jsonWriter.name("actionButtonStyle").value(extractTextAppearanceInformations("actionButtonStyle", "QToolButton", null, -1));
+ jsonWriter.name("actionBarTabTextStyle").value(extractTextAppearanceInformations("actionBarTabTextStyle", null, null, -1));
+ jsonWriter.name("actionBarTabStyle").value(extractTextAppearanceInformations("actionBarTabStyle", null, null, -1));
+ jsonWriter.name("actionOverflowButtonStyle").value(extractImageViewInformations("actionOverflowButtonStyle", null));
+ extractTabBar(jsonWriter, "actionBarTabBarStyle", "QTabBar");
} catch (Exception e) {
e.printStackTrace();
}
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 21a9d498df..656dbdda45 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -1,32 +1,38 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -42,6 +48,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.graphics.Rect;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
@@ -68,6 +75,8 @@ import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.view.ViewTreeObserver;
+import android.widget.ImageView;
+import android.widget.PopupMenu;
import java.io.BufferedReader;
import java.io.DataOutputStream;
@@ -80,6 +89,8 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
+import org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate;
+
public class QtActivityDelegate
{
private Activity m_activity = null;
@@ -102,6 +113,7 @@ public class QtActivityDelegate
private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
private static final String EXTRACT_STYLE_KEY = "extract.android.style";
+ private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option";
private static String m_environmentVariables = null;
private static String m_applicationParameters = null;
@@ -118,6 +130,8 @@ public class QtActivityDelegate
private HashMap<Integer, QtSurface> m_surfaces = null;
private HashMap<Integer, View> m_nativeViews = null;
private QtLayout m_layout = null;
+ private ImageView m_splashScreen = null;
+ private boolean m_splashScreenSticky = false;
private QtEditText m_editText = null;
private InputMethodManager m_imm = null;
private boolean m_quitApp = true;
@@ -140,14 +154,13 @@ public class QtActivityDelegate
m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
try {
if (Build.VERSION.SDK_INT >= 19) {
- int flags = View.class.getDeclaredField("SYSTEM_UI_FLAG_HIDE_NAVIGATION").getInt(null);
- flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_STABLE").getInt(null);
- flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION").getInt(null);
- flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN").getInt(null);
- flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_FULLSCREEN").getInt(null);
+ int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
flags |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null);
- Method m = View.class.getMethod("setSystemUiVisibility", int.class);
- m.invoke(m_activity.getWindow().getDecorView(), flags | View.INVISIBLE);
+ m_activity.getWindow().getDecorView().setSystemUiVisibility(flags | View.INVISIBLE);
}
} catch (Exception e) {
e.printStackTrace();
@@ -155,15 +168,7 @@ public class QtActivityDelegate
} else {
m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
- if (Build.VERSION.SDK_INT >= 14) {
- try {
- int ui_flag_visible = View.class.getDeclaredField("SYSTEM_UI_FLAG_VISIBLE").getInt(null);
- Method m = View.class.getMethod("setSystemUiVisibility", int.class);
- m.invoke(m_activity.getWindow().getDecorView(), ui_flag_visible);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
+ m_activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
m_layout.requestLayout();
}
@@ -293,8 +298,7 @@ public class QtActivityDelegate
imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
break;
case EnterKeyPrevious:
- if (Build.VERSION.SDK_INT > 10)
- imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
+ imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
break;
}
@@ -307,7 +311,7 @@ public class QtActivityDelegate
| android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
}
- if (Build.VERSION.SDK_INT > 10 && (inputHints & ImhHiddenText) != 0)
+ if ((inputHints & ImhHiddenText) != 0)
inputType |= 0x10 /* TYPE_NUMBER_VARIATION_PASSWORD */;
} else if ((inputHints & ImhDialableCharactersOnly) != 0) {
inputType = android.text.InputType.TYPE_CLASS_PHONE;
@@ -485,11 +489,19 @@ public class QtActivityDelegate
continue;
try {
- @SuppressWarnings("rawtypes")
- Class<?> initClass = classLoader.loadClass(className);
- Object staticInitDataObject = initClass.newInstance(); // create an instance
- Method m = initClass.getMethod("setActivity", Activity.class, Object.class);
- m.invoke(staticInitDataObject, m_activity, this);
+ Class<?> initClass = classLoader.loadClass(className);
+ Object staticInitDataObject = initClass.newInstance(); // create an instance
+ try {
+ Method m = initClass.getMethod("setActivity", Activity.class, Object.class);
+ m.invoke(staticInitDataObject, m_activity, this);
+ } catch (Exception e) {
+ }
+
+ try {
+ Method m = initClass.getMethod("setContext", Context.class);
+ m.invoke(staticInitDataObject, (Context)m_activity);
+ } catch (Exception e) {
+ }
} catch (Exception e) {
e.printStackTrace();
}
@@ -505,7 +517,8 @@ public class QtActivityDelegate
if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) {
String path = loaderParams.getString(EXTRACT_STYLE_KEY);
- new ExtractStyle(m_activity, path);
+ new ExtractStyle(m_activity, path, loaderParams.containsKey(EXTRACT_STYLE_MINIMAL_KEY) &&
+ loaderParams.getBoolean(EXTRACT_STYLE_MINIMAL_KEY));
}
try {
@@ -518,13 +531,7 @@ public class QtActivityDelegate
m_super_onConfigurationChanged = m_activity.getClass().getMethod("super_onConfigurationChanged", Configuration.class);
m_super_onActivityResult = m_activity.getClass().getMethod("super_onActivityResult", Integer.TYPE, Integer.TYPE, Intent.class);
m_super_onWindowFocusChanged = m_activity.getClass().getMethod("super_onWindowFocusChanged", Boolean.TYPE);
- if (Build.VERSION.SDK_INT >= 12) {
- try {
- m_super_dispatchGenericMotionEvent = m_activity.getClass().getMethod("super_dispatchGenericMotionEvent", MotionEvent.class);
- } catch (Exception e) {
- }
- }
-
+ m_super_dispatchGenericMotionEvent = m_activity.getClass().getMethod("super_dispatchGenericMotionEvent", MotionEvent.class);
} catch (Exception e) {
e.printStackTrace();
return false;
@@ -540,10 +547,8 @@ public class QtActivityDelegate
+ "\tNECESSITAS_API_LEVEL=" + necessitasApiLevel
+ "\tHOME=" + m_activity.getFilesDir().getAbsolutePath()
+ "\tTMPDIR=" + m_activity.getFilesDir().getAbsolutePath();
- if (Build.VERSION.SDK_INT < 14)
- additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Droid Sans;Droid Sans Fallback";
- else
- additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Roboto;Droid Sans;Droid Sans Fallback";
+
+ additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Roboto;Droid Sans;Droid Sans Fallback";
additionalEnvironmentVariables += getAppIconSize(activity);
@@ -881,6 +886,22 @@ public class QtActivityDelegate
};
}
m_layout = new QtLayout(m_activity, startApplication);
+
+ try {
+ ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA);
+ if (info.metaData.containsKey("android.app.splash_screen_drawable")) {
+ m_splashScreenSticky = info.metaData.containsKey("android.app.splash_screen_sticky") && info.metaData.getBoolean("android.app.splash_screen_sticky");
+ int id = info.metaData.getInt("android.app.splash_screen_drawable");
+ m_splashScreen = new ImageView(m_activity);
+ m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(id));
+ m_splashScreen.setScaleType(ImageView.ScaleType.FIT_XY);
+ m_splashScreen.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ m_layout.addView(m_splashScreen);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
m_editText = new QtEditText(m_activity, this);
m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE);
m_surfaces = new HashMap<Integer, QtSurface>();
@@ -922,23 +943,18 @@ public class QtActivityDelegate
});
}
+ public void hideSplashScreen()
+ {
+ if (m_splashScreen == null)
+ return;
+ m_layout.removeView(m_splashScreen);
+ m_splashScreen = null;
+ }
+
+
public void initializeAccessibility()
{
- // Initialize accessibility
- try {
- final String a11yDelegateClassName = "org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate";
- Class<?> qtDelegateClass = Class.forName(a11yDelegateClassName);
- Constructor constructor = qtDelegateClass.getConstructor(android.app.Activity.class,
- android.view.ViewGroup.class,
- this.getClass());
- Object accessibilityDelegate = constructor.newInstance(m_activity, m_layout, this);
- } catch (ClassNotFoundException e) {
- // Class not found is fine since we are compatible with Android API < 16, but the function will
- // only be available with that API level.
- } catch (Exception e) {
- // Unknown exception means something went wrong.
- Log.w("Qt A11y", "Unknown exception: " + e.toString());
- }
+ new QtAccessibilityDelegate(m_activity, m_layout, this);
}
public void onWindowFocusChanged(boolean hasFocus) {
@@ -958,6 +974,7 @@ public class QtActivityDelegate
} catch (Exception e) {
e.printStackTrace();
}
+
int rotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
if (rotation != m_currentRotation) {
QtNative.handleOrientationChanged(rotation, m_nativeOrientation);
@@ -970,6 +987,7 @@ public class QtActivityDelegate
{
if (m_quitApp) {
QtNative.terminateQt();
+ QtNative.setActivity(null, null);
if (m_debuggerProcess != null)
m_debuggerProcess.destroy();
System.exit(0);// FIXME remove it or find a better way
@@ -1152,17 +1170,9 @@ public class QtActivityDelegate
public void resetOptionsMenu()
{
- if (Build.VERSION.SDK_INT > 10) {
- try {
- Activity.class.getMethod("invalidateOptionsMenu").invoke(m_activity);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- else
- if (m_optionsMenuIsVisible)
- m_activity.closeOptionsMenu();
+ m_activity.invalidateOptionsMenu();
}
+
private boolean m_contextMenuVisible = false;
public void onCreateContextMenu(ContextMenu menu,
View v,
@@ -1198,15 +1208,22 @@ public class QtActivityDelegate
m_layout.postDelayed(new Runnable() {
@Override
public void run() {
- if (Build.VERSION.SDK_INT < 11 || w <= 0 || h <= 0) {
- m_activity.openContextMenu(m_layout);
- } else if (Build.VERSION.SDK_INT < 14) {
- m_layout.setLayoutParams(m_editText, new QtLayout.LayoutParams(w, h, x, y), false);
- QtPopupMenu.getInstance().showMenu(m_editText);
- } else {
- m_layout.setLayoutParams(m_editText, new QtLayout.LayoutParams(w, h, x, y), false);
- QtPopupMenu14.getInstance().showMenu(m_editText);
- }
+ m_layout.setLayoutParams(m_editText, new QtLayout.LayoutParams(w, h, x, y), false);
+ PopupMenu popup = new PopupMenu(m_activity, m_editText);
+ QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu());
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem menuItem) {
+ return QtActivityDelegate.this.onContextItemSelected(menuItem);
+ }
+ });
+ popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
+ @Override
+ public void onDismiss(PopupMenu popupMenu) {
+ QtActivityDelegate.this.onContextMenuClosed(popupMenu.getMenu());
+ }
+ });
+ popup.show();
}
}, 100);
}
@@ -1216,46 +1233,14 @@ public class QtActivityDelegate
m_activity.closeContextMenu();
}
- private boolean hasPermanentMenuKey()
- {
- try {
- return Build.VERSION.SDK_INT < 11 || (Build.VERSION.SDK_INT >= 14 &&
- (Boolean)ViewConfiguration.class.getMethod("hasPermanentMenuKey").invoke(ViewConfiguration.get(m_activity)));
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
-
- private Object getActionBar()
- {
- try {
- return Activity.class.getMethod("getActionBar").invoke(m_activity);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
private void setActionBarVisibility(boolean visible)
{
- if (hasPermanentMenuKey() || !visible) {
- if (Build.VERSION.SDK_INT > 10 && getActionBar() != null) {
- try {
- Class.forName("android.app.ActionBar").getMethod("hide").invoke(getActionBar());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- } else {
- if (Build.VERSION.SDK_INT > 10 && getActionBar() != null)
- try {
- Class.forName("android.app.ActionBar").getMethod("show").invoke(getActionBar());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
+ if (m_activity.getActionBar() == null)
+ return;
+ if (ViewConfiguration.get(m_activity).hasPermanentMenuKey() || !visible)
+ m_activity.getActionBar().hide();
+ else
+ m_activity.getActionBar().show();
}
public void insertNativeView(int id, View view, int x, int y, int w, int h) {
@@ -1311,6 +1296,8 @@ public class QtActivityDelegate
m_layout.addView(surface, surfaceCount);
m_surfaces.put(id, surface);
+ if (!m_splashScreenSticky)
+ hideSplashScreen();
}
public void setSurfaceGeometry(int id, int x, int y, int w, int h) {
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java b/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java
index c01b0693d9..e6da5482ca 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java
@@ -1,32 +1,38 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
index 1536d60faa..7c621a11e2 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
@@ -1,32 +1,38 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtLayout.java b/src/android/jar/src/org/qtproject/qt5/android/QtLayout.java
index 5181cc7e11..f22b8176c8 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtLayout.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtLayout.java
@@ -1,32 +1,38 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java
index f9ece74de3..a3bbff4e1a 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java
@@ -1,31 +1,37 @@
/****************************************************************************
**
** Copyright (C) 2016 BogDan Vatra <bogdan@kde.org>
- ** Contact: http://www.qt.io/licensing/
+ ** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
- ** $QT_BEGIN_LICENSE:LGPL21$
+ ** $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 http://www.qt.io/terms-conditions. For further
- ** information use the contact form at http://www.qt.io/contact-us.
+ ** 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 2.1 or version 3 as published by the Free
- ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
- ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
- ** following information to ensure the GNU Lesser General Public License
- ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
- ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ ** 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.
**
- ** As a special exception, The Qt Company gives you certain additional
- ** rights. These rights are described in The Qt Company LGPL Exception
- ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ ** 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$
**
@@ -100,14 +106,12 @@ public class QtMessageDialogHelper
if (m_icon == 0)
return null;
- if (Build.VERSION.SDK_INT > 10) {
- try {
- TypedValue typedValue = new TypedValue();
- m_theme.resolveAttribute(Class.forName("android.R$attr").getDeclaredField("alertDialogIcon").getInt(null), typedValue, true);
- return m_activity.getResources().getDrawable(typedValue.resourceId);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ try {
+ TypedValue typedValue = new TypedValue();
+ m_theme.resolveAttribute(android.R.attr.alertDialogIcon, typedValue, true);
+ return m_activity.getResources().getDrawable(typedValue.resourceId);
+ } catch (Exception e) {
+ e.printStackTrace();
}
// Information, Warning, Critical, Question
@@ -115,7 +119,7 @@ public class QtMessageDialogHelper
{
case 1: // Information
try {
- return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_info").getInt(null));
+ return m_activity.getResources().getDrawable(android.R.drawable.ic_dialog_info);
} catch (Exception e) {
e.printStackTrace();
}
@@ -129,14 +133,14 @@ public class QtMessageDialogHelper
// break;
case 3: // Critical
try {
- return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_alert").getInt(null));
+ return m_activity.getResources().getDrawable(android.R.drawable.ic_dialog_alert);
} catch (Exception e) {
e.printStackTrace();
}
break;
case 4: // Question
try {
- return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_menu_help").getInt(null));
+ return m_activity.getResources().getDrawable(android.R.drawable.ic_menu_help);
} catch (Exception e) {
e.printStackTrace();
}
@@ -286,15 +290,11 @@ public class QtMessageDialogHelper
for (ButtonStruct button: m_buttonsList)
{
Button bv;
- if (Build.VERSION.SDK_INT > 10) {
- try {
- bv = new Button(m_activity, null, Class.forName("android.R$attr").getDeclaredField("borderlessButtonStyle").getInt(null));
- } catch (Exception e) {
- bv = new Button(m_activity);
- e.printStackTrace();
- }
- } else {
+ try {
+ bv = new Button(m_activity, null, Class.forName("android.R$attr").getDeclaredField("borderlessButtonStyle").getInt(null));
+ } catch (Exception e) {
bv = new Button(m_activity);
+ e.printStackTrace();
}
bv.setText(button.m_text);
@@ -303,14 +303,12 @@ public class QtMessageDialogHelper
{
LinearLayout.LayoutParams layout = null;
View spacer = new View(m_activity);
- if (Build.VERSION.SDK_INT > 10) {
- try {
- layout = new LinearLayout.LayoutParams(1, RelativeLayout.LayoutParams.MATCH_PARENT);
- spacer.setBackgroundDrawable(getStyledDrawable("dividerVertical"));
- buttonsLayout.addView(spacer, layout);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ try {
+ layout = new LinearLayout.LayoutParams(1, RelativeLayout.LayoutParams.MATCH_PARENT);
+ spacer.setBackgroundDrawable(getStyledDrawable("dividerVertical"));
+ buttonsLayout.addView(spacer, layout);
+ } catch (Exception e) {
+ e.printStackTrace();
}
}
LinearLayout.LayoutParams layout = null;
@@ -319,23 +317,21 @@ public class QtMessageDialogHelper
firstButton = false;
}
- if (Build.VERSION.SDK_INT > 10) {
- try {
- View horizontalDevider = new View(m_activity);
- horizontalDevider.setId(id++);
- horizontalDevider.setBackgroundDrawable(getStyledDrawable("dividerHorizontal"));
- RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 1);
- relativeParams.setMargins(0, 10, 0, 0);
- if (lastView != null) {
- relativeParams.addRule(RelativeLayout.BELOW, lastView.getId());
- }
- else
- relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- dialogLayout.addView(horizontalDevider, relativeParams);
- lastView = horizontalDevider;
- } catch (Exception e) {
- e.printStackTrace();
+ try {
+ View horizontalDevider = new View(m_activity);
+ horizontalDevider.setId(id++);
+ horizontalDevider.setBackgroundDrawable(getStyledDrawable("dividerHorizontal"));
+ RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 1);
+ relativeParams.setMargins(0, 10, 0, 0);
+ if (lastView != null) {
+ relativeParams.addRule(RelativeLayout.BELOW, lastView.getId());
}
+ else
+ relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(horizontalDevider, relativeParams);
+ lastView = horizontalDevider;
+ } catch (Exception e) {
+ e.printStackTrace();
}
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (lastView != null) {
@@ -343,10 +339,7 @@ public class QtMessageDialogHelper
}
else
relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- if (Build.VERSION.SDK_INT < 11)
- relativeParams.setMargins(2, 12, 2, 4);
- else
- relativeParams.setMargins(2, 0, 2, 0);
+ relativeParams.setMargins(2, 0, 2, 0);
dialogLayout.addView(buttonsLayout, relativeParams);
}
scrollView.addView(dialogLayout);
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 e602a6deba..04b8e6a06f 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -1,32 +1,38 @@
/****************************************************************************
**
-** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 BogDan Vatra <bogdan@kde.org>
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -39,6 +45,7 @@ import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import android.app.Activity;
+import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -66,7 +73,9 @@ public class QtNative
{
private static Activity m_activity = null;
private static boolean m_activityPaused = false;
+ private static Service m_service = null;
private static QtActivityDelegate m_activityDelegate = null;
+ private static QtServiceDelegate m_serviceDelegate = null;
public static Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations
public static final String QtTAG = "Qt JAVA"; // string used for Log.x
@@ -85,6 +94,12 @@ public class QtNative
private static ClipboardManager m_clipboardManager = null;
private static Method m_checkSelfPermissionMethod = null;
private static Boolean m_tabletEventSupported = null;
+ private static final Runnable runPendingCppRunnablesRunnable = new Runnable() {
+ @Override
+ public void run() {
+ runPendingCppRunnables();
+ }
+ };
private static ClassLoader m_classLoader = null;
public static ClassLoader classLoader()
@@ -104,6 +119,14 @@ public class QtNative
}
}
+ public static Service service()
+ {
+ synchronized (m_mainActivityMutex) {
+ return m_service;
+ }
+ }
+
+
public static QtActivityDelegate activityDelegate()
{
synchronized (m_mainActivityMutex) {
@@ -111,6 +134,13 @@ public class QtNative
}
}
+ public static QtServiceDelegate serviceDelegate()
+ {
+ synchronized (m_mainActivityMutex) {
+ return m_serviceDelegate;
+ }
+ }
+
public static boolean openURL(String url, String mime)
{
boolean ok = true;
@@ -175,6 +205,14 @@ public class QtNative
}
}
+ public static void setService(Service qtMainService, QtServiceDelegate qtServiceDelegate)
+ {
+ synchronized (m_mainActivityMutex) {
+ m_service = qtMainService;
+ m_serviceDelegate = qtServiceDelegate;
+ }
+ }
+
public static void setApplicationState(int state)
{
synchronized (m_mainActivityMutex) {
@@ -205,14 +243,14 @@ public class QtNative
}
}
- private static void runQtOnUiThread(final long id)
+ private static void runPendingCppRunnablesOnUiThread()
{
- runAction(new Runnable() {
- @Override
- public void run() {
- QtNative.onAndroidUiThread(id);
- }
- });
+ synchronized (m_mainActivityMutex) {
+ if (!m_activityPaused && m_activity != null)
+ m_activity.runOnUiThread(runPendingCppRunnablesRunnable);
+ else
+ runAction(runPendingCppRunnablesRunnable);
+ }
}
private static void setViewVisibility(final View view, final boolean visible)
@@ -308,7 +346,11 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activity.finish();
+ quitQtAndroidPlugin();
+ if (m_activity != null)
+ m_activity.finish();
+ if (m_service != null)
+ m_service.stopSelf();
}
});
}
@@ -347,16 +389,14 @@ public class QtNative
if (m_tabletEventSupported == null)
m_tabletEventSupported = isTabletEventSupported();
- if (Build.VERSION.SDK_INT >= 14) {
- switch (event.getToolType(0)) {
- case MotionEvent.TOOL_TYPE_STYLUS:
- pointerType = 1; // QTabletEvent::Pen
- break;
- case MotionEvent.TOOL_TYPE_ERASER:
- pointerType = 3; // QTabletEvent::Eraser
- break;
- // TODO TOOL_TYPE_MOUSE
- }
+ switch (event.getToolType(0)) {
+ case MotionEvent.TOOL_TYPE_STYLUS:
+ pointerType = 1; // QTabletEvent::Pen
+ break;
+ case MotionEvent.TOOL_TYPE_ERASER:
+ pointerType = 3; // QTabletEvent::Eraser
+ break;
+ // TODO TOOL_TYPE_MOUSE
}
if (m_tabletEventSupported && pointerType != 0) {
@@ -446,7 +486,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.updateSelection(selStart, selEnd, candidatesStart, candidatesEnd);
+ if (m_activityDelegate != null)
+ m_activityDelegate.updateSelection(selStart, selEnd, candidatesStart, candidatesEnd);
}
});
}
@@ -461,7 +502,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
+ if (m_activityDelegate != null)
+ m_activityDelegate.showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
}
});
}
@@ -471,7 +513,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.resetSoftwareKeyboard();
+ if (m_activityDelegate != null)
+ m_activityDelegate.resetSoftwareKeyboard();
}
});
}
@@ -481,7 +524,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.hideSoftwareKeyboard();
+ if (m_activityDelegate != null)
+ m_activityDelegate.hideSoftwareKeyboard();
}
});
}
@@ -491,7 +535,9 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.setFullScreen(fullScreen);
+ if (m_activityDelegate != null) {
+ m_activityDelegate.setFullScreen(fullScreen);
+ }
updateWindow();
}
});
@@ -499,34 +545,44 @@ public class QtNative
private static void registerClipboardManager()
{
- final Semaphore semaphore = new Semaphore(0);
- runAction(new Runnable() {
- @Override
- public void run() {
- m_clipboardManager = (android.text.ClipboardManager) m_activity.getSystemService(Context.CLIPBOARD_SERVICE);
- semaphore.release();
+ if (m_service == null || m_activity != null) { // Avoid freezing if only service
+ final Semaphore semaphore = new Semaphore(0);
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_activity != null)
+ m_clipboardManager = (android.text.ClipboardManager) m_activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ semaphore.release();
+ }
+ });
+ try {
+ semaphore.acquire();
+ } catch (Exception e) {
+ e.printStackTrace();
}
- });
- try {
- semaphore.acquire();
- } catch (Exception e) {
- e.printStackTrace();
}
}
private static void setClipboardText(String text)
{
- m_clipboardManager.setText(text);
+ if (m_clipboardManager != null)
+ m_clipboardManager.setText(text);
}
private static boolean hasClipboardText()
{
- return m_clipboardManager.hasText();
+ if (m_clipboardManager != null)
+ return m_clipboardManager.hasText();
+ else
+ return false;
}
private static String getClipboardText()
{
- return m_clipboardManager.getText().toString();
+ if (m_clipboardManager != null)
+ return m_clipboardManager.getText().toString();
+ else
+ return "";
}
private static void openContextMenu(final int x, final int y, final int w, final int h)
@@ -534,7 +590,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.openContextMenu(x, y, w, h);
+ if (m_activityDelegate != null)
+ m_activityDelegate.openContextMenu(x, y, w, h);
}
});
}
@@ -544,7 +601,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.closeContextMenu();
+ if (m_activityDelegate != null)
+ m_activityDelegate.closeContextMenu();
}
});
}
@@ -554,7 +612,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.resetOptionsMenu();
+ if (m_activityDelegate != null)
+ m_activityDelegate.resetOptionsMenu();
}
});
}
@@ -564,7 +623,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activity.openOptionsMenu();
+ if (m_activity != null)
+ m_activity.openOptionsMenu();
}
});
}
@@ -601,7 +661,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.createSurface(id, onTop, x, y, w, h, imageDepth);
+ if (m_activityDelegate != null)
+ m_activityDelegate.createSurface(id, onTop, x, y, w, h, imageDepth);
}
});
}
@@ -611,7 +672,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.insertNativeView(id, view, x, y, w, h);
+ if (m_activityDelegate != null)
+ m_activityDelegate.insertNativeView(id, view, x, y, w, h);
}
});
}
@@ -621,7 +683,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.setSurfaceGeometry(id, x, y, w, h);
+ if (m_activityDelegate != null)
+ m_activityDelegate.setSurfaceGeometry(id, x, y, w, h);
}
});
}
@@ -631,7 +694,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.bringChildToFront(id);
+ if (m_activityDelegate != null)
+ m_activityDelegate.bringChildToFront(id);
}
});
}
@@ -641,7 +705,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.bringChildToBack(id);
+ if (m_activityDelegate != null)
+ m_activityDelegate.bringChildToBack(id);
}
});
}
@@ -651,7 +716,8 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.destroySurface(id);
+ if (m_activityDelegate != null)
+ m_activityDelegate.destroySurface(id);
}
});
}
@@ -666,6 +732,17 @@ public class QtNative
});
}
+ private static void hideSplashScreen()
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_activityDelegate != null)
+ m_activityDelegate.hideSplashScreen();
+ }
+ });
+ }
+
// screen methods
public static native void setDisplayMetrics(int screenWidthPixels,
int screenHeightPixels,
@@ -731,5 +808,8 @@ public class QtNative
public static native void onActivityResult(int requestCode, int resultCode, Intent data);
public static native void onNewIntent(Intent data);
- public static native void onAndroidUiThread(long id);
+ public static native void runPendingCppRunnables();
+
+ private static native void setNativeActivity(Activity activity);
+ private static native void setNativeService(Service service);
}
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 a7dd96d609..ff3bf19383 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java
@@ -1,32 +1,38 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
-** Contact: http://www.qt.io/licensing/
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -34,17 +40,17 @@
package org.qtproject.qt5.android;
-import android.app.Activity;
+import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
public class QtNativeLibrariesDir {
- public static String nativeLibrariesDir(Activity activity)
+ public static String nativeLibrariesDir(Context context)
{
String m_nativeLibraryDir = null;
try {
- ApplicationInfo ai = activity.getPackageManager().getApplicationInfo(activity.getPackageName(), 0);
- m_nativeLibraryDir = ai.nativeLibraryDir+"/";
+ ApplicationInfo ai = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
+ m_nativeLibraryDir = ai.nativeLibraryDir + "/";
} catch (NameNotFoundException e) {
e.printStackTrace();
}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu.java b/src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu.java
deleted file mode 100644
index d89b454b77..0000000000
--- a/src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Android port of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-package org.qtproject.qt5.android;
-
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.PopupMenu;
-
-public class QtPopupMenu {
- private QtPopupMenu() { }
-
- private static class QtPopupMenuHolder {
- private static final QtPopupMenu INSTANCE = new QtPopupMenu();
- }
-
- public static QtPopupMenu getInstance() {
- return QtPopupMenuHolder.INSTANCE;
- }
-
- public void showMenu(View anchor)
- {
- PopupMenu popup = new PopupMenu(QtNative.activity(), anchor);
- QtNative.activityDelegate().onCreatePopupMenu(popup.getMenu());
- popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem menuItem) {
- boolean res = QtNative.onContextItemSelected(menuItem.getItemId(), menuItem.isChecked());
- if (res)
- QtNative.activityDelegate().onContextMenuClosed(null);
- return res;
- }
- });
- popup.show();
- }
-}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu14.java b/src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu14.java
deleted file mode 100644
index edef682dec..0000000000
--- a/src/android/jar/src/org/qtproject/qt5/android/QtPopupMenu14.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Android port of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** 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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-package org.qtproject.qt5.android;
-
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.PopupMenu;
-
-public class QtPopupMenu14 {
- private QtPopupMenu14() { }
-
- private static class QtPopupMenu14Holder {
- private static final QtPopupMenu14 INSTANCE = new QtPopupMenu14();
- }
-
- public static QtPopupMenu14 getInstance() {
- return QtPopupMenu14Holder.INSTANCE;
- }
-
- public void showMenu(View anchor)
- {
- PopupMenu popup = new PopupMenu(QtNative.activity(), anchor);
- QtNative.activityDelegate().onCreatePopupMenu(popup.getMenu());
- popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem menuItem) {
- return QtNative.activityDelegate().onContextItemSelected(menuItem);
- }
- });
- popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
- @Override
- public void onDismiss(PopupMenu popupMenu) {
- QtNative.activityDelegate().onContextMenuClosed(popupMenu.getMenu());
- }
- });
- popup.show();
- }
-}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java
new file mode 100644
index 0000000000..5ac406c710
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 BogDan Vatra <bogdan@kde.org>
+** Copyright (C) 2016 The Qt Company Ltd.
+** 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 android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
+import android.graphics.drawable.ColorDrawable;
+import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.text.method.MetaKeyKeyListener;
+import android.util.Base64;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+public class QtServiceDelegate
+{
+ private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
+ private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
+ private static final String MAIN_LIBRARY_KEY = "main.library";
+ private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
+ private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
+ private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
+ private static final String APP_DISPLAY_METRIC_SCREEN_DESKTOP_KEY = "display.screen.desktop";
+ private static final String APP_DISPLAY_METRIC_SCREEN_XDPI_KEY = "display.screen.dpi.x";
+ private static final String APP_DISPLAY_METRIC_SCREEN_YDPI_KEY = "display.screen.dpi.y";
+ private static final String APP_DISPLAY_METRIC_SCREEN_DENSITY_KEY = "display.screen.density";
+
+ private Service m_service = null;
+ private String m_mainLib;
+ private static String m_environmentVariables = null;
+ private static String m_applicationParameters = null;
+
+ public boolean loadApplication(Service service, ClassLoader classLoader, Bundle loaderParams)
+ {
+ /// check parameters integrity
+ if (!loaderParams.containsKey(NATIVE_LIBRARIES_KEY)
+ || !loaderParams.containsKey(BUNDLED_LIBRARIES_KEY)) {
+ return false;
+ }
+
+ m_service = service;
+ QtNative.setService(m_service, this);
+ QtNative.setClassLoader(classLoader);
+
+ QtNative.setApplicationDisplayMetrics(10, 10, 10, 10, 120, 120, 1.0, 1.0);
+
+ if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) {
+ for (String className: loaderParams.getStringArray(STATIC_INIT_CLASSES_KEY)) {
+ if (className.length() == 0)
+ continue;
+ try {
+ Class<?> initClass = classLoader.loadClass(className);
+ Object staticInitDataObject = initClass.newInstance(); // create an instance
+ try {
+ Method m = initClass.getMethod("setService", Service.class, Object.class);
+ m.invoke(staticInitDataObject, m_service, this);
+ } catch (Exception e) {
+ }
+
+ try {
+ Method m = initClass.getMethod("setContext", Context.class);
+ m.invoke(staticInitDataObject, (Context)m_service);
+ } catch (Exception e) {
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ QtNative.loadQtLibraries(loaderParams.getStringArrayList(NATIVE_LIBRARIES_KEY));
+ ArrayList<String> libraries = loaderParams.getStringArrayList(BUNDLED_LIBRARIES_KEY);
+ QtNative.loadBundledLibraries(libraries, QtNativeLibrariesDir.nativeLibrariesDir(m_service));
+ m_mainLib = loaderParams.getString(MAIN_LIBRARY_KEY);
+
+ m_environmentVariables = loaderParams.getString(ENVIRONMENT_VARIABLES_KEY);
+ String additionalEnvironmentVariables = "QT_ANDROID_FONTS_MONOSPACE=Droid Sans Mono;Droid Sans;Droid Sans Fallback"
+ + "\tQT_ANDROID_FONTS_SERIF=Droid Serif"
+ + "\tHOME=" + m_service.getFilesDir().getAbsolutePath()
+ + "\tTMPDIR=" + m_service.getFilesDir().getAbsolutePath();
+ if (Build.VERSION.SDK_INT < 14)
+ additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Droid Sans;Droid Sans Fallback";
+ else
+ additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Roboto;Droid Sans;Droid Sans Fallback";
+
+ if (m_environmentVariables != null && m_environmentVariables.length() > 0)
+ m_environmentVariables = additionalEnvironmentVariables + "\t" + m_environmentVariables;
+ else
+ m_environmentVariables = additionalEnvironmentVariables;
+
+ if (loaderParams.containsKey(APPLICATION_PARAMETERS_KEY))
+ m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY);
+ else
+ m_applicationParameters = "";
+
+ return true;
+ }
+
+ public boolean startApplication()
+ {
+ // start application
+ try {
+ String nativeLibraryDir = QtNativeLibrariesDir.nativeLibrariesDir(m_service);
+ QtNative.startApplication(m_applicationParameters,
+ m_environmentVariables,
+ m_mainLib,
+ nativeLibraryDir);
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public void onDestroy()
+ {
+ QtNative.setService(null, null);
+ }
+}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java
index 74433d2b65..4d8abb2117 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java
@@ -1,32 +1,38 @@
/****************************************************************************
**
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -62,9 +68,6 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
else
getHolder().setFormat(PixelFormat.RGBA_8888);
- if (android.os.Build.VERSION.SDK_INT < 11)
- getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
-
setId(id);
m_gestureDetector =
new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
diff --git a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java
index 6f95675597..79caaf318e 100644
--- a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/accessibility/QtAccessibilityDelegate.java
@@ -1,31 +1,37 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
diff --git a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java b/src/android/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java
index bfda2d55b7..a83174377d 100644
--- a/src/android/accessibility/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/accessibility/QtNativeAccessibility.java
@@ -1,31 +1,37 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Android port of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
diff --git a/src/android/java/res/values-ro/strings.xml b/src/android/java/res/values-ro/strings.xml
index f88a442b35..fef52ad3bd 100644
--- a/src/android/java/res/values-ro/strings.xml
+++ b/src/android/java/res/values-ro/strings.xml
@@ -3,4 +3,5 @@
<string name="ministro_not_found_msg">Serviciul Ministro nu poate fi găsit.\nAplicaţia nu poate porni.</string>
<string name="ministro_needed_msg">Această aplicaţie necesită serviciul Ministro.\nDoriţi să-l instalaţi?</string>
<string name="fatal_error_msg">Aplicaţia dumneavoastră a întâmpinat o eroare fatală şi nu poate continua.</string>
+ <string name="unsupported_android_version">Versiune Android nesuportată.</string>
</resources>
diff --git a/src/android/java/res/values/strings.xml b/src/android/java/res/values/strings.xml
index fcc3eb097b..95b3385924 100644
--- a/src/android/java/res/values/strings.xml
+++ b/src/android/java/res/values/strings.xml
@@ -4,4 +4,5 @@
<string name="ministro_not_found_msg">Can\'t find Ministro service.\nThe application can\'t start.</string>
<string name="ministro_needed_msg">This application requires Ministro service. Would you like to install it?</string>
<string name="fatal_error_msg">Your application encountered a fatal error and cannot continue.</string>
+ <string name="unsupported_android_version">Unsupported Android version.</string>
</resources>
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index 9fc903af8e..573a28e44b 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2012-2013, BogDan Vatra <bogdan@kde.org>
+ Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
Contact: http://www.qt.io/licensing/
Commercial License Usage
@@ -36,47 +36,20 @@
package org.qtproject.qt5.android.bindings;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.FileOutputStream;
-import java.io.FileInputStream;
-import java.io.DataOutputStream;
-import java.io.DataInputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.kde.necessitas.ministro.IMinistro;
-import org.kde.necessitas.ministro.IMinistroCallback;
-
import android.app.Activity;
-import android.app.AlertDialog;
import android.app.Dialog;
-import android.content.ComponentName;
+import android.app.Fragment;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageInfo;
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
-import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.drawable.ColorDrawable;
-import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
import android.util.AttributeSet;
-import android.util.Log;
+import android.view.ActionMode;
+import android.view.ActionMode.Callback;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
@@ -84,68 +57,23 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
-import dalvik.system.DexClassLoader;
-
-//@ANDROID-11
-import android.app.Fragment;
-import android.view.ActionMode;
-import android.view.ActionMode.Callback;
-//@ANDROID-11
public class QtActivity extends Activity
{
- private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished
- private static final int MINISTRO_API_LEVEL = 5; // Ministro api level (check IMinistro.aidl file)
- private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin
- private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0
-
- private static final String ERROR_CODE_KEY = "error.code";
- private static final String ERROR_MESSAGE_KEY = "error.message";
- private static final String DEX_PATH_KEY = "dex.path";
- private static final String LIB_PATH_KEY = "lib.path";
- private static final String LOADER_CLASS_NAME_KEY = "loader.class.name";
- private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
- private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
- private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
- private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
- private static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id";
- private static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id";
- private static final String MAIN_LIBRARY_KEY = "main.library";
- private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
- private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
- private static final String EXTRACT_STYLE_KEY = "extract.android.style";
-
- /// Ministro server parameter keys
- private static final String REQUIRED_MODULES_KEY = "required.modules";
- private static final String APPLICATION_TITLE_KEY = "application.title";
- private static final String MINIMUM_MINISTRO_API_KEY = "minimum.ministro.api";
- private static final String MINIMUM_QT_VERSION_KEY = "minimum.qt.version";
- private static final String SOURCES_KEY = "sources"; // needs MINISTRO_API_LEVEL >=3 !!!
- // Use this key to specify any 3rd party sources urls
- // Ministro will download these repositories into their
- // own folders, check http://community.kde.org/Necessitas/Ministro
- // for more details.
-
- private static final String REPOSITORY_KEY = "repository"; // use this key to overwrite the default ministro repsitory
- private 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"
// e.g "-param1\t-param2=value2\t-param3\tvalue3"
- public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\tQT_USE_ANDROID_NATIVE_DIALOGS=1\t";
+ public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1";
// use this variable to add any environment variables to your application.
// the env vars must be separated with "\t"
// e.g. "ENV_VAR1=1\tENV_VAR2=2\t"
// Currently the following vars are used by the android plugin:
- // * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available.
- // * QT_USE_ANDROID_NATIVE_DIALOGS -1 to use the android native dialogs.
+ // * QT_USE_ANDROID_NATIVE_DIALOGS - 1 to use the android native dialogs.
public String[] QT_ANDROID_THEMES = null; // A list with all themes that your application want to use.
// The name of the theme must be the same with any theme from
@@ -161,33 +89,11 @@ public class QtActivity extends Activity
public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme.
- private static final int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded.
- private static final int BUFFER_SIZE = 1024;
-
- private ActivityInfo m_activityInfo = null; // activity info object, used to access the libs and the strings
- private DexClassLoader m_classLoader = null; // loader object
- private String[] m_sources = {"https://download.qt-project.org/ministro/android/qt5/qt-5.2"}; // Make sure you are using ONLY secure locations
- private String m_repository = "default"; // Overwrites the default Ministro repository
- // Possible values:
- // * default - Ministro default repository set with "Ministro configuration tool".
- // By default the stable version is used. Only this or stable repositories should
- // be used in production.
- // * stable - stable repository, only this and default repositories should be used
- // in production.
- // * testing - testing repository, DO NOT use this repository in production,
- // 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.
- private String[] m_qtLibs = null; // required qt libs
- private int m_displayDensity = -1;
-
+ private QtActivityLoader m_loader;
public QtActivity()
{
- if (Build.VERSION.SDK_INT <= 10) {
- QT_ANDROID_THEMES = new String[] {"Theme_Light"};
- QT_ANDROID_DEFAULT_THEME = "Theme_Light";
- }
- else if ((Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) || Build.VERSION.SDK_INT >= 21){
+ m_loader = new QtActivityLoader(this);
+ if (Build.VERSION.SDK_INT >= 21) {
QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"};
QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
} else {
@@ -196,493 +102,6 @@ public class QtActivity extends Activity
}
}
- // this function is used to load and start the loader
- private void loadApplication(Bundle loaderParams)
- {
- try {
- final int errorCode = loaderParams.getInt(ERROR_CODE_KEY);
- if (errorCode != 0) {
- if (errorCode == INCOMPATIBLE_MINISTRO_VERSION) {
- downloadUpgradeMinistro(loaderParams.getString(ERROR_MESSAGE_KEY));
- return;
- }
-
- // fatal error, show the error and quit
- AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create();
- errorDialog.setMessage(loaderParams.getString(ERROR_MESSAGE_KEY));
- errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- });
- errorDialog.show();
- return;
- }
-
- // add all bundled Qt libs to loader params
- ArrayList<String> libs = new ArrayList<String>();
- if ( m_activityInfo.metaData.containsKey("android.app.bundled_libs_resource_id") )
- libs.addAll(Arrays.asList(getResources().getStringArray(m_activityInfo.metaData.getInt("android.app.bundled_libs_resource_id"))));
-
- String libName = null;
- if ( m_activityInfo.metaData.containsKey("android.app.lib_name") ) {
- libName = m_activityInfo.metaData.getString("android.app.lib_name");
- loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function
- }
-
- loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs);
- loaderParams.putInt(NECESSITAS_API_LEVEL_KEY, NECESSITAS_API_LEVEL);
-
- // load and start QtLoader class
- m_classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files
- getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written.
- loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists)
- getClassLoader()); // parent loader
-
- @SuppressWarnings("rawtypes")
- Class loaderClass = m_classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class
- Object qtLoader = loaderClass.newInstance(); // create an instance
- Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication",
- Activity.class,
- ClassLoader.class,
- Bundle.class);
- if (!(Boolean)prepareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams))
- throw new Exception("");
-
- QtApplication.setQtActivityDelegate(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("");
-
- } catch (Exception e) {
- e.printStackTrace();
- AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create();
- if (m_activityInfo.metaData.containsKey("android.app.fatal_error_msg"))
- errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.fatal_error_msg"));
- else
- errorDialog.setMessage("Fatal error, your application can't be started.");
-
- errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- });
- errorDialog.show();
- }
- }
-
- private ServiceConnection m_ministroConnection=new ServiceConnection() {
- private IMinistro m_service = null;
- @Override
- public void onServiceConnected(ComponentName name, IBinder service)
- {
- m_service = IMinistro.Stub.asInterface(service);
- try {
- if (m_service != null) {
- Bundle parameters = new Bundle();
- parameters.putStringArray(REQUIRED_MODULES_KEY, m_qtLibs);
- parameters.putString(APPLICATION_TITLE_KEY, (String)QtActivity.this.getTitle());
- parameters.putInt(MINIMUM_MINISTRO_API_KEY, MINISTRO_API_LEVEL);
- parameters.putInt(MINIMUM_QT_VERSION_KEY, QT_VERSION);
- parameters.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES);
- if (APPLICATION_PARAMETERS != null)
- parameters.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS);
- parameters.putStringArray(SOURCES_KEY, m_sources);
- parameters.putString(REPOSITORY_KEY, m_repository);
- if (QT_ANDROID_THEMES != null)
- parameters.putStringArray(ANDROID_THEMES_KEY, QT_ANDROID_THEMES);
- m_service.requestLoader(m_ministroCallback, parameters);
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- private IMinistroCallback m_ministroCallback = new IMinistroCallback.Stub() {
- // this function is called back by Ministro.
- @Override
- public void loaderReady(final Bundle loaderParams) throws RemoteException {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- unbindService(m_ministroConnection);
- loadApplication(loaderParams);
- }
- });
- }
- };
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- m_service = null;
- }
- };
-
- private void downloadUpgradeMinistro(String msg)
- {
- AlertDialog.Builder downloadDialog = new AlertDialog.Builder(this);
- downloadDialog.setMessage(msg);
- downloadDialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int i) {
- try {
- Uri uri = Uri.parse("market://search?q=pname:org.kde.necessitas.ministro");
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- startActivityForResult(intent, MINISTRO_INSTALL_REQUEST_CODE);
- } catch (Exception e) {
- e.printStackTrace();
- ministroNotFound();
- }
- }
- });
-
- downloadDialog.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int i) {
- QtActivity.this.finish();
- }
- });
- downloadDialog.show();
- }
-
- private void ministroNotFound()
- {
- AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create();
-
- if (m_activityInfo.metaData.containsKey("android.app.ministro_not_found_msg"))
- errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.ministro_not_found_msg"));
- else
- errorDialog.setMessage("Can't find Ministro service.\nThe application can't start.");
-
- errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- });
- 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 = getAssets();
- InputStream inputStream = assetsManager.open(source);
- OutputStream outputStream = new FileOutputStream(destinationFile);
- copyFile(inputStream, outputStream);
-
- inputStream.close();
- 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 = new FileInputStream(source);
- OutputStream outputStream = new FileOutputStream(destinationFile);
- copyFile(inputStream, outputStream);
-
- inputStream.close();
- outputStream.close();
- }
-
- private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion)
- {
- File versionFile = new File(pluginsPrefix + "cache.version");
-
- long cacheVersion = 0;
- if (versionFile.exists() && versionFile.canRead()) {
- try {
- DataInputStream inputStream = new DataInputStream(new FileInputStream(versionFile));
- cacheVersion = inputStream.readLong();
- inputStream.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- if (cacheVersion != packageVersion) {
- deleteRecursively(new File(pluginsPrefix));
- return true;
- } else {
- return false;
- }
- }
-
- private void extractBundledPluginsAndImports(String pluginsPrefix)
- throws IOException
- {
- ArrayList<String> libs = new ArrayList<String>();
-
- String libsDir = getApplicationInfo().nativeLibraryDir + "/";
-
- long packageVersion = -1;
- try {
- PackageInfo packageInfo = getPackageManager().getPackageInfo(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 = new DataOutputStream(new FileOutputStream(versionFile));
- outputStream.writeLong(packageVersion);
- outputStream.close();
- }
-
- {
- String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
- java.util.Set<String> keys = m_activityInfo.metaData.keySet();
- if (m_activityInfo.metaData.containsKey(key)) {
- String[] list = getResources().getStringArray(m_activityInfo.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_activityInfo.metaData.containsKey(key)) {
- String[] list = getResources().getStringArray(m_activityInfo.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);
- }
- }
- }
-
- private void startApp(final boolean firstStart)
- {
- try {
- if (m_activityInfo.metaData.containsKey("android.app.qt_sources_resource_id")) {
- int resourceId = m_activityInfo.metaData.getInt("android.app.qt_sources_resource_id");
- m_sources = getResources().getStringArray(resourceId);
- }
-
- if (m_activityInfo.metaData.containsKey("android.app.repository"))
- m_repository = m_activityInfo.metaData.getString("android.app.repository");
-
- if (m_activityInfo.metaData.containsKey("android.app.qt_libs_resource_id")) {
- int resourceId = m_activityInfo.metaData.getInt("android.app.qt_libs_resource_id");
- m_qtLibs = getResources().getStringArray(resourceId);
- }
-
- if (m_activityInfo.metaData.containsKey("android.app.use_local_qt_libs")
- && m_activityInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) {
- ArrayList<String> libraryList = new ArrayList<String>();
-
-
- String localPrefix = "/data/local/tmp/qt/";
- if (m_activityInfo.metaData.containsKey("android.app.libs_prefix"))
- localPrefix = m_activityInfo.metaData.getString("android.app.libs_prefix");
-
- String pluginsPrefix = localPrefix;
-
- boolean bundlingQtLibs = false;
- if (m_activityInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
- && m_activityInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
- localPrefix = getApplicationInfo().dataDir + "/";
- pluginsPrefix = localPrefix + "qt-reserved-files/";
- cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
- extractBundledPluginsAndImports(pluginsPrefix);
- bundlingQtLibs = true;
- }
-
- if (m_qtLibs != null) {
- for (int i=0;i<m_qtLibs.length;i++) {
- libraryList.add(localPrefix
- + "lib/lib"
- + m_qtLibs[i]
- + ".so");
- }
- }
-
- if (m_activityInfo.metaData.containsKey("android.app.load_local_libs")) {
- String[] extraLibs = m_activityInfo.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);
- }
- }
- }
-
-
- String dexPaths = new String();
- String pathSeparator = System.getProperty("path.separator", ":");
- if (!bundlingQtLibs && m_activityInfo.metaData.containsKey("android.app.load_local_jars")) {
- String[] jarFiles = m_activityInfo.metaData.getString("android.app.load_local_jars").split(":");
- for (String jar:jarFiles) {
- if (jar.length() > 0) {
- if (dexPaths.length() > 0)
- dexPaths += pathSeparator;
- dexPaths += localPrefix + jar;
- }
- }
- }
-
- Bundle loaderParams = new Bundle();
- loaderParams.putInt(ERROR_CODE_KEY, 0);
- loaderParams.putString(DEX_PATH_KEY, dexPaths);
- loaderParams.putString(LOADER_CLASS_NAME_KEY, "org.qtproject.qt5.android.QtActivityDelegate");
- if (m_activityInfo.metaData.containsKey("android.app.static_init_classes")) {
- loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY,
- m_activityInfo.metaData.getString("android.app.static_init_classes").split(":"));
- }
- loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList);
-
-
- String themePath = getApplicationInfo().dataDir + "/qt-reserved-files/android-style/";
- String stylePath = themePath + m_displayDensity + "/";
- if (!(new File(stylePath)).exists())
- loaderParams.putString(EXTRACT_STYLE_KEY, stylePath);
- ENVIRONMENT_VARIABLES += "\tMINISTRO_ANDROID_STYLE_PATH=" + stylePath
- + "\tQT_ANDROID_THEMES_ROOT_PATH=" + themePath;
-
- loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES
- + "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml"
- + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports"
- + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins");
-
- if (APPLICATION_PARAMETERS != null) {
- loaderParams.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS);
- } else {
- Intent intent = getIntent();
- if (intent != null) {
- String parameters = intent.getStringExtra("applicationArguments");
- if (parameters != null)
- loaderParams.putString(APPLICATION_PARAMETERS_KEY, parameters.replace(' ', '\t'));
- }
- }
-
- loadApplication(loaderParams);
- return;
- }
-
- try {
- if (!bindService(new Intent(org.kde.necessitas.ministro.IMinistro.class.getCanonicalName()),
- m_ministroConnection,
- Context.BIND_AUTO_CREATE)) {
- throw new SecurityException("");
- }
- } catch (Exception e) {
- if (firstStart) {
- String msg = "This application requires Ministro service. Would you like to install it?";
- if (m_activityInfo.metaData.containsKey("android.app.ministro_needed_msg"))
- msg = m_activityInfo.metaData.getString("android.app.ministro_needed_msg");
- downloadUpgradeMinistro(msg);
- } else {
- ministroNotFound();
- }
- }
- } catch (Exception e) {
- Log.e(QtApplication.QtTAG, "Can't create main activity", e);
- }
- }
-
-
/////////////////////////// forward all notifications ////////////////////////////
/////////////////////////// Super class calls ////////////////////////////////////
@@ -753,8 +172,8 @@ public class QtActivity extends Activity
QtApplication.invokeDelegateMethod(QtApplication.onActivityResult, requestCode, resultCode, data);
return;
}
- if (requestCode == MINISTRO_INSTALL_REQUEST_CODE)
- startApp(false);
+ if (requestCode == QtLoader.MINISTRO_INSTALL_REQUEST_CODE)
+ m_loader.startApp(false);
super.onActivityResult(requestCode, resultCode, data);
}
public void super_onActivityResult(int requestCode, int resultCode, Intent data)
@@ -843,68 +262,11 @@ public class QtActivity extends Activity
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
-
- try {
- m_activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
- for (Field f : Class.forName("android.R$style").getDeclaredFields()) {
- if (f.getInt(null) == m_activityInfo.getThemeResource()) {
- QT_ANDROID_THEMES = new String[] {f.getName()};
- QT_ANDROID_DEFAULT_THEME = f.getName();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- finish();
- return;
- }
-
- try {
- setTheme(Class.forName("android.R$style").getDeclaredField(QT_ANDROID_DEFAULT_THEME).getInt(null));
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- if (Build.VERSION.SDK_INT > 10) {
- try {
- requestWindowFeature(Window.class.getField("FEATURE_ACTION_BAR").getInt(null));
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- }
-
- if (QtApplication.m_delegateObject != null && QtApplication.onCreate != null) {
- QtApplication.invokeDelegateMethod(QtApplication.onCreate, savedInstanceState);
- return;
- }
-
- m_displayDensity = getResources().getDisplayMetrics().densityDpi;
-
- ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_DEFAULT_THEME
- + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + m_displayDensity + "\t";
-
- if (null == getLastNonConfigurationInstance()) {
- // if splash screen is defined, then show it
- if (m_activityInfo.metaData.containsKey("android.app.splash_screen_drawable"))
- getWindow().setBackgroundDrawableResource(m_activityInfo.metaData.getInt("android.app.splash_screen_drawable"));
- else
- getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000));
-
- if (m_activityInfo.metaData.containsKey("android.app.background_running")
- && m_activityInfo.metaData.getBoolean("android.app.background_running")) {
- ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=0\t";
- } else {
- ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=1\t";
- }
-
- if (m_activityInfo.metaData.containsKey("android.app.auto_screen_scale_factor")
- && m_activityInfo.metaData.getBoolean("android.app.auto_screen_scale_factor")) {
- ENVIRONMENT_VARIABLES += "QT_AUTO_SCREEN_SCALE_FACTOR=1\t";
- }
-
- startApp(true);
- }
+ m_loader.APPLICATION_PARAMETERS = APPLICATION_PARAMETERS;
+ m_loader.ENVIRONMENT_VARIABLES = ENVIRONMENT_VARIABLES;
+ m_loader.QT_ANDROID_THEMES = QT_ANDROID_THEMES;
+ m_loader.QT_ANDROID_DEFAULT_THEME = QT_ANDROID_DEFAULT_THEME;
+ m_loader.onCreate(savedInstanceState);
}
//---------------------------------------------------------------------------
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
new file mode 100644
index 0000000000..2494035c60
--- /dev/null
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
@@ -0,0 +1,184 @@
+/*
+ Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt-project.org/legal
+
+ 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 Digia. For licensing terms and
+ conditions see http://qt.digia.com/licensing. For further information
+ use the contact form at http://qt.digia.com/contact-us.
+
+ BSD License Usage
+ Alternatively, this file may be used under the BSD license as follows:
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android.bindings;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.ColorDrawable;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.Window;
+
+
+import java.lang.reflect.Field;
+
+public class QtActivityLoader extends QtLoader {
+ QtActivity m_activity;
+
+ QtActivityLoader(QtActivity activity)
+ {
+ super(activity, QtActivity.class);
+ m_activity = activity;
+ }
+ @Override
+ protected void downloadUpgradeMinistro(String msg) {
+ AlertDialog.Builder downloadDialog = new AlertDialog.Builder(m_activity);
+ downloadDialog.setMessage(msg);
+ downloadDialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ try {
+ Uri uri = Uri.parse("market://search?q=pname:org.kde.necessitas.ministro");
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ m_activity.startActivityForResult(intent, MINISTRO_INSTALL_REQUEST_CODE);
+ } catch (Exception e) {
+ e.printStackTrace();
+ ministroNotFound();
+ }
+ }
+ });
+
+ downloadDialog.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ m_activity.finish();
+ }
+ });
+ downloadDialog.show();
+ }
+
+ @Override
+ protected String loaderClassName() {
+ return "org.qtproject.qt5.android.QtActivityDelegate";
+ }
+
+ @Override
+ protected Class<?> contextClassName() {
+ return android.app.Activity.class;
+ }
+
+ @Override
+ protected void finish() {
+ m_activity.finish();
+ }
+
+ @Override
+ protected String getTitle() {
+ return (String) m_activity.getTitle();
+ }
+
+ @Override
+ protected void runOnUiThread(Runnable run) {
+ m_activity.runOnUiThread(run);
+ }
+
+ @Override
+ Intent getIntent() {
+ return m_activity.getIntent();
+ }
+
+ public void onCreate(Bundle savedInstanceState) {
+ try {
+ m_contextInfo = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA);
+ for (Field f : Class.forName("android.R$style").getDeclaredFields()) {
+ if (f.getInt(null) == ((ActivityInfo)m_contextInfo).getThemeResource()) {
+ QT_ANDROID_THEMES = new String[] {f.getName()};
+ QT_ANDROID_DEFAULT_THEME = f.getName();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ finish();
+ return;
+ }
+
+ if (Build.VERSION.SDK_INT < 16) {
+ // fatal error, show the error and quit
+ AlertDialog errorDialog = new AlertDialog.Builder(m_activity).create();
+ if (m_contextInfo.metaData.containsKey("android.app.unsupported_android_version"))
+ errorDialog.setMessage(m_contextInfo.metaData.getString("android.app.unsupported_android_version"));
+ else
+ errorDialog.setMessage("Unsupported Android version.");
+ errorDialog.setButton(m_activity.getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+ errorDialog.show();
+ return;
+ }
+
+ try {
+ m_activity.setTheme(Class.forName("android.R$style").getDeclaredField(QT_ANDROID_DEFAULT_THEME).getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ m_activity.requestWindowFeature(Window.FEATURE_ACTION_BAR);
+
+ if (QtApplication.m_delegateObject != null && QtApplication.onCreate != null) {
+ QtApplication.invokeDelegateMethod(QtApplication.onCreate, savedInstanceState);
+ return;
+ }
+
+ m_displayDensity = m_activity.getResources().getDisplayMetrics().densityDpi;
+
+ ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_DEFAULT_THEME
+ + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + m_displayDensity + "\t";
+
+ if (null == m_activity.getLastNonConfigurationInstance()) {
+ if (m_contextInfo.metaData.containsKey("android.app.background_running")
+ && m_contextInfo.metaData.getBoolean("android.app.background_running")) {
+ ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=0\t";
+ } else {
+ ENVIRONMENT_VARIABLES += "QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED=1\t";
+ }
+
+ if (m_contextInfo.metaData.containsKey("android.app.auto_screen_scale_factor")
+ && m_contextInfo.metaData.getBoolean("android.app.auto_screen_scale_factor")) {
+ ENVIRONMENT_VARIABLES += "QT_AUTO_SCREEN_SCALE_FACTOR=1\t";
+ }
+
+ startApp(true);
+ }
+ }
+}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java
index c78aeb7f13..1078060d7f 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtApplication.java
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2012-2013, BogDan Vatra <bogdan@kde.org>
+ Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
Contact: http://www.qt.io/licensing/
Commercial License Usage
@@ -36,13 +36,13 @@
package org.qtproject.qt5.android.bindings;
+import android.app.Application;
+
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
-import android.app.Application;
-
public class QtApplication extends Application
{
public final static String QtTAG = "Qt";
@@ -64,10 +64,11 @@ public class QtApplication extends Application
public static Method onKeyShortcut = null;
public static Method dispatchGenericMotionEvent = null;
public static Method onGenericMotionEvent = null;
-
- public static void setQtActivityDelegate(Object listener)
+ private static String activityClassName;
+ public static void setQtContextDelegate(Class<?> clazz, Object listener)
{
- QtApplication.m_delegateObject = listener;
+ m_delegateObject = listener;
+ activityClassName = clazz.getCanonicalName();
ArrayList<Method> delegateMethods = new ArrayList<Method>();
for (Method m : listener.getClass().getMethods()) {
@@ -83,7 +84,7 @@ public class QtApplication extends Application
for (Method delegateMethod : delegateMethods) {
try {
- QtActivity.class.getDeclaredMethod(delegateMethod.getName(), delegateMethod.getParameterTypes());
+ clazz.getDeclaredMethod(delegateMethod.getName(), delegateMethod.getParameterTypes());
if (QtApplication.m_delegateMethods.containsKey(delegateMethod.getName())) {
QtApplication.m_delegateMethods.get(delegateMethod.getName()).add(delegateMethod);
} else {
@@ -126,15 +127,17 @@ public class QtApplication extends Application
return result;
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
if (-1 == stackDeep) {
- String activityClassName = QtActivity.class.getCanonicalName();
for (int it=0;it<elements.length;it++)
if (elements[it].getClassName().equals(activityClassName)) {
stackDeep = it;
break;
}
}
+ if (-1 == stackDeep)
+ return result;
+
final String methodName=elements[stackDeep].getMethodName();
- if (-1 == stackDeep || !m_delegateMethods.containsKey(methodName))
+ if (!m_delegateMethods.containsKey(methodName))
return result;
for (Method m : m_delegateMethods.get(methodName)) {
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
new file mode 100644
index 0000000000..d281cb0996
--- /dev/null
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
@@ -0,0 +1,671 @@
+/*
+ Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt.io/licensing/
+
+ 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 http://www.qt.io/terms-conditions. For further
+ information use the contact form at http://www.qt.io/contact-us.
+
+ BSD License Usage
+ Alternatively, this file may be used under the BSD license as follows:
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android.bindings;
+
+import android.app.AlertDialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+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.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+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 dalvik.system.DexClassLoader;
+
+public abstract class QtLoader {
+
+ public final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished
+ public static final int MINISTRO_API_LEVEL = 5; // Ministro api level (check IMinistro.aidl file)
+ public static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin
+ public static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0
+
+ public static final String ERROR_CODE_KEY = "error.code";
+ public static final String ERROR_MESSAGE_KEY = "error.message";
+ public static final String DEX_PATH_KEY = "dex.path";
+ public static final String LIB_PATH_KEY = "lib.path";
+ public static final String LOADER_CLASS_NAME_KEY = "loader.class.name";
+ public static final String NATIVE_LIBRARIES_KEY = "native.libraries";
+ 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 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";
+ public static final String EXTRACT_STYLE_KEY = "extract.android.style";
+ private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option";
+
+ /// Ministro server parameter keys
+ public static final String REQUIRED_MODULES_KEY = "required.modules";
+ public static final String APPLICATION_TITLE_KEY = "application.title";
+ public static final String MINIMUM_MINISTRO_API_KEY = "minimum.ministro.api";
+ public static final String MINIMUM_QT_VERSION_KEY = "minimum.qt.version";
+ public static final String SOURCES_KEY = "sources"; // needs MINISTRO_API_LEVEL >=3 !!!
+ // Use this key to specify any 3rd party sources urls
+ // Ministro will download these repositories into their
+ // own folders, check http://community.kde.org/Necessitas/Ministro
+ // for more details.
+
+ 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"
+ // e.g "-param1\t-param2=value2\t-param3\tvalue3"
+
+ public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1";
+ // use this variable to add any environment variables to your application.
+ // the env vars must be separated with "\t"
+ // e.g. "ENV_VAR1=1\tENV_VAR2=2\t"
+ // Currently the following vars are used by the android plugin:
+ // * QT_USE_ANDROID_NATIVE_DIALOGS -1 to use the android native dialogs.
+
+ public String[] QT_ANDROID_THEMES = null; // A list with all themes that your application want to use.
+ // The name of the theme must be the same with any theme from
+ // http://developer.android.com/reference/android/R.style.html
+ // The most used themes are:
+ // * "Theme" - (fallback) check http://developer.android.com/reference/android/R.style.html#Theme
+ // * "Theme_Black" - check http://developer.android.com/reference/android/R.style.html#Theme_Black
+ // * "Theme_Light" - (default for API <=10) check http://developer.android.com/reference/android/R.style.html#Theme_Light
+ // * "Theme_Holo" - check http://developer.android.com/reference/android/R.style.html#Theme_Holo
+ // * "Theme_Holo_Light" - (default for API 11-13) check http://developer.android.com/reference/android/R.style.html#Theme_Holo_Light
+ // * "Theme_DeviceDefault" - check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault
+ // * "Theme_DeviceDefault_Light" - (default for API 14+) check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault_Light
+
+ 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
+ // Possible values:
+ // * default - Ministro default repository set with "Ministro configuration tool".
+ // By default the stable version is used. Only this or stable repositories should
+ // be used in production.
+ // * stable - stable repository, only this and default repositories should be used
+ // in production.
+ // * testing - testing repository, DO NOT use this repository in production,
+ // 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 int m_displayDensity = -1;
+ private ContextWrapper m_context;
+ protected ComponentInfo m_contextInfo;
+ private Class<?> m_delegateClass;
+
+ QtLoader(ContextWrapper context, Class<?> clazz) {
+ m_context = context;
+ m_delegateClass = clazz;
+ }
+
+ // Implement in subclass
+ protected void finish() {}
+
+ protected String getTitle() {
+ return "Qt";
+ }
+
+ protected void runOnUiThread(Runnable run) {
+ run.run();
+ }
+ protected void downloadUpgradeMinistro(String msg)
+ {
+ Log.e(QtApplication.QtTAG, msg);
+ }
+
+ protected abstract String loaderClassName();
+ protected abstract Class<?> contextClassName();
+
+ Intent getIntent()
+ {
+ return null;
+ }
+ // Implement in subclass
+
+
+ // this function is used to load and start the loader
+ private void loadApplication(Bundle loaderParams)
+ {
+ try {
+ final int errorCode = loaderParams.getInt(ERROR_CODE_KEY);
+ if (errorCode != 0) {
+ if (errorCode == INCOMPATIBLE_MINISTRO_VERSION) {
+ downloadUpgradeMinistro(loaderParams.getString(ERROR_MESSAGE_KEY));
+ return;
+ }
+
+ // fatal error, show the error and quit
+ AlertDialog errorDialog = new AlertDialog.Builder(m_context).create();
+ errorDialog.setMessage(loaderParams.getString(ERROR_MESSAGE_KEY));
+ errorDialog.setButton(m_context.getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+ errorDialog.show();
+ return;
+ }
+
+ // 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"))));
+
+ String libName = null;
+ 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
+ }
+
+ loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs);
+ loaderParams.putInt(NECESSITAS_API_LEVEL_KEY, NECESSITAS_API_LEVEL);
+
+ // load and start QtLoader class
+ DexClassLoader classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files
+ m_context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written.
+ loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists)
+ m_context.getClassLoader()); // parent loader
+
+ Class<?> loaderClass = classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class
+ Object qtLoader = loaderClass.newInstance(); // create an instance
+ Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication",
+ contextClassName(),
+ ClassLoader.class,
+ Bundle.class);
+ if (!(Boolean)prepareAppMethod.invoke(qtLoader, m_context, classLoader, loaderParams))
+ throw new Exception("");
+
+ 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("");
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ AlertDialog errorDialog = new AlertDialog.Builder(m_context).create();
+ if (m_contextInfo.metaData.containsKey("android.app.fatal_error_msg"))
+ errorDialog.setMessage(m_contextInfo.metaData.getString("android.app.fatal_error_msg"));
+ else
+ errorDialog.setMessage("Fatal error, your application can't be started.");
+
+ errorDialog.setButton(m_context.getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+ errorDialog.show();
+ }
+ }
+
+ private ServiceConnection m_ministroConnection=new ServiceConnection() {
+ private IMinistro m_service = null;
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service)
+ {
+ m_service = IMinistro.Stub.asInterface(service);
+ try {
+ if (m_service != null) {
+ Bundle parameters = new Bundle();
+ parameters.putStringArray(REQUIRED_MODULES_KEY, m_qtLibs);
+ parameters.putString(APPLICATION_TITLE_KEY, getTitle());
+ parameters.putInt(MINIMUM_MINISTRO_API_KEY, MINISTRO_API_LEVEL);
+ parameters.putInt(MINIMUM_QT_VERSION_KEY, QT_VERSION);
+ parameters.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES);
+ if (APPLICATION_PARAMETERS != null)
+ parameters.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS);
+ parameters.putStringArray(SOURCES_KEY, m_sources);
+ parameters.putString(REPOSITORY_KEY, m_repository);
+ if (QT_ANDROID_THEMES != null)
+ parameters.putStringArray(ANDROID_THEMES_KEY, QT_ANDROID_THEMES);
+ m_service.requestLoader(m_ministroCallback, parameters);
+ }
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private IMinistroCallback m_ministroCallback = new IMinistroCallback.Stub() {
+ // this function is called back by Ministro.
+ @Override
+ public void loaderReady(final Bundle loaderParams) throws RemoteException {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ m_context.unbindService(m_ministroConnection);
+ loadApplication(loaderParams);
+ }
+ });
+ }
+ };
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ m_service = null;
+ }
+ };
+
+ protected void ministroNotFound()
+ {
+ AlertDialog errorDialog = new AlertDialog.Builder(m_context).create();
+
+ if (m_contextInfo.metaData.containsKey("android.app.ministro_not_found_msg"))
+ errorDialog.setMessage(m_contextInfo.metaData.getString("android.app.ministro_not_found_msg"));
+ else
+ errorDialog.setMessage("Can't find Ministro service.\nThe application can't start.");
+
+ errorDialog.setButton(m_context.getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+ 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 = assetsManager.open(source);
+ OutputStream outputStream = new FileOutputStream(destinationFile);
+ copyFile(inputStream, outputStream);
+
+ inputStream.close();
+ 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 = new FileInputStream(source);
+ OutputStream outputStream = new FileOutputStream(destinationFile);
+ copyFile(inputStream, outputStream);
+
+ inputStream.close();
+ outputStream.close();
+ }
+
+ private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion)
+ {
+ File versionFile = new File(pluginsPrefix + "cache.version");
+
+ long cacheVersion = 0;
+ if (versionFile.exists() && versionFile.canRead()) {
+ try {
+ DataInputStream inputStream = new DataInputStream(new FileInputStream(versionFile));
+ cacheVersion = inputStream.readLong();
+ inputStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (cacheVersion != packageVersion) {
+ deleteRecursively(new File(pluginsPrefix));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void extractBundledPluginsAndImports(String pluginsPrefix)
+ 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);
+ 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 = new DataOutputStream(new FileOutputStream(versionFile));
+ outputStream.writeLong(packageVersion);
+ outputStream.close();
+ }
+
+ {
+ String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
+ java.util.Set<String> keys = m_contextInfo.metaData.keySet();
+ 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 {
+ if (m_contextInfo.metaData.containsKey("android.app.qt_sources_resource_id")) {
+ int resourceId = m_contextInfo.metaData.getInt("android.app.qt_sources_resource_id");
+ m_sources = m_context.getResources().getStringArray(resourceId);
+ }
+
+ if (m_contextInfo.metaData.containsKey("android.app.repository"))
+ m_repository = m_contextInfo.metaData.getString("android.app.repository");
+
+ 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);
+ }
+
+ if (m_contextInfo.metaData.containsKey("android.app.use_local_qt_libs")
+ && m_contextInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) {
+ ArrayList<String> libraryList = new ArrayList<String>();
+
+
+ String localPrefix = "/data/local/tmp/qt/";
+ if (m_contextInfo.metaData.containsKey("android.app.libs_prefix"))
+ localPrefix = m_contextInfo.metaData.getString("android.app.libs_prefix");
+
+ String pluginsPrefix = localPrefix;
+
+ 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 + "/";
+ pluginsPrefix = localPrefix + "qt-reserved-files/";
+ cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
+ extractBundledPluginsAndImports(pluginsPrefix);
+ bundlingQtLibs = true;
+ }
+
+ if (m_qtLibs != null) {
+ for (int i=0;i<m_qtLibs.length;i++) {
+ libraryList.add(localPrefix
+ + "lib/lib"
+ + 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);
+ }
+ }
+ }
+
+
+ String dexPaths = new String();
+ String pathSeparator = System.getProperty("path.separator", ":");
+ if (!bundlingQtLibs && m_contextInfo.metaData.containsKey("android.app.load_local_jars")) {
+ String[] jarFiles = m_contextInfo.metaData.getString("android.app.load_local_jars").split(":");
+ for (String jar:jarFiles) {
+ if (jar.length() > 0) {
+ if (dexPaths.length() > 0)
+ dexPaths += pathSeparator;
+ dexPaths += localPrefix + jar;
+ }
+ }
+ }
+
+ Bundle loaderParams = new Bundle();
+ loaderParams.putInt(ERROR_CODE_KEY, 0);
+ loaderParams.putString(DEX_PATH_KEY, dexPaths);
+ loaderParams.putString(LOADER_CLASS_NAME_KEY, loaderClassName());
+ if (m_contextInfo.metaData.containsKey("android.app.static_init_classes")) {
+ loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY,
+ m_contextInfo.metaData.getString("android.app.static_init_classes").split(":"));
+ }
+ loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList);
+
+
+ String themePath = m_context.getApplicationInfo().dataDir + "/qt-reserved-files/android-style/";
+ String stylePath = themePath + m_displayDensity + "/";
+
+ String extractOption = "full";
+ if (m_contextInfo.metaData.containsKey("android.app.extract_android_style")) {
+ extractOption = m_contextInfo.metaData.getString("android.app.extract_android_style");
+ if (!extractOption.equals("full") && !extractOption.equals("minimal") && !extractOption.equals("none")) {
+ Log.e(QtApplication.QtTAG, "Invalid extract_android_style option \"" + extractOption + "\", defaulting to full");
+ extractOption = "full";
+ }
+ }
+
+ if (!(new File(stylePath)).exists() && !extractOption.equals("none")) {
+ loaderParams.putString(EXTRACT_STYLE_KEY, stylePath);
+ loaderParams.putBoolean(EXTRACT_STYLE_MINIMAL_KEY, extractOption.equals("minimal"));
+ if (extractOption.equals("full"))
+ ENVIRONMENT_VARIABLES += "\tQT_USE_ANDROID_NATIVE_STYLE=1";
+ }
+ ENVIRONMENT_VARIABLES += "\tMINISTRO_ANDROID_STYLE_PATH=" + stylePath
+ + "\tQT_ANDROID_THEMES_ROOT_PATH=" + themePath;
+
+ loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES
+ + "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml"
+ + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports"
+ + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins");
+
+ String appParams = null;
+ if (APPLICATION_PARAMETERS != null)
+ appParams = APPLICATION_PARAMETERS;
+
+ Intent intent = getIntent();
+ if (intent != null) {
+ String parameters = intent.getStringExtra("applicationArguments");
+ if (parameters != null)
+ if (appParams == null)
+ appParams = parameters;
+ else
+ appParams += '\t' + parameters;
+ }
+
+ if (m_contextInfo.metaData.containsKey("android.app.arguments")) {
+ String parameters = m_contextInfo.metaData.getString("android.app.arguments");
+ if (appParams == null)
+ appParams = parameters;
+ else
+ appParams += '\t' + parameters;
+ }
+
+ if (appParams != null)
+ loaderParams.putString(APPLICATION_PARAMETERS_KEY, appParams.replace(' ', '\t').trim());
+
+ loadApplication(loaderParams);
+ return;
+ }
+
+ try {
+ if (!m_context.bindService(new Intent(org.kde.necessitas.ministro.IMinistro.class.getCanonicalName()),
+ m_ministroConnection,
+ Context.BIND_AUTO_CREATE)) {
+ throw new SecurityException("");
+ }
+ } catch (Exception e) {
+ if (firstStart) {
+ String msg = "This application requires Ministro service. Would you like to install it?";
+ if (m_contextInfo.metaData.containsKey("android.app.ministro_needed_msg"))
+ msg = m_contextInfo.metaData.getString("android.app.ministro_needed_msg");
+ downloadUpgradeMinistro(msg);
+ } else {
+ ministroNotFound();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(QtApplication.QtTAG, "Can't create main activity", e);
+ }
+ }
+}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtService.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtService.java
new file mode 100644
index 0000000000..71acf9683e
--- /dev/null
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtService.java
@@ -0,0 +1,153 @@
+/*
+ Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt.io/licensing/
+
+ 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 http://www.qt.io/terms-conditions. For further
+ information use the contact form at http://www.qt.io/contact-us.
+
+ BSD License Usage
+ Alternatively, this file may be used under the BSD license as follows:
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android.bindings;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.IBinder;
+
+public class QtService extends Service
+{
+ QtServiceLoader m_loader = new QtServiceLoader(this);
+
+
+ /////////////////////////// forward all notifications ////////////////////////////
+ /////////////////////////// Super class calls ////////////////////////////////////
+ /////////////// PLEASE DO NOT CHANGE THE FOLLOWING CODE //////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////
+ @Override
+ public void onCreate()
+ {
+ super.onCreate();
+ m_loader.onCreate();
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public void onDestroy()
+ {
+ super.onDestroy();
+ QtApplication.invokeDelegate();
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public IBinder onBind(Intent intent)
+ {
+ QtApplication.InvokeResult res = QtApplication.invokeDelegate(intent);
+ if (res.invoked)
+ return (IBinder)res.methodReturns;
+ else
+ return null;
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig)
+ {
+ if (!QtApplication.invokeDelegate(newConfig).invoked)
+ super.onConfigurationChanged(newConfig);
+ }
+ public void super_onConfigurationChanged(Configuration newConfig)
+ {
+ super.onConfigurationChanged(newConfig);
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public void onLowMemory()
+ {
+ if (!QtApplication.invokeDelegate().invoked)
+ super.onLowMemory();
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId)
+ {
+ QtApplication.InvokeResult res = QtApplication.invokeDelegate(intent, flags, startId);
+ if (res.invoked)
+ return (Integer) res.methodReturns;
+ else
+ return super.onStartCommand(intent, flags, startId);
+ }
+ public int super_onStartCommand(Intent intent, int flags, int startId)
+ {
+ return super.onStartCommand(intent, flags, startId);
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public void onTaskRemoved(Intent rootIntent)
+ {
+ if (!QtApplication.invokeDelegate(rootIntent).invoked)
+ super.onTaskRemoved(rootIntent);
+ }
+ public void super_onTaskRemoved(Intent rootIntent)
+ {
+ super.onTaskRemoved(rootIntent);
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public void onTrimMemory(int level)
+ {
+ if (!QtApplication.invokeDelegate(level).invoked)
+ super.onTrimMemory(level);
+ }
+ public void super_onTrimMemory(int level)
+ {
+ super.onTrimMemory(level);
+ }
+ //---------------------------------------------------------------------------
+
+ @Override
+ public boolean onUnbind(Intent intent)
+ {
+ QtApplication.InvokeResult res = QtApplication.invokeDelegate(intent);
+ if (res.invoked)
+ return (Boolean) res.methodReturns;
+ else
+ return super.onUnbind(intent);
+ }
+ public boolean super_onUnbind(Intent intent)
+ {
+ return super.onUnbind(intent);
+ }
+ //---------------------------------------------------------------------------
+}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java
new file mode 100644
index 0000000000..60aecbf7b3
--- /dev/null
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtServiceLoader.java
@@ -0,0 +1,77 @@
+/*
+ Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt.io/licensing/
+
+ 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 http://www.qt.io/terms-conditions. For further
+ information use the contact form at http://www.qt.io/contact-us.
+
+ BSD License Usage
+ Alternatively, this file may be used under the BSD license as follows:
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android.bindings;
+
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+
+public class QtServiceLoader extends QtLoader {
+ QtService m_service;
+ QtServiceLoader(QtService service) {
+ super(service, QtService.class);
+ m_service = service;
+ }
+
+ public void onCreate() {
+ try {
+ m_contextInfo = m_service.getPackageManager().getServiceInfo(new ComponentName(m_service, m_service.getClass()), PackageManager.GET_META_DATA);
+ } catch (Exception e) {
+ e.printStackTrace();
+ m_service.stopSelf();
+ return;
+ }
+
+ if (QtApplication.m_delegateObject != null && QtApplication.onCreate != null)
+ QtApplication.invokeDelegateMethod(QtApplication.onCreate);
+ startApp(true);
+ }
+
+ @Override
+ protected void finish() {
+ m_service.stopSelf();
+ }
+
+ @Override
+ protected String loaderClassName() {
+ return "org.qtproject.qt5.android.QtServiceDelegate";
+ }
+
+ @Override
+ protected Class<?> contextClassName() {
+ return android.app.Service.class;
+ }
+}
diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml
index 262a5f6dba..066ec0a63c 100644
--- a/src/android/templates/AndroidManifest.xml
+++ b/src/android/templates/AndroidManifest.xml
@@ -10,6 +10,11 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
+
+ <!-- Application arguments -->
+ <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
+ <!-- Application arguments -->
+
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
@@ -32,9 +37,8 @@
<!-- Messages maps -->
<!-- Splash screen -->
- <!--
- <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
- -->
+ <!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
+ <!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
<!-- Splash screen -->
<!-- Background running -->
@@ -48,9 +52,22 @@
<!-- auto screen scale factor -->
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
<!-- auto screen scale factor -->
- </activity>
+
+ <!-- extract android style -->
+ <!-- available android:values :
+ * full - useful QWidget & Quick Controls 1 apps
+ * minimal - useful for Quick Controls 2 apps, it is much faster than "full"
+ * none - useful for apps that don't use any of the above Qt modules
+ -->
+ <meta-data android:name="android.app.extract_android_style" android:value="full"/>
+ <!-- extract android style -->
+ </activity>
+
+ <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
+
</application>
- <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
+
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
diff --git a/src/android/templates/res/values/libs.xml b/src/android/templates/res/values/libs.xml
index ee3f5e940e..43296f2e7a 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.6</item>
+ <item>https://download.qt.io/ministro/android/qt5/qt-5.7</item>
</array>
<!-- The following is handled automatically by the deployment tool. It should