├── README.md
├── android
├── Activity-AndroidManifest.xml
├── Service-AndroidManifest.xml
├── jni
│ ├── Android.mk
│ └── QtAndroidService.cpp
├── libs
│ └── guava-10.0.1.jar
├── res
│ ├── layout
│ │ └── serviceconfigactivity.xml
│ └── values
│ │ ├── dimens.xml
│ │ └── style.xml
├── setup.sh
└── src
│ └── org
│ └── qtproject
│ └── qt5
│ └── android
│ ├── QtServiceDelegate.java
│ └── addons
│ ├── qtactivityapp
│ ├── QtService.java
│ └── QtServiceActivity.java
│ └── qtserviceapp
│ ├── QtService.java
│ ├── QtServiceActivity.java
│ └── QtServiceBroadcastReceiver.java
└── example
└── MyTestService
├── MyTestService.pro
├── android
├── Activity-AndroidManifest.xml
├── AndroidManifest.xml
├── README.md
├── Service-AndroidManifest.xml
├── jni
│ ├── Android.mk
│ └── QtAndroidService.cpp
├── libs
│ ├── armeabi
│ │ └── libQtAndroidService.so
│ └── guava-10.0.1.jar
├── obj
│ └── local
│ │ └── armeabi
│ │ ├── libQtAndroidService.so
│ │ ├── libstdc++.a
│ │ └── objs
│ │ └── QtAndroidService
│ │ ├── QtAndroidService.o
│ │ └── QtAndroidService.o.d
├── res
│ ├── drawable-hdpi-v11
│ │ └── notificon.png
│ ├── drawable-hdpi
│ │ ├── icon.png
│ │ └── notificon.png
│ ├── drawable-mdpi-v11
│ │ └── notificon.png
│ ├── drawable-mdpi
│ │ ├── icon.png
│ │ └── notificon.png
│ ├── drawable-xhdpi-v11
│ │ └── notificon.png
│ ├── drawable-xhdpi
│ │ ├── icon.png
│ │ └── notificon.png
│ ├── drawable-xxhdpi-v11
│ │ └── notificon.png
│ ├── drawable-xxhdpi
│ │ ├── icon.png
│ │ └── notificon.png
│ ├── drawable-xxxhdpi
│ │ └── icon.png
│ ├── layout
│ │ └── serviceconfigactivity.xml
│ └── values
│ │ ├── dimens.xml
│ │ └── style.xml
├── setup.sh
└── src
│ ├── com
│ └── mycompany
│ │ └── test1
│ │ ├── MyTestService.java
│ │ ├── MyTestServiceActivity.java
│ │ └── MyTestServiceBroadcastReceiver.java
│ └── org
│ └── qtproject
│ └── qt5
│ └── android
│ ├── QtServiceDelegate.java
│ └── addons
│ └── qtserviceapp
│ ├── QtService.java
│ ├── QtServiceActivity.java
│ └── QtServiceBroadcastReceiver.java
└── main.cpp
/README.md:
--------------------------------------------------------------------------------
1 | Qt Android service and activity helper classes
2 | ==============================================
3 |
4 | - First create a project in QtCreator QtQuick or QtWidget for activity based application or "Qt Console Application" for a service based one
5 |
6 | - In project - Android - Run - Advanced actions, create an AndroidManifest
7 | or put the following lines to your .pro
8 |
9 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
10 |
11 | OTHER_FILES += \
12 | android/AndroidManifest.xml
13 |
14 |
15 | - ! Only bundled Qt librairies have been tested ...
16 |
17 | - Replace the "android" folder that qtcreator have created in your project by this one or if your edited the .pro just put it in your project.
18 |
19 | - Run ./setup.sh in the android folder
20 | - Put your icon.png and notificon.png
21 |
--------------------------------------------------------------------------------
/android/Activity-AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/android/Service-AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/android/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH:= $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 |
5 | LOCAL_MODULE := QtAndroidService
6 | LOCAL_CFLAGS := -Werror
7 | LOCAL_SRC_FILES := QtAndroidService.cpp
8 | LOCAL_LDLIBS := -llog
9 |
10 | include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------------------------------
/android/jni/QtAndroidService.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | // Global variables
12 |
13 | static jclass m_applicationClass = NULL;
14 | static jobject m_classLoaderObject = NULL;
15 | static jmethodID m_loadClassMethodID = NULL;
16 | static jobject m_resourcesObj;
17 | static jobject m_activityObject = NULL;
18 |
19 | extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application
20 | static JavaVM *m_javaVM = NULL;
21 | static Main m_main = NULL;
22 | static void *m_mainLibraryHnd = NULL;
23 |
24 | static const char m_classErrorMsg[] = "Can't find class \"%s\"";
25 | static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
26 |
27 | // Methods definition
28 |
29 | static jboolean startQtAndroidPlugin(JNIEnv* env, jobject object /*, jobject applicationAssetManager*/)
30 | {
31 | return 1;
32 | }
33 |
34 | static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
35 | jint /*widthPixels*/, jint /*heightPixels*/,
36 | jint desktopWidthPixels, jint desktopHeightPixels,
37 | jdouble xdpi, jdouble ydpi, jdouble scaledDensity)
38 | {}
39 |
40 | // Methods definition
41 |
42 | static void *startMainMethod(void *ar)
43 | {
44 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Calling main method");
45 |
46 | char *argv[] = { NULL};
47 | int argc = sizeof(argv) / sizeof(char*) - 1;
48 |
49 | int ret = m_main(argc, argv);
50 |
51 | return NULL;
52 | }
53 |
54 | static jboolean startQtApplication(JNIEnv *env, jobject object, jstring paramsString, jstring environmentString)
55 | {
56 | // Get native
57 |
58 | const char *nativeEnvironmentString = (env)->GetStringUTFChars(environmentString, NULL); // C++
59 | const char *nativeParamsString = (env)->GetStringUTFChars(paramsString, NULL); // C++
60 |
61 | // Print info
62 |
63 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Starting the Qt service");
64 |
65 | char cwd[1024];
66 | if (getcwd(cwd, sizeof(cwd)) != NULL)
67 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Current working dir : %s", cwd);
68 |
69 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Param : %s", nativeParamsString );
70 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Env : %s", nativeEnvironmentString );
71 |
72 | // Start
73 |
74 | m_mainLibraryHnd = NULL;
75 |
76 | // Obtain a handle to the main library (the library that contains the main() function).
77 | // This library should already be loaded, and calling dlopen() will just return a reference to it.
78 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Trying to open %s", nativeParamsString);
79 | m_mainLibraryHnd = dlopen(nativeParamsString, 0);
80 |
81 | if (m_mainLibraryHnd == NULL) {
82 |
83 | __android_log_print(ANDROID_LOG_INFO, "Qt", "No main library was specified; searching entire process (this is slow!)");
84 | m_main = (Main)dlsym(RTLD_DEFAULT, "main");
85 | }
86 | else {
87 |
88 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Getting the main method from handler");
89 | m_main = (Main)dlsym(m_mainLibraryHnd, "main");
90 | }
91 |
92 |
93 | if (!m_main) {
94 |
95 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Could not find main method");
96 | return 0;
97 | }
98 | else{
99 |
100 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Main method found, starting");
101 | }
102 |
103 |
104 | pthread_t appThread;
105 | return pthread_create(&appThread, NULL, startMainMethod, NULL) == 0;
106 |
107 | //env->ReleaseStringUTFChars(environmentString, nativeString);
108 | }
109 |
110 | static void quitQtAndroidPlugin(JNIEnv *env, jclass clazz)
111 | {
112 |
113 | }
114 |
115 | static void terminateQt(JNIEnv *env, jclass clazz)
116 | {
117 |
118 | }
119 |
120 | // Native methods
121 |
122 | static JNINativeMethod methods[] = {
123 | {"startQtAndroidPlugin", "()Z", (void *)startQtAndroidPlugin},
124 | {"setDisplayMetrics", "(IIIIDDD)V", (void *)setDisplayMetrics},
125 | {"startQtApplication", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)startQtApplication},
126 | {"quitQtAndroidPlugin", "()V", (void *)quitQtAndroidPlugin},
127 | {"terminateQt", "()V", (void *)terminateQt}
128 | };
129 |
130 |
131 | // Helpers functions
132 |
133 | #define FIND_AND_CHECK_CLASS(CLASS_NAME) \
134 | clazz = env->FindClass(CLASS_NAME); \
135 | if (!clazz) { \
136 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_classErrorMsg, CLASS_NAME); \
137 | return JNI_FALSE; \
138 | }
139 |
140 | #define GET_AND_CHECK_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
141 | VAR = env->GetMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \
142 | if (!VAR) { \
143 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \
144 | return JNI_FALSE; \
145 | }
146 |
147 | #define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
148 | VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \
149 | if (!VAR) { \
150 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \
151 | return JNI_FALSE; \
152 | }
153 |
154 | #define GET_AND_CHECK_FIELD(VAR, CLASS, FIELD_NAME, FIELD_SIGNATURE) \
155 | VAR = env->GetFieldID(CLASS, FIELD_NAME, FIELD_SIGNATURE); \
156 | if (!VAR) { \
157 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, FIELD_NAME, FIELD_SIGNATURE); \
158 | return JNI_FALSE; \
159 | }
160 |
161 | #define GET_AND_CHECK_STATIC_FIELD(VAR, CLASS, FIELD_NAME, FIELD_SIGNATURE) \
162 | VAR = env->GetStaticFieldID(CLASS, FIELD_NAME, FIELD_SIGNATURE); \
163 | if (!VAR) { \
164 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, FIELD_NAME, FIELD_SIGNATURE); \
165 | return JNI_FALSE; \
166 | }
167 |
168 | // On load
169 |
170 | jint JNICALL JNI_OnLoad(JavaVM *vm, void *ld)
171 | {
172 |
173 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Qt Android service wrapper start");
174 |
175 | JNIEnv* env;
176 | if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) {
177 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Can't get env in wrapper start"); \
178 | return -1;
179 | }
180 |
181 | m_javaVM = vm;
182 |
183 | jclass clazz;
184 | FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative");
185 | m_applicationClass = static_cast(env->NewGlobalRef(clazz));
186 |
187 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Registering native classes for service wrapper");
188 |
189 | if (env->RegisterNatives(m_applicationClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
190 | __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed for service wrapper");
191 | return JNI_FALSE;
192 | }
193 |
194 | return JNI_VERSION_1_4;
195 | }
196 |
197 |
198 |
--------------------------------------------------------------------------------
/android/libs/guava-10.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/android/libs/guava-10.0.1.jar
--------------------------------------------------------------------------------
/android/res/layout/serviceconfigactivity.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
21 |
22 |
30 |
31 |
40 |
41 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/android/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/android/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This script will setup the android folder for an activity or a service based qt application
4 |
5 | # Functions
6 |
7 | function setup(){
8 |
9 | clear
10 |
11 | echo ""
12 | echo "Please enter your package name (ex : org.qt-project.myqtapplication) : "
13 | read package
14 |
15 | app=`ls ../*.pro | cut -d '/' -f 2 | cut -d '.' -f 1`
16 |
17 | if [ "$app" == "" ];
18 | then
19 | echo "Can't find .pro in ../ exiting"
20 | exit 1
21 | fi
22 |
23 | echo ""
24 | echo "Do you want to create an activity or a service based application ? [a/s]"
25 | read tp
26 |
27 | if [ "$tp" == "a" ];
28 | then
29 |
30 | activity $package $app
31 |
32 | elif [ "$tp" == "s" ];
33 | then
34 |
35 | service $package $app
36 |
37 | else
38 |
39 | clear
40 | echo "Bad selection"
41 | sleep 2
42 | setup
43 | fi
44 | }
45 |
46 | function activity(){
47 |
48 | echo "You've selected an activity based application"
49 |
50 | cp Activity-AndroidManifest.xml AndroidManifest.xml
51 |
52 | echo "Cleaning un-necesary files"
53 | #################################
54 |
55 | rm -rf src/org/qtproject/qt5/android/addons/qtserviceapp
56 | rm src/org/qtproject/qt5/android/QtServiceDelegate.java
57 |
58 | echo "Configuring manifest"
59 | ###########################
60 |
61 | sed -i "s|org.qtproject.qt5.android.addons|$1|" AndroidManifest.xml
62 | sed -i "s|qtactivityapp.QtServiceActivity|$2Activity|g" AndroidManifest.xml
63 | sed -i "s|qtactivityapp.QtService|$2Service|g" AndroidManifest.xml
64 |
65 | echo "Creating package folders"
66 | ###############################
67 |
68 | fld=src/$(sed 's|\.|/|g' <<< $1)
69 | mkdir -p $fld
70 |
71 |
72 | echo "Configuring activity"
73 | ###########################
74 |
75 |
76 | echo ""
77 | echo "Do you want to use a sticky notification with service ? [y/n]"
78 | read sticky
79 |
80 |
81 | echo "package $1;" >> $fld/$2Activity.java
82 |
83 | echo "import org.qtproject.qt5.android.addons.qtactivityapp.QtServiceActivity;" >> $fld/$2Activity.java
84 | echo "import org.qtproject.qt5.android.addons.qtactivityapp.QtService;" >> $fld/$2Activity.java
85 | echo "import android.os.Bundle;" >> $fld/$2Activity.java
86 | echo "import android.content.Intent;" >> $fld/$2Activity.java
87 | echo "import android.content.ComponentName;" >> $fld/$2Activity.java
88 | echo "import android.util.Log;" >> $fld/$2Activity.java
89 |
90 | echo "public class $2Activity extends QtServiceActivity" >> $fld/$2Activity.java
91 | echo "{" >> $fld/$2Activity.java
92 | echo " public void onCreate(Bundle savedInstanceState)" >> $fld/$2Activity.java
93 | echo " {" >> $fld/$2Activity.java
94 | echo " Log.w(getClass().getName(), "Starting config editor");" >> $fld/$2Activity.java
95 |
96 | if [ "$sticky" == "y" ];
97 | then
98 | echo " super.setServiceClass($2Service.java);" >> $fld/$2Activity.java
99 | else
100 | echo " super.setServiceClass(null);" >> $fld/$2Activity.java
101 | fi
102 |
103 | echo " super.onCreate(savedInstanceState);" >> $fld/$2Activity.java
104 | echo " }" >> $fld/$2Activity.java
105 | echo "}" >> $fld/$2Activity.java
106 |
107 |
108 | echo "Configuring service"
109 | ##########################
110 |
111 | echo "package $1;" >> $fld/$2Service.java
112 |
113 | echo "import org.qtproject.qt5.android.addons.qtactivityapp.QtService;" >> $fld/$2Service.java
114 | echo "import android.util.Log;" >> $fld/$2Service.java
115 |
116 | echo "public class $2Service extends QtService" >> $fld/$2Service.java
117 | echo "{" >> $fld/$2Service.java
118 | echo " public void onCreate()" >> $fld/$2Service.java
119 | echo " {" >> $fld/$2Service.java
120 | echo " Log.w(getClass().getName(), "Starting config editor service");" >> $fld/$2Service.java
121 | echo " super.setActivityClass($2Activity.class);" >> $fld/$2Service.java
122 | echo " super.onCreate();" >> $fld/$2Service.java
123 | echo " }" >> $fld/$2Service.java
124 | echo "}" >> $fld/$2Service.java
125 |
126 | }
127 |
128 | function service(){
129 |
130 | echo "You've selected a service based application"
131 | ##################################################
132 |
133 | cp Service-AndroidManifest.xml AndroidManifest.xml
134 |
135 | echo "Compiling helper librairy"
136 | ################################
137 |
138 | cd jni
139 | ndk-build
140 | cd ..
141 |
142 | echo "Cleaning un-necesary files"
143 | #################################
144 |
145 | rm -rf src/org/qtproject/qt5/android/addons/qtactivityapp
146 |
147 | echo "Configuring manifest"
148 | ###########################
149 |
150 | sed -i "s|org.qtproject.qt5.android.addons|$1|" AndroidManifest.xml
151 | sed -i "s|qtserviceapp.QtService|$2|g" AndroidManifest.xml
152 | sed -i "s|QtServiceActivity|$2|g" AndroidManifest.xml
153 |
154 | sed -i "s|import R;|import $1.R;|" src/org/qtproject/qt5/android/addons/qtserviceapp/QtServiceActivity.java # FIXME !!!!
155 |
156 |
157 | echo "Creating package folders"
158 | ###############################
159 |
160 | fld=src/$(sed 's|\.|/|g' <<< $1)
161 | mkdir -p $fld
162 |
163 |
164 | echo "Configuring Service"
165 | ##########################
166 |
167 | echo "package $1;" >> $fld/$2.java
168 |
169 | echo "import org.qtproject.qt5.android.addons.qtserviceapp.QtService;" >> $fld/$2.java
170 | echo "import android.util.Log;" >> $fld/$2.java
171 |
172 | echo "public class $2 extends QtService {" >> $fld/$2.java
173 |
174 | echo " public void onCreate()" >> $fld/$2.java
175 | echo " {" >> $fld/$2.java
176 | echo " Log.w(getClass().getName(), \"Starting datasync service\");" >> $fld/$2.java
177 | echo " super.setActivityClass($2Activity.class);" >> $fld/$2.java
178 | echo " super.onCreate();" >> $fld/$2.java
179 | echo " }" >> $fld/$2.java
180 | echo "}" >> $fld/$2.java
181 | echo "" >> $fld/$2.java
182 |
183 |
184 | echo "Configuring service activity"
185 | ###################################
186 |
187 | echo "package $1;" >> $fld/$2Activity.java
188 |
189 | echo "import $1.R;" >> $fld/$2Activity.java
190 |
191 | echo "import org.qtproject.qt5.android.addons.qtserviceapp.QtServiceActivity;" >> $fld/$2Activity.java
192 |
193 | echo "import android.os.Bundle;" >> $fld/$2Activity.java
194 | echo "import android.util.Log;" >> $fld/$2Activity.java
195 |
196 | echo "public class $2Activity extends QtServiceActivity {" >> $fld/$2Activity.java
197 |
198 | echo " @Override" >> $fld/$2Activity.java
199 | echo " public void onCreate(Bundle savedInstanceState)" >> $fld/$2Activity.java
200 | echo " {" >> $fld/$2Activity.java
201 | echo " Log.w(getClass().getName(), \"Starting datasync service activity\");" >> $fld/$2Activity.java
202 | echo " super.setActivityClass($2.class);" >> $fld/$2Activity.java
203 | echo " super.onCreate(savedInstanceState);" >> $fld/$2Activity.java
204 | echo " }" >> $fld/$2Activity.java
205 | echo "}" >> $fld/$2Activity.java
206 | echo "" >> $fld/$2Activity.java
207 |
208 |
209 | echo "Configuring broadcast receiver (to be run at startup)"
210 | ############################################################
211 |
212 | echo "package $1;" >> $fld/$2BroadcastReceiver.java
213 |
214 | echo "import org.qtproject.qt5.android.addons.qtserviceapp.QtServiceBroadcastReceiver;" >> $fld/$2BroadcastReceiver.java
215 |
216 | echo "import android.content.Context;" >> $fld/$2BroadcastReceiver.java
217 | echo "import android.content.Intent;" >> $fld/$2BroadcastReceiver.java
218 | echo "import android.util.Log;" >> $fld/$2BroadcastReceiver.java
219 |
220 | echo "public class $2BroadcastReceiver extends QtServiceBroadcastReceiver {" >> $fld/$2BroadcastReceiver.java
221 |
222 | echo " @Override" >> $fld/$2BroadcastReceiver.java
223 | echo " public void onReceive(Context context, Intent intent) {" >> $fld/$2BroadcastReceiver.java
224 |
225 | echo " Log.w(getClass().getName(), \"Broadcast received for Comservice\");" >> $fld/$2BroadcastReceiver.java
226 |
227 | echo " super.setActivityClass($2.class);" >> $fld/$2BroadcastReceiver.java
228 | echo " super.onReceive(context, intent);" >> $fld/$2BroadcastReceiver.java
229 | echo " }" >> $fld/$2BroadcastReceiver.java
230 | echo "}" >> $fld/$2BroadcastReceiver.java
231 | echo "" >> $fld/$2BroadcastReceiver.java
232 | }
233 |
234 | # Main
235 |
236 | clear
237 | echo ""
238 | echo "This script will allow you to setup a qt activity based application with a service that run a sticky notification or a service based application (without grafical interface)"
239 | echo "First create a qt project in qtcreator "
240 | echo "Please ensure that ndk-build (android-ndk) is in your path before continuing"
241 | echo ""
242 | echo "Press any key to continue"
243 | read
244 |
245 | setup
246 |
247 | clear
248 | echo "Almost done, please create an icon.png and a notificon.png for every resolution you want to support in the res folder"
249 | echo "You can use : http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html to create it"
250 |
--------------------------------------------------------------------------------
/android/src/org/qtproject/qt5/android/QtServiceDelegate.java:
--------------------------------------------------------------------------------
1 |
2 | package org.qtproject.qt5.android;
3 |
4 | import java.io.File;
5 | import java.io.FileWriter;
6 | import java.io.IOException;
7 | import java.lang.reflect.Method;
8 | import java.util.ArrayList;
9 | import java.util.Iterator;
10 |
11 | import android.app.Service;
12 | import android.content.Context;
13 | import android.content.pm.ApplicationInfo;
14 | import android.content.pm.PackageManager;
15 | import android.content.pm.PackageManager.NameNotFoundException;
16 | import android.content.res.Configuration;
17 | import android.graphics.Rect;
18 | import android.os.Build;
19 | import android.os.Bundle;
20 | import android.util.Log;
21 |
22 | public class QtServiceDelegate
23 | {
24 | private Service m_service = null;
25 |
26 | private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
27 | private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
28 | private static final String MAIN_LIBRARY_KEY = "main.library";
29 | private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
30 | private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
31 | private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
32 | private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
33 |
34 | private static String m_environmentVariables = null;
35 | private static String m_applicationParameters = null;
36 |
37 | private String m_mainLib;
38 |
39 | public boolean loadApplication(Service service, ClassLoader classLoader, Bundle loaderParams)
40 | {
41 | if (!loaderParams.containsKey(NATIVE_LIBRARIES_KEY))
42 | Log.w(getClass().getName(), "Missing parameters1 in loaderParams");
43 |
44 | if (!loaderParams.containsKey(BUNDLED_LIBRARIES_KEY))
45 | Log.w(getClass().getName(), "Missing parameters2 in loaderParams");
46 |
47 | /// check parameters integrity
48 | if (!loaderParams.containsKey(NATIVE_LIBRARIES_KEY)
49 | || !loaderParams.containsKey(BUNDLED_LIBRARIES_KEY)) {
50 |
51 | Log.w(getClass().getName(), "Missing parameters in loaderParams");
52 | return false;
53 | }
54 |
55 | m_service = service;
56 | //QtNative.setActivity(m_activity, this);
57 | QtNative.setClassLoader(classLoader);
58 | if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) {
59 | for (String className: loaderParams.getStringArray(STATIC_INIT_CLASSES_KEY)) {
60 | Log.w(getClass().getName(), className);
61 | if (className.length() == 0)
62 | continue;
63 |
64 | try {
65 | @SuppressWarnings("rawtypes")
66 | Class initClass = classLoader.loadClass(className);
67 | Object staticInitDataObject = initClass.newInstance(); // create an instance
68 | //Method m = initClass.getMethod("setActivity", Activity.class, Object.class);
69 | //m.invoke(staticInitDataObject, m_activity, this);
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 | }
74 | }
75 |
76 | QtNative.loadQtLibraries(loaderParams.getStringArrayList(NATIVE_LIBRARIES_KEY));
77 | ArrayList libraries = loaderParams.getStringArrayList(BUNDLED_LIBRARIES_KEY);
78 | QtNative.loadBundledLibraries(libraries, QtNativeNativeLibrariesDir(m_service));
79 | m_mainLib = loaderParams.getString(MAIN_LIBRARY_KEY);
80 | // older apps provide the main library as the last bundled library; look for this if the main library isn't provided
81 | if (null == m_mainLib && libraries.size() > 0)
82 | m_mainLib = libraries.get(libraries.size() - 1);
83 |
84 |
85 | int necessitasApiLevel = 1;
86 | if (loaderParams.containsKey(NECESSITAS_API_LEVEL_KEY))
87 | necessitasApiLevel = loaderParams.getInt(NECESSITAS_API_LEVEL_KEY);
88 |
89 | m_environmentVariables ="";
90 |
91 | if (loaderParams.containsKey(APPLICATION_PARAMETERS_KEY))
92 | m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY);
93 | else
94 | m_applicationParameters = "";
95 |
96 | return true;
97 | }
98 |
99 | public void debugLog(String msg)
100 | {
101 | Log.i(QtNative.QtTAG, "DEBUGGER: " + msg);
102 | }
103 |
104 | public boolean startApplication()
105 | {
106 |
107 | try {
108 |
109 | String nativeLibraryDir = QtNativeNativeLibrariesDir(m_service);
110 |
111 | Log.i(QtNative.QtTAG, "LIB DIR : " + nativeLibraryDir);
112 |
113 | //QtNativeStartApplication
114 | QtNative.startApplication
115 | ( m_applicationParameters,
116 | m_environmentVariables,
117 | m_mainLib,
118 | nativeLibraryDir);
119 | return true;
120 | }
121 | catch (Exception e) {
122 |
123 | e.printStackTrace();
124 | return false;
125 | }
126 | }
127 |
128 | public static String QtNativeNativeLibrariesDir(Service service)
129 | {
130 | String m_nativeLibraryDir = null;
131 | try {
132 | ApplicationInfo ai = service.getPackageManager().getApplicationInfo(service.getPackageName(), 0);
133 | m_nativeLibraryDir = ai.nativeLibraryDir+"/";
134 | } catch (NameNotFoundException e) {
135 | e.printStackTrace();
136 | }
137 | return m_nativeLibraryDir;
138 | }
139 |
140 |
141 | public static boolean QtNativeStartApplication(String params,
142 | String environment,
143 | String mainLibrary,
144 | String nativeLibraryDir) throws Exception
145 | {
146 | File f = new File(nativeLibraryDir + "lib" + mainLibrary + ".so");
147 | if (!f.exists())
148 | throw new Exception("Can't find main library '" + mainLibrary + "'");
149 |
150 | if (params == null)
151 | params = "-platform\tandroid";
152 |
153 | boolean res = false;
154 |
155 | if (params.length() > 0 && !params.startsWith("\t"))
156 | params = "\t" + params;
157 | startQtApplication(f.getAbsolutePath() + params, environment);
158 |
159 | return res;
160 | }
161 |
162 | public static native void startQtApplication(String params, String env);
163 | }
164 |
--------------------------------------------------------------------------------
/android/src/org/qtproject/qt5/android/addons/qtactivityapp/QtService.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtactivityapp;
2 |
3 | import java.lang.reflect.Method;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 |
7 | import dalvik.system.DexClassLoader;
8 |
9 | import android.annotation.SuppressLint;
10 | import android.app.Notification;
11 | import android.app.NotificationManager;
12 | import android.app.PendingIntent;
13 | import android.app.Service;
14 | import android.content.ComponentName;
15 | import android.content.Context;
16 | import android.content.pm.PackageManager;
17 | import android.content.pm.ServiceInfo;
18 | import android.content.Intent;
19 | import android.os.Bundle;
20 | import android.os.IBinder;
21 | import android.util.Log;
22 | import android.os.Process;
23 | import android.widget.Toast;
24 |
25 | public class QtService extends Service
26 | {
27 | public static final String EXTRA_MESSAGE="EXTRA_MESSAGE";
28 |
29 | private boolean isRunning=false;
30 | private ComponentName myService;
31 | private Class m_class = QtServiceActivity.class;
32 |
33 | private static ServiceInfo m_serviceInfo = null;
34 | private static NotificationManager m_notificationManager;
35 | private static Notification.Builder m_builder;
36 | private static QtService m_instance;
37 | private static String m_lib_name;
38 | private static PendingIntent pi;
39 |
40 | /* Event handling */
41 |
42 | public void onCreate (){
43 |
44 | Log.w(getClass().getName(), "Service created ...");
45 |
46 | m_instance = this;
47 |
48 | try{
49 | ComponentName myService = new ComponentName(this, this.getClass());
50 | m_serviceInfo = getPackageManager().getServiceInfo(myService, PackageManager.GET_META_DATA);
51 | m_lib_name = splitCamelCase (m_serviceInfo.metaData.getString("android.app.lib_name"));
52 | }
53 | catch (Exception e) {
54 |
55 | e.printStackTrace();
56 | }
57 | }
58 |
59 | public IBinder onBind(Intent intent){
60 |
61 | return(null);
62 | }
63 |
64 | public int onStartCommand(Intent intent, int flags, int startId){
65 |
66 | /* Notifiication */
67 |
68 | Notification note=new Notification(m_serviceInfo.metaData.getInt("android.app.notificon"),"",System.currentTimeMillis());
69 |
70 | Intent i=new Intent(m_instance, m_class);
71 | i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
72 |
73 | pi=PendingIntent.getActivity(this, 0,
74 | i, 0);
75 |
76 | note.setLatestEventInfo(this, m_lib_name ,
77 | "Running",
78 | pi);
79 | note.flags|=Notification.FLAG_NO_CLEAR;
80 |
81 | startForeground(1337, note);
82 |
83 | /* Return */
84 |
85 | return(START_STICKY);
86 | }
87 |
88 | public void onDestroy(){
89 |
90 | Log.w(getClass().getName(), "Service destroyed ...");
91 |
92 | Process.killProcess(Process.myPid());
93 | }
94 |
95 | /* Activity class */
96 |
97 | public void setActivityClass(Class cl){
98 |
99 | m_class = cl;
100 | }
101 |
102 | /* Notification methods */
103 |
104 | public static void notify(String s){
105 |
106 | if (m_notificationManager == null) {
107 |
108 | m_notificationManager = (NotificationManager)m_instance.getSystemService(Context.NOTIFICATION_SERVICE);
109 | m_builder = new Notification.Builder(m_instance);
110 | m_builder.setSmallIcon(m_serviceInfo.metaData.getInt("android.app.notificon"));
111 | m_builder.setContentTitle(m_lib_name);
112 | m_builder.setContentIntent(pi);
113 | }
114 |
115 | m_builder.setContentText(s);
116 | Notification note = m_builder.build();
117 | note.flags |= Notification.FLAG_NO_CLEAR;
118 |
119 | m_notificationManager.notify(1337, note);
120 | }
121 |
122 | /* Helper classes */
123 |
124 | static String splitCamelCase(String sp) {
125 |
126 | String s = Character.toUpperCase(sp.charAt(0)) + sp.substring(1);
127 |
128 | return s.replaceAll(
129 | String.format("%s|%s|%s",
130 | "(?<=[A-Z])(?=[A-Z][a-z])",
131 | "(?<=[^A-Z])(?=[A-Z])",
132 | "(?<=[A-Za-z])(?=[^A-Za-z])"
133 | ),
134 | " "
135 | );
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/android/src/org/qtproject/qt5/android/addons/qtactivityapp/QtServiceActivity.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtactivityapp;
2 |
3 | import org.qtproject.qt5.android.bindings.QtActivity;
4 |
5 | import android.app.Activity;
6 | import android.content.pm.ActivityInfo;
7 | import android.content.ComponentName;
8 | import android.os.Bundle;
9 | import android.content.pm.PackageManager;
10 | import android.content.pm.PackageManager.NameNotFoundException;
11 | import android.util.Log;
12 | import android.content.Intent;
13 | import android.view.Window;
14 | import android.view.WindowManager;
15 |
16 | public class QtServiceActivity extends QtActivity
17 | {
18 | private ActivityInfo m_activityInfo = null;
19 | private Class m_class = QtService.class;
20 |
21 | @Override
22 | public void onCreate(Bundle savedInstanceState)
23 | {
24 | requestWindowFeature(Window.FEATURE_NO_TITLE);
25 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
26 |
27 | super.onCreate(savedInstanceState);
28 |
29 | try {
30 | m_activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
31 | }
32 | catch (NameNotFoundException e) {
33 | e.printStackTrace();
34 | finish();
35 | return;
36 | }
37 |
38 | loadService();
39 | }
40 |
41 | public void setServiceClass(Class cl){
42 |
43 | m_class = cl;
44 | }
45 |
46 | private int loadService()
47 | {
48 | int retVal = -1;
49 | Log.w("Qt", "loadService");
50 | try
51 | {
52 | if (m_class != null){
53 | Intent i = new Intent(this, m_class);
54 | i.putExtra(QtService.EXTRA_MESSAGE, "Loading " + m_activityInfo.metaData.getString("android.app.lib_name"));
55 | ComponentName cn = startService(i);
56 | retVal = 0;
57 | }
58 | }
59 | catch (Exception e)
60 | {
61 | Log.e("Qt", "Can't create service " + e);
62 | }
63 |
64 | return retVal;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/android/src/org/qtproject/qt5/android/addons/qtserviceapp/QtService.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtserviceapp;
2 |
3 | import java.lang.reflect.Method;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 |
7 | import dalvik.system.DexClassLoader;
8 |
9 | import android.annotation.SuppressLint;
10 | import android.app.Notification;
11 | import android.app.NotificationManager;
12 | import android.app.PendingIntent;
13 | import android.app.Service;
14 | import android.content.ComponentName;
15 | import android.content.Context;
16 | import android.content.pm.PackageManager;
17 | import android.content.pm.ServiceInfo;
18 | import android.content.Intent;
19 | import android.os.Bundle;
20 | import android.os.IBinder;
21 | import android.util.Log;
22 | import android.os.Process;
23 | import android.widget.Toast;
24 |
25 | @SuppressLint("NewApi")
26 | public class QtService extends Service {
27 |
28 | /* Private variables */
29 |
30 | public Boolean started=false;
31 | private String[] m_qtLibs = null;
32 | private DexClassLoader m_classLoader = null;
33 |
34 | private Class m_class = QtServiceActivity.class;
35 |
36 | private static ServiceInfo m_serviceInfo = null;
37 | protected static NotificationManager m_notificationManager;
38 | protected static Notification.Builder m_builder;
39 | protected static PendingIntent pi;
40 | private static QtService m_instance;
41 | private static String m_lib_name;
42 |
43 | private static final String ERROR_CODE_KEY = "error.code";
44 | private static final String DEX_PATH_KEY = "dex.path";
45 | private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
46 | private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
47 | private static final String MAIN_LIBRARY_KEY = "main.library";
48 | private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
49 | private static final String LOADER_CLASS_NAME_KEY = "loader.class.name";
50 | private static final String LIB_PATH_KEY = "lib.path";
51 | private static final String ENVIRONMENT_VARIABLES_KEY = "env.variable";
52 |
53 | /* Service methods */
54 |
55 | public void onCreate (){
56 |
57 | Log.w(getClass().getName(), "Service created ...");
58 |
59 | m_instance = this;
60 |
61 | try{
62 | ComponentName myService = new ComponentName(this, this.getClass());
63 | m_serviceInfo = getPackageManager().getServiceInfo(myService, PackageManager.GET_META_DATA);
64 | m_lib_name = splitCamelCase (m_serviceInfo.metaData.getString("android.app.lib_name"));
65 | }
66 | catch (Exception e) {
67 |
68 | e.printStackTrace();
69 | }
70 | }
71 |
72 | public IBinder onBind(Intent intent) {
73 |
74 | return null;
75 | }
76 |
77 | @SuppressWarnings("deprecation")
78 | public int onStartCommand(Intent intent, int flags, int startId)
79 | {
80 |
81 | /* Notification */
82 |
83 | createNotification();
84 |
85 | /* Start the app */
86 |
87 | startApp();
88 |
89 | /* Return */
90 |
91 | return(START_STICKY);
92 | }
93 |
94 | public void onDestroy(){
95 |
96 | Log.w(getClass().getName(), "Service destroyed ...");
97 |
98 | Process.killProcess(Process.myPid());
99 | }
100 |
101 | /* Internals methods */
102 |
103 | private void startApp(){
104 |
105 | if (!started){
106 |
107 | started = true;
108 | Toast.makeText(getBaseContext(), m_lib_name + " starting", Toast.LENGTH_LONG).show();
109 |
110 | try{
111 |
112 | if (m_serviceInfo.metaData.containsKey("android.app.qt_libs_resource_id")) {
113 | int resourceId = m_serviceInfo.metaData.getInt("android.app.qt_libs_resource_id");
114 | m_qtLibs = getResources().getStringArray(resourceId);
115 | }
116 |
117 | if (m_serviceInfo.metaData.containsKey("android.app.use_local_qt_libs")
118 | && m_serviceInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) {
119 | ArrayList libraryList = new ArrayList();
120 |
121 |
122 | String localPrefix = "/data/local/tmp/qt/";
123 | if (m_serviceInfo.metaData.containsKey("android.app.libs_prefix"))
124 | localPrefix = m_serviceInfo.metaData.getString("android.app.libs_prefix");
125 |
126 | boolean bundlingQtLibs = false;
127 | if (m_serviceInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
128 | && m_serviceInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
129 | localPrefix = getApplicationInfo().dataDir + "/";
130 | bundlingQtLibs = true;
131 | }
132 |
133 | if (m_qtLibs != null) {
134 | for (int i=0;i 0) {
150 | if (dexPaths.length() > 0)
151 | dexPaths += pathSeparator;
152 | dexPaths += localPrefix + jar;
153 | }
154 | }
155 | }
156 |
157 | Bundle loaderParams = new Bundle();
158 | loaderParams.putInt(ERROR_CODE_KEY, 0);
159 | loaderParams.putString(DEX_PATH_KEY, dexPaths);
160 | loaderParams.putString(LOADER_CLASS_NAME_KEY, "org.qtproject.qt5.android.QtServiceDelegate");
161 | loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, "");
162 | if (m_serviceInfo.metaData.containsKey("android.app.static_init_classes")) {
163 | loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY,
164 | m_serviceInfo.metaData.getString("android.app.static_init_classes").split(":"));
165 | }
166 | loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList);
167 |
168 | loadApplication(loaderParams);
169 | return;
170 | }
171 | }
172 | catch (Exception e) {
173 | started = false;
174 | e.printStackTrace();
175 | }
176 | }
177 | }
178 |
179 | @SuppressLint("NewApi")
180 | public void loadApplication(Bundle loaderParams){
181 |
182 | try{
183 |
184 | ArrayList libs = new ArrayList();
185 | if ( m_serviceInfo.metaData.containsKey("android.app.bundled_libs_resource_id") )
186 | libs.addAll(Arrays.asList(getResources().getStringArray(m_serviceInfo.metaData.getInt("android.app.bundled_libs_resource_id"))));
187 |
188 | String libName = null;
189 | if ( m_serviceInfo.metaData.containsKey("android.app.lib_name") ) {
190 | libName = m_serviceInfo.metaData.getString("android.app.lib_name");
191 | loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function
192 | }
193 |
194 | loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs);
195 | loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, "");
196 |
197 | m_classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files
198 | getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written.
199 | loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists)
200 | getClassLoader()); // parent loader
201 |
202 | String loaderClassName = loaderParams.getString(LOADER_CLASS_NAME_KEY);
203 |
204 | Log.w(getClass().getName(), "Loader : " + loaderClassName);
205 |
206 | Class> loaderClass = m_classLoader.loadClass(loaderClassName); // load QtLoader class
207 | Object qtLoader = loaderClass.newInstance(); // create an instance
208 |
209 | Method perpareAppMethod = qtLoader.getClass().getMethod("loadApplication",
210 | Service.class,
211 | ClassLoader.class,
212 | Bundle.class);
213 |
214 | if (!(Boolean)perpareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams))
215 | throw new Exception("");
216 |
217 | // now load the application library so it's accessible from this class loader
218 | if (libName != null)
219 | System.loadLibrary(libName);
220 |
221 | Method startAppMethod=qtLoader.getClass().getMethod("startApplication");
222 | if (!(Boolean)startAppMethod.invoke(qtLoader))
223 | throw new Exception("");
224 |
225 |
226 | }
227 | catch (Exception e) {
228 | e.printStackTrace();
229 | }
230 | }
231 |
232 | /* Activity class */
233 |
234 | public void setActivityClass(Class cl){
235 |
236 | m_class = cl;
237 | }
238 |
239 |
240 | /* Notification methods */
241 |
242 | protected void createNotification(){
243 |
244 | Notification note=new Notification(m_serviceInfo.metaData.getInt("android.app.notificon"),"",System.currentTimeMillis());
245 |
246 | Intent i=new Intent(m_instance, m_class);
247 | i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
248 |
249 | pi=PendingIntent.getActivity(this, 0,
250 | i, 0);
251 |
252 | note.setLatestEventInfo(this, m_lib_name ,
253 | "Running",
254 | pi);
255 | note.flags|=Notification.FLAG_NO_CLEAR;
256 |
257 | startForeground(1337, note);
258 | }
259 |
260 | public static void notify(String s)
261 | {
262 | if (m_notificationManager == null) {
263 |
264 | m_notificationManager = (NotificationManager)m_instance.getSystemService(Context.NOTIFICATION_SERVICE);
265 | m_builder = new Notification.Builder(m_instance);
266 | m_builder.setSmallIcon(m_serviceInfo.metaData.getInt("android.app.notificon"));
267 | m_builder.setContentTitle(m_lib_name);
268 | m_builder.setContentIntent(pi);
269 | }
270 |
271 | m_builder.setContentText(s);
272 | Notification note = m_builder.build();
273 | note.flags |= Notification.FLAG_NO_CLEAR;
274 |
275 | m_notificationManager.notify(1337, note);
276 | }
277 |
278 | /* Helpers */
279 |
280 | static String splitCamelCase(String sp) {
281 |
282 | String s = Character.toUpperCase(sp.charAt(0)) + sp.substring(1);
283 |
284 | return s.replaceAll(
285 | String.format("%s|%s|%s",
286 | "(?<=[A-Z])(?=[A-Z][a-z])",
287 | "(?<=[^A-Z])(?=[A-Z])",
288 | "(?<=[A-Za-z])(?=[^A-Za-z])"
289 | ),
290 | " "
291 | );
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/android/src/org/qtproject/qt5/android/addons/qtserviceapp/QtServiceActivity.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtserviceapp;
2 |
3 | import R;
4 |
5 | import android.app.Activity;
6 | import android.app.ActivityManager;
7 | import android.app.ActivityManager.RunningServiceInfo;
8 | import android.os.Bundle;
9 | import android.content.ComponentName;
10 | import android.content.Context;
11 | import android.content.Intent;
12 | import android.content.SharedPreferences;
13 | import android.content.SharedPreferences.Editor;
14 | import android.content.pm.ActivityInfo;
15 | import android.content.pm.PackageManager;
16 | import android.content.pm.ServiceInfo;
17 | import android.content.pm.PackageManager.NameNotFoundException;
18 | import android.widget.CompoundButton;
19 | import android.widget.Switch;
20 |
21 | public class QtServiceActivity extends Activity {
22 |
23 | private Intent i;
24 | private Class m_class = QtService.class;
25 |
26 | @Override
27 | public void onCreate(Bundle savedInstanceState)
28 | {
29 |
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.serviceconfigactivity);
32 |
33 | i = new Intent(this, m_class);
34 |
35 | final Switch sRun = (Switch) findViewById(R.id.switch_run);
36 | sRun.setChecked(isMyServiceRunning());
37 | sRun.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
38 |
39 | @Override
40 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
41 |
42 | if (isChecked)
43 | startService(i);
44 | else
45 | stopService(i);
46 | }
47 | });
48 |
49 | ComponentName myActivity = new ComponentName(this, this.getClass());
50 | ActivityInfo activityInfo = null;
51 | try {
52 | activityInfo = getPackageManager().getActivityInfo(myActivity, PackageManager.GET_META_DATA);
53 | }
54 | catch (NameNotFoundException e) {
55 | e.printStackTrace();
56 | }
57 |
58 | SharedPreferences settings = getBaseContext().getSharedPreferences(activityInfo.metaData.getString("android.app.lib_name"), 0);
59 | final Editor editor = settings.edit();
60 |
61 | boolean startup = settings.getBoolean("runStartup", true);
62 |
63 | final Switch sRunStartup = (Switch) findViewById(R.id.switch_runstartup);
64 | sRunStartup.setChecked(startup);
65 | sRunStartup.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
66 |
67 | @Override
68 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
69 |
70 | editor.putBoolean("runStartup", isChecked);
71 | editor.commit();
72 | }
73 | });
74 | }
75 |
76 | private boolean isMyServiceRunning() {
77 | ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
78 | for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
79 | if (m_class.getName().equals(service.service.getClassName())) {
80 | return true;
81 | }
82 | }
83 | return false;
84 | }
85 |
86 | /* Activity class */
87 |
88 | public void setActivityClass(Class cl){
89 |
90 | m_class = cl;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/android/src/org/qtproject/qt5/android/addons/qtserviceapp/QtServiceBroadcastReceiver.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtserviceapp;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.ComponentName;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.SharedPreferences;
8 | import android.content.pm.ActivityInfo;
9 | import android.content.pm.PackageManager;
10 | import android.os.Bundle;
11 | import android.util.Log;
12 |
13 | public class QtServiceBroadcastReceiver extends BroadcastReceiver {
14 |
15 | private Class m_class = QtService.class;
16 |
17 | @Override
18 | public void onReceive(Context context, Intent intent) {
19 |
20 | Log.w("Qt", "Starting service");
21 |
22 | try
23 | {
24 | ActivityInfo activityInfo = context.getPackageManager().getReceiverInfo(new ComponentName(context, this.getClass()), PackageManager.GET_META_DATA);
25 | Bundle meta = activityInfo.metaData;
26 |
27 | SharedPreferences settings = context.getSharedPreferences(meta.getString("android.app.lib_name"), 0);
28 | boolean startup = settings.getBoolean("runStartup", true);
29 |
30 | if (startup){
31 |
32 | Intent i = new Intent(context, m_class);
33 | context.startService(i);
34 | }
35 | }
36 | catch (Exception e)
37 | {
38 | Log.e("Qt", "Can't create service" + e);
39 | }
40 |
41 | }
42 |
43 | /* Activity class */
44 |
45 | public void setActivityClass(Class cl){
46 |
47 | m_class = cl;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/example/MyTestService/MyTestService.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2014-03-26T12:42:37
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core
8 |
9 | QT -= gui
10 |
11 | TARGET = MyTestService
12 | CONFIG += console
13 | CONFIG -= app_bundle
14 |
15 | TEMPLATE = app
16 |
17 |
18 | SOURCES += main.cpp
19 |
20 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
21 |
22 | OTHER_FILES += \
23 | android/AndroidManifest.xml
24 |
--------------------------------------------------------------------------------
/example/MyTestService/android/Activity-AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/example/MyTestService/android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/example/MyTestService/android/README.md:
--------------------------------------------------------------------------------
1 | Qt Android service and activity helper classes
2 | ==============================================
3 |
4 | - First create a project in QtCreator QtQuick or QtWidget for activity based application or "Qt Console Application" for a service based one
5 |
6 | - In project - Android - Run - Advanced actions, create an AndroidManifest
7 | or put the following lines to your .pro
8 |
9 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
10 |
11 | OTHER_FILES += \
12 | android/AndroidManifest.xml
13 |
14 |
15 | - ! Only bundled Qt librairies have been tested ...
16 |
17 | - Replace the "android" folder that qtcreator have created in your project by this one or if your edited the .pro just put it in your project.
18 |
19 | - Run ./setup.sh in the android folder
20 | - Put your icon.png and notificon.png
21 |
--------------------------------------------------------------------------------
/example/MyTestService/android/Service-AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/example/MyTestService/android/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH:= $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 |
5 | LOCAL_MODULE := QtAndroidService
6 | LOCAL_CFLAGS := -Werror
7 | LOCAL_SRC_FILES := QtAndroidService.cpp
8 | LOCAL_LDLIBS := -llog
9 |
10 | include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------------------------------
/example/MyTestService/android/jni/QtAndroidService.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | // Global variables
12 |
13 | static jclass m_applicationClass = NULL;
14 | static jobject m_classLoaderObject = NULL;
15 | static jmethodID m_loadClassMethodID = NULL;
16 | static jobject m_resourcesObj;
17 | static jobject m_activityObject = NULL;
18 |
19 | extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application
20 | static JavaVM *m_javaVM = NULL;
21 | static Main m_main = NULL;
22 | static void *m_mainLibraryHnd = NULL;
23 |
24 | static const char m_classErrorMsg[] = "Can't find class \"%s\"";
25 | static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
26 |
27 | // Methods definition
28 |
29 | static jboolean startQtAndroidPlugin(JNIEnv* env, jobject object /*, jobject applicationAssetManager*/)
30 | {
31 | return 1;
32 | }
33 |
34 | static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
35 | jint /*widthPixels*/, jint /*heightPixels*/,
36 | jint desktopWidthPixels, jint desktopHeightPixels,
37 | jdouble xdpi, jdouble ydpi, jdouble scaledDensity)
38 | {}
39 |
40 | // Methods definition
41 |
42 | static void *startMainMethod(void *ar)
43 | {
44 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Calling main method");
45 |
46 | char *argv[] = { NULL};
47 | int argc = sizeof(argv) / sizeof(char*) - 1;
48 |
49 | int ret = m_main(argc, argv);
50 |
51 | return NULL;
52 | }
53 |
54 | static jboolean startQtApplication(JNIEnv *env, jobject object, jstring paramsString, jstring environmentString)
55 | {
56 | // Get native
57 |
58 | const char *nativeEnvironmentString = (env)->GetStringUTFChars(environmentString, NULL); // C++
59 | const char *nativeParamsString = (env)->GetStringUTFChars(paramsString, NULL); // C++
60 |
61 | // Print info
62 |
63 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Starting the Qt service");
64 |
65 | char cwd[1024];
66 | if (getcwd(cwd, sizeof(cwd)) != NULL)
67 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Current working dir : %s", cwd);
68 |
69 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Param : %s", nativeParamsString );
70 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Env : %s", nativeEnvironmentString );
71 |
72 | // Start
73 |
74 | m_mainLibraryHnd = NULL;
75 |
76 | // Obtain a handle to the main library (the library that contains the main() function).
77 | // This library should already be loaded, and calling dlopen() will just return a reference to it.
78 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Trying to open %s", nativeParamsString);
79 | m_mainLibraryHnd = dlopen(nativeParamsString, 0);
80 |
81 | if (m_mainLibraryHnd == NULL) {
82 |
83 | __android_log_print(ANDROID_LOG_INFO, "Qt", "No main library was specified; searching entire process (this is slow!)");
84 | m_main = (Main)dlsym(RTLD_DEFAULT, "main");
85 | }
86 | else {
87 |
88 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Getting the main method from handler");
89 | m_main = (Main)dlsym(m_mainLibraryHnd, "main");
90 | }
91 |
92 |
93 | if (!m_main) {
94 |
95 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Could not find main method");
96 | return 0;
97 | }
98 | else{
99 |
100 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Main method found, starting");
101 | }
102 |
103 |
104 | pthread_t appThread;
105 | return pthread_create(&appThread, NULL, startMainMethod, NULL) == 0;
106 |
107 | //env->ReleaseStringUTFChars(environmentString, nativeString);
108 | }
109 |
110 | static void quitQtAndroidPlugin(JNIEnv *env, jclass clazz)
111 | {
112 |
113 | }
114 |
115 | static void terminateQt(JNIEnv *env, jclass clazz)
116 | {
117 |
118 | }
119 |
120 | // Native methods
121 |
122 | static JNINativeMethod methods[] = {
123 | {"startQtAndroidPlugin", "()Z", (void *)startQtAndroidPlugin},
124 | {"setDisplayMetrics", "(IIIIDDD)V", (void *)setDisplayMetrics},
125 | {"startQtApplication", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)startQtApplication},
126 | {"quitQtAndroidPlugin", "()V", (void *)quitQtAndroidPlugin},
127 | {"terminateQt", "()V", (void *)terminateQt}
128 | };
129 |
130 |
131 | // Helpers functions
132 |
133 | #define FIND_AND_CHECK_CLASS(CLASS_NAME) \
134 | clazz = env->FindClass(CLASS_NAME); \
135 | if (!clazz) { \
136 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_classErrorMsg, CLASS_NAME); \
137 | return JNI_FALSE; \
138 | }
139 |
140 | #define GET_AND_CHECK_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
141 | VAR = env->GetMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \
142 | if (!VAR) { \
143 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \
144 | return JNI_FALSE; \
145 | }
146 |
147 | #define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
148 | VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \
149 | if (!VAR) { \
150 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE); \
151 | return JNI_FALSE; \
152 | }
153 |
154 | #define GET_AND_CHECK_FIELD(VAR, CLASS, FIELD_NAME, FIELD_SIGNATURE) \
155 | VAR = env->GetFieldID(CLASS, FIELD_NAME, FIELD_SIGNATURE); \
156 | if (!VAR) { \
157 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, FIELD_NAME, FIELD_SIGNATURE); \
158 | return JNI_FALSE; \
159 | }
160 |
161 | #define GET_AND_CHECK_STATIC_FIELD(VAR, CLASS, FIELD_NAME, FIELD_SIGNATURE) \
162 | VAR = env->GetStaticFieldID(CLASS, FIELD_NAME, FIELD_SIGNATURE); \
163 | if (!VAR) { \
164 | __android_log_print(ANDROID_LOG_FATAL, "Qt", m_methodErrorMsg, FIELD_NAME, FIELD_SIGNATURE); \
165 | return JNI_FALSE; \
166 | }
167 |
168 | // On load
169 |
170 | jint JNICALL JNI_OnLoad(JavaVM *vm, void *ld)
171 | {
172 |
173 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Qt Android service wrapper start");
174 |
175 | JNIEnv* env;
176 | if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) {
177 | __android_log_print(ANDROID_LOG_FATAL, "Qt", "Can't get env in wrapper start"); \
178 | return -1;
179 | }
180 |
181 | m_javaVM = vm;
182 |
183 | jclass clazz;
184 | FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative");
185 | m_applicationClass = static_cast(env->NewGlobalRef(clazz));
186 |
187 | __android_log_print(ANDROID_LOG_INFO, "Qt", "Registering native classes for service wrapper");
188 |
189 | if (env->RegisterNatives(m_applicationClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
190 | __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed for service wrapper");
191 | return JNI_FALSE;
192 | }
193 |
194 | return JNI_VERSION_1_4;
195 | }
196 |
197 |
198 |
--------------------------------------------------------------------------------
/example/MyTestService/android/libs/armeabi/libQtAndroidService.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/libs/armeabi/libQtAndroidService.so
--------------------------------------------------------------------------------
/example/MyTestService/android/libs/guava-10.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/libs/guava-10.0.1.jar
--------------------------------------------------------------------------------
/example/MyTestService/android/obj/local/armeabi/libQtAndroidService.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/obj/local/armeabi/libQtAndroidService.so
--------------------------------------------------------------------------------
/example/MyTestService/android/obj/local/armeabi/libstdc++.a:
--------------------------------------------------------------------------------
1 | !
2 |
--------------------------------------------------------------------------------
/example/MyTestService/android/obj/local/armeabi/objs/QtAndroidService/QtAndroidService.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/obj/local/armeabi/objs/QtAndroidService/QtAndroidService.o
--------------------------------------------------------------------------------
/example/MyTestService/android/obj/local/armeabi/objs/QtAndroidService/QtAndroidService.o.d:
--------------------------------------------------------------------------------
1 | /home/christophe/Devel/Qt/MyTestService/android/obj/local/armeabi/objs/QtAndroidService/QtAndroidService.o: \
2 | /home/christophe/Devel/Qt/MyTestService/android/jni/QtAndroidService.cpp \
3 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/dlfcn.h \
4 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/cdefs.h \
5 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/cdefs_elf.h \
6 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/android/api-level.h \
7 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/pthread.h \
8 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/time.h \
9 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/time.h \
10 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/types.h \
11 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/stdint.h \
12 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/_types.h \
13 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/_types.h \
14 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/posix_types.h \
15 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/stddef.h \
16 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/compiler.h \
17 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/posix_types.h \
18 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/types.h \
19 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/types.h \
20 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/kernel.h \
21 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/sysmacros.h \
22 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/time.h \
23 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/siginfo.h \
24 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm-generic/siginfo.h \
25 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/signal.h \
26 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/limits.h \
27 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/limits.h \
28 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/limits.h \
29 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/internal_types.h \
30 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/limits.h \
31 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/syslimits.h \
32 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/page.h \
33 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/string.h \
34 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/malloc.h \
35 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/signal.h \
36 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm-generic/signal.h \
37 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sched.h \
38 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/stdlib.h \
39 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/alloca.h \
40 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/strings.h \
41 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/memory.h \
42 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/unistd.h \
43 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/select.h \
44 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/sysconf.h \
45 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/capability.h \
46 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/pathconf.h \
47 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/jni.h \
48 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/android/log.h
49 |
50 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/dlfcn.h:
51 |
52 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/cdefs.h:
53 |
54 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/cdefs_elf.h:
55 |
56 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/android/api-level.h:
57 |
58 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/pthread.h:
59 |
60 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/time.h:
61 |
62 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/time.h:
63 |
64 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/types.h:
65 |
66 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/stdint.h:
67 |
68 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/_types.h:
69 |
70 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/_types.h:
71 |
72 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/posix_types.h:
73 |
74 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/stddef.h:
75 |
76 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/compiler.h:
77 |
78 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/posix_types.h:
79 |
80 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/types.h:
81 |
82 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/types.h:
83 |
84 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/kernel.h:
85 |
86 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/sysmacros.h:
87 |
88 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/time.h:
89 |
90 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/siginfo.h:
91 |
92 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm-generic/siginfo.h:
93 |
94 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/signal.h:
95 |
96 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/limits.h:
97 |
98 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/limits.h:
99 |
100 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/limits.h:
101 |
102 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/internal_types.h:
103 |
104 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/machine/limits.h:
105 |
106 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/syslimits.h:
107 |
108 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/page.h:
109 |
110 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/string.h:
111 |
112 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/malloc.h:
113 |
114 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm/signal.h:
115 |
116 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/asm-generic/signal.h:
117 |
118 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sched.h:
119 |
120 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/stdlib.h:
121 |
122 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/alloca.h:
123 |
124 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/strings.h:
125 |
126 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/memory.h:
127 |
128 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/unistd.h:
129 |
130 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/select.h:
131 |
132 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/sys/sysconf.h:
133 |
134 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/linux/capability.h:
135 |
136 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/pathconf.h:
137 |
138 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/jni.h:
139 |
140 | /opt/Android/android-ndk-r9b/platforms/android-3/arch-arm/usr/include/android/log.h:
141 |
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-hdpi-v11/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-hdpi-v11/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-hdpi/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-hdpi/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-mdpi-v11/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-mdpi-v11/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-mdpi/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-mdpi/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-xhdpi-v11/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-xhdpi-v11/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-xhdpi/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-xhdpi/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-xxhdpi-v11/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-xxhdpi-v11/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-xxhdpi/notificon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-xxhdpi/notificon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/drawable-xxxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/think-free-backup/QtAndroidHelper/e50daeaa54c9a08633f645e5cd174f3c1f4a2ba4/example/MyTestService/android/res/drawable-xxxhdpi/icon.png
--------------------------------------------------------------------------------
/example/MyTestService/android/res/layout/serviceconfigactivity.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
21 |
22 |
30 |
31 |
40 |
41 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/example/MyTestService/android/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/MyTestService/android/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/example/MyTestService/android/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This script will setup the android folder for an activity or a service based qt application
4 |
5 | # Functions
6 |
7 | function setup(){
8 |
9 | clear
10 |
11 | echo ""
12 | echo "Please enter your package name (ex : org.qt-project.myqtapplication) : "
13 | read package
14 |
15 | app=`ls ../*.pro | cut -d '/' -f 2 | cut -d '.' -f 1`
16 |
17 | if [ "$app" == "" ];
18 | then
19 | echo "Can't find .pro in ../ exiting"
20 | exit 1
21 | fi
22 |
23 | echo ""
24 | echo "Do you want to create an activity or a service based application ? [a/s]"
25 | read tp
26 |
27 | if [ "$tp" == "a" ];
28 | then
29 |
30 | activity $package $app
31 |
32 | elif [ "$tp" == "s" ];
33 | then
34 |
35 | service $package $app
36 |
37 | else
38 |
39 | clear
40 | echo "Bad selection"
41 | sleep 2
42 | setup
43 | fi
44 | }
45 |
46 | function activity(){
47 |
48 | echo "You've selected an activity based application"
49 |
50 | cp Activity-AndroidManifest.xml AndroidManifest.xml
51 |
52 | echo "Cleaning un-necesary files"
53 | #################################
54 |
55 | rm -rf src/org/qtproject/qt5/android/addons/qtserviceapp
56 | rm src/org/qtproject/qt5/android/QtServiceDelegate.java
57 |
58 | echo "Configuring manifest"
59 | ###########################
60 |
61 | sed -i "s|org.qtproject.qt5.android.addons|$1|" AndroidManifest.xml
62 | sed -i "s|qtactivityapp.QtServiceActivity|$2Activity|g" AndroidManifest.xml
63 | sed -i "s|qtactivityapp.QtService|$2Service|g" AndroidManifest.xml
64 |
65 | echo "Creating package folders"
66 | ###############################
67 |
68 | fld=src/$(sed 's|\.|/|g' <<< $1)
69 | mkdir -p $fld
70 |
71 |
72 | echo "Configuring activity"
73 | ###########################
74 |
75 |
76 | echo ""
77 | echo "Do you want to use a sticky notification with service ? [y/n]"
78 | read sticky
79 |
80 |
81 | echo "package $1;" >> $fld/$2Activity.java
82 |
83 | echo "import org.qtproject.qt5.android.addons.qtactivityapp.QtServiceActivity;" >> $fld/$2Activity.java
84 | echo "import org.qtproject.qt5.android.addons.qtactivityapp.QtService;" >> $fld/$2Activity.java
85 | echo "import android.os.Bundle;" >> $fld/$2Activity.java
86 | echo "import android.content.Intent;" >> $fld/$2Activity.java
87 | echo "import android.content.ComponentName;" >> $fld/$2Activity.java
88 | echo "import android.util.Log;" >> $fld/$2Activity.java
89 |
90 | echo "public class $2Activity extends QtServiceActivity" >> $fld/$2Activity.java
91 | echo "{" >> $fld/$2Activity.java
92 | echo " public void onCreate(Bundle savedInstanceState)" >> $fld/$2Activity.java
93 | echo " {" >> $fld/$2Activity.java
94 | echo " Log.w(getClass().getName(), "Starting config editor");" >> $fld/$2Activity.java
95 |
96 | if [ "$sticky" == "y" ];
97 | then
98 | echo " super.setServiceClass($2Service.java);" >> $fld/$2Activity.java
99 | else
100 | echo " super.setServiceClass(null);" >> $fld/$2Activity.java
101 | fi
102 |
103 | echo " super.onCreate(savedInstanceState);" >> $fld/$2Activity.java
104 | echo " }" >> $fld/$2Activity.java
105 | echo "}" >> $fld/$2Activity.java
106 |
107 |
108 | echo "Configuring service"
109 | ##########################
110 |
111 | echo "package $1;" >> $fld/$2Service.java
112 |
113 | echo "import org.qtproject.qt5.android.addons.qtactivityapp.QtService;" >> $fld/$2Service.java
114 | echo "import android.util.Log;" >> $fld/$2Service.java
115 |
116 | echo "public class $2Service extends QtService" >> $fld/$2Service.java
117 | echo "{" >> $fld/$2Service.java
118 | echo " public void onCreate()" >> $fld/$2Service.java
119 | echo " {" >> $fld/$2Service.java
120 | echo " Log.w(getClass().getName(), "Starting config editor service");" >> $fld/$2Service.java
121 | echo " super.setActivityClass($2Activity.class);" >> $fld/$2Service.java
122 | echo " super.onCreate();" >> $fld/$2Service.java
123 | echo " }" >> $fld/$2Service.java
124 | echo "}" >> $fld/$2Service.java
125 |
126 | }
127 |
128 | function service(){
129 |
130 | echo "You've selected a service based application"
131 | ##################################################
132 |
133 | cp Service-AndroidManifest.xml AndroidManifest.xml
134 |
135 | echo "Compiling helper librairy"
136 | ################################
137 |
138 | cd jni
139 | ndk-build
140 | cd ..
141 |
142 | echo "Cleaning un-necesary files"
143 | #################################
144 |
145 | rm -rf src/org/qtproject/qt5/android/addons/qtactivityapp
146 |
147 | echo "Configuring manifest"
148 | ###########################
149 |
150 | sed -i "s|org.qtproject.qt5.android.addons|$1|" AndroidManifest.xml
151 | sed -i "s|qtserviceapp.QtService|$2|g" AndroidManifest.xml
152 | sed -i "s|QtServiceActivity|$2|g" AndroidManifest.xml
153 |
154 | sed -i "s|import R;|import $1.R;|" src/org/qtproject/qt5/android/addons/qtserviceapp/QtServiceActivity.java # FIXME !!!!
155 |
156 |
157 | echo "Creating package folders"
158 | ###############################
159 |
160 | fld=src/$(sed 's|\.|/|g' <<< $1)
161 | mkdir -p $fld
162 |
163 |
164 | echo "Configuring Service"
165 | ##########################
166 |
167 | echo "package $1;" >> $fld/$2.java
168 |
169 | echo "import org.qtproject.qt5.android.addons.qtserviceapp.QtService;" >> $fld/$2.java
170 | echo "import android.util.Log;" >> $fld/$2.java
171 |
172 | echo "public class $2 extends QtService {" >> $fld/$2.java
173 |
174 | echo " public void onCreate()" >> $fld/$2.java
175 | echo " {" >> $fld/$2.java
176 | echo " Log.w(getClass().getName(), \"Starting datasync service\");" >> $fld/$2.java
177 | echo " super.setActivityClass($2Activity.class);" >> $fld/$2.java
178 | echo " super.onCreate();" >> $fld/$2.java
179 | echo " }" >> $fld/$2.java
180 | echo "}" >> $fld/$2.java
181 | echo "" >> $fld/$2.java
182 |
183 |
184 | echo "Configuring service activity"
185 | ###################################
186 |
187 | echo "package $1;" >> $fld/$2Activity.java
188 |
189 | echo "import $1.R;" >> $fld/$2Activity.java
190 |
191 | echo "import org.qtproject.qt5.android.addons.qtserviceapp.QtServiceActivity;" >> $fld/$2Activity.java
192 |
193 | echo "import android.os.Bundle;" >> $fld/$2Activity.java
194 | echo "import android.util.Log;" >> $fld/$2Activity.java
195 |
196 | echo "public class $2Activity extends QtServiceActivity {" >> $fld/$2Activity.java
197 |
198 | echo " @Override" >> $fld/$2Activity.java
199 | echo " public void onCreate(Bundle savedInstanceState)" >> $fld/$2Activity.java
200 | echo " {" >> $fld/$2Activity.java
201 | echo " Log.w(getClass().getName(), \"Starting datasync service activity\");" >> $fld/$2Activity.java
202 | echo " super.setActivityClass($2.class);" >> $fld/$2Activity.java
203 | echo " super.onCreate(savedInstanceState);" >> $fld/$2Activity.java
204 | echo " }" >> $fld/$2Activity.java
205 | echo "}" >> $fld/$2Activity.java
206 | echo "" >> $fld/$2Activity.java
207 |
208 |
209 | echo "Configuring broadcast receiver (to be run at startup)"
210 | ############################################################
211 |
212 | echo "package $1;" >> $fld/$2BroadcastReceiver.java
213 |
214 | echo "import org.qtproject.qt5.android.addons.qtserviceapp.QtServiceBroadcastReceiver;" >> $fld/$2BroadcastReceiver.java
215 |
216 | echo "import android.content.Context;" >> $fld/$2BroadcastReceiver.java
217 | echo "import android.content.Intent;" >> $fld/$2BroadcastReceiver.java
218 | echo "import android.util.Log;" >> $fld/$2BroadcastReceiver.java
219 |
220 | echo "public class $2BroadcastReceiver extends QtServiceBroadcastReceiver {" >> $fld/$2BroadcastReceiver.java
221 |
222 | echo " @Override" >> $fld/$2BroadcastReceiver.java
223 | echo " public void onReceive(Context context, Intent intent) {" >> $fld/$2BroadcastReceiver.java
224 |
225 | echo " Log.w(getClass().getName(), \"Broadcast received for Comservice\");" >> $fld/$2BroadcastReceiver.java
226 |
227 | echo " super.setActivityClass($2.class);" >> $fld/$2BroadcastReceiver.java
228 | echo " super.onReceive(context, intent);" >> $fld/$2BroadcastReceiver.java
229 | echo " }" >> $fld/$2BroadcastReceiver.java
230 | echo "}" >> $fld/$2BroadcastReceiver.java
231 | echo "" >> $fld/$2BroadcastReceiver.java
232 | }
233 |
234 | # Main
235 |
236 | clear
237 | echo ""
238 | echo "This script will allow you to setup a qt activity based application with a service that run a sticky notification or a service based application (without grafical interface)"
239 | echo "First create a qt project in qtcreator "
240 | echo "Please ensure that ndk-build (android-ndk) is in your path before continuing"
241 | echo ""
242 | echo "Press any key to continue"
243 | read
244 |
245 | setup
246 |
247 | clear
248 | echo "Almost done, please create an icon.png and a notificon.png for every resolution you want to support in the res folder"
249 | echo "You can use : http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html to create it"
250 |
--------------------------------------------------------------------------------
/example/MyTestService/android/src/com/mycompany/test1/MyTestService.java:
--------------------------------------------------------------------------------
1 | package com.mycompany.test1;
2 | import org.qtproject.qt5.android.addons.qtserviceapp.QtService;
3 | import android.util.Log;
4 | public class MyTestService extends QtService {
5 | public void onCreate()
6 | {
7 | Log.w(getClass().getName(), "Starting datasync service");
8 | super.setActivityClass(MyTestServiceActivity.class);
9 | super.onCreate();
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/example/MyTestService/android/src/com/mycompany/test1/MyTestServiceActivity.java:
--------------------------------------------------------------------------------
1 | package com.mycompany.test1;
2 | import com.mycompany.test1.R;
3 | import org.qtproject.qt5.android.addons.qtserviceapp.QtServiceActivity;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | public class MyTestServiceActivity extends QtServiceActivity {
7 | @Override
8 | public void onCreate(Bundle savedInstanceState)
9 | {
10 | Log.w(getClass().getName(), "Starting datasync service activity");
11 | super.setActivityClass(MyTestService.class);
12 | super.onCreate(savedInstanceState);
13 | }
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/example/MyTestService/android/src/com/mycompany/test1/MyTestServiceBroadcastReceiver.java:
--------------------------------------------------------------------------------
1 | package com.mycompany.test1;
2 | import org.qtproject.qt5.android.addons.qtserviceapp.QtServiceBroadcastReceiver;
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.util.Log;
6 | public class MyTestServiceBroadcastReceiver extends QtServiceBroadcastReceiver {
7 | @Override
8 | public void onReceive(Context context, Intent intent) {
9 | Log.w(getClass().getName(), "Broadcast received for Comservice");
10 | super.setActivityClass(MyTestService.class);
11 | super.onReceive(context, intent);
12 | }
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/example/MyTestService/android/src/org/qtproject/qt5/android/QtServiceDelegate.java:
--------------------------------------------------------------------------------
1 |
2 | package org.qtproject.qt5.android;
3 |
4 | import java.io.File;
5 | import java.io.FileWriter;
6 | import java.io.IOException;
7 | import java.lang.reflect.Method;
8 | import java.util.ArrayList;
9 | import java.util.Iterator;
10 |
11 | import android.app.Service;
12 | import android.content.Context;
13 | import android.content.pm.ApplicationInfo;
14 | import android.content.pm.PackageManager;
15 | import android.content.pm.PackageManager.NameNotFoundException;
16 | import android.content.res.Configuration;
17 | import android.graphics.Rect;
18 | import android.os.Build;
19 | import android.os.Bundle;
20 | import android.util.Log;
21 |
22 | public class QtServiceDelegate
23 | {
24 | private Service m_service = null;
25 |
26 | private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
27 | private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
28 | private static final String MAIN_LIBRARY_KEY = "main.library";
29 | private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
30 | private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
31 | private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
32 | private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
33 |
34 | private static String m_environmentVariables = null;
35 | private static String m_applicationParameters = null;
36 |
37 | private String m_mainLib;
38 |
39 | public boolean loadApplication(Service service, ClassLoader classLoader, Bundle loaderParams)
40 | {
41 | if (!loaderParams.containsKey(NATIVE_LIBRARIES_KEY))
42 | Log.w(getClass().getName(), "Missing parameters1 in loaderParams");
43 |
44 | if (!loaderParams.containsKey(BUNDLED_LIBRARIES_KEY))
45 | Log.w(getClass().getName(), "Missing parameters2 in loaderParams");
46 |
47 | /// check parameters integrity
48 | if (!loaderParams.containsKey(NATIVE_LIBRARIES_KEY)
49 | || !loaderParams.containsKey(BUNDLED_LIBRARIES_KEY)) {
50 |
51 | Log.w(getClass().getName(), "Missing parameters in loaderParams");
52 | return false;
53 | }
54 |
55 | m_service = service;
56 | //QtNative.setActivity(m_activity, this);
57 | QtNative.setClassLoader(classLoader);
58 | if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) {
59 | for (String className: loaderParams.getStringArray(STATIC_INIT_CLASSES_KEY)) {
60 | Log.w(getClass().getName(), className);
61 | if (className.length() == 0)
62 | continue;
63 |
64 | try {
65 | @SuppressWarnings("rawtypes")
66 | Class initClass = classLoader.loadClass(className);
67 | Object staticInitDataObject = initClass.newInstance(); // create an instance
68 | //Method m = initClass.getMethod("setActivity", Activity.class, Object.class);
69 | //m.invoke(staticInitDataObject, m_activity, this);
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 | }
74 | }
75 |
76 | QtNative.loadQtLibraries(loaderParams.getStringArrayList(NATIVE_LIBRARIES_KEY));
77 | ArrayList libraries = loaderParams.getStringArrayList(BUNDLED_LIBRARIES_KEY);
78 | QtNative.loadBundledLibraries(libraries, QtNativeNativeLibrariesDir(m_service));
79 | m_mainLib = loaderParams.getString(MAIN_LIBRARY_KEY);
80 | // older apps provide the main library as the last bundled library; look for this if the main library isn't provided
81 | if (null == m_mainLib && libraries.size() > 0)
82 | m_mainLib = libraries.get(libraries.size() - 1);
83 |
84 |
85 | int necessitasApiLevel = 1;
86 | if (loaderParams.containsKey(NECESSITAS_API_LEVEL_KEY))
87 | necessitasApiLevel = loaderParams.getInt(NECESSITAS_API_LEVEL_KEY);
88 |
89 | m_environmentVariables ="";
90 |
91 | if (loaderParams.containsKey(APPLICATION_PARAMETERS_KEY))
92 | m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY);
93 | else
94 | m_applicationParameters = "";
95 |
96 | return true;
97 | }
98 |
99 | public void debugLog(String msg)
100 | {
101 | Log.i(QtNative.QtTAG, "DEBUGGER: " + msg);
102 | }
103 |
104 | public boolean startApplication()
105 | {
106 |
107 | try {
108 |
109 | String nativeLibraryDir = QtNativeNativeLibrariesDir(m_service);
110 |
111 | Log.i(QtNative.QtTAG, "LIB DIR : " + nativeLibraryDir);
112 |
113 | //QtNativeStartApplication
114 | QtNative.startApplication
115 | ( m_applicationParameters,
116 | m_environmentVariables,
117 | m_mainLib,
118 | nativeLibraryDir);
119 | return true;
120 | }
121 | catch (Exception e) {
122 |
123 | e.printStackTrace();
124 | return false;
125 | }
126 | }
127 |
128 | public static String QtNativeNativeLibrariesDir(Service service)
129 | {
130 | String m_nativeLibraryDir = null;
131 | try {
132 | ApplicationInfo ai = service.getPackageManager().getApplicationInfo(service.getPackageName(), 0);
133 | m_nativeLibraryDir = ai.nativeLibraryDir+"/";
134 | } catch (NameNotFoundException e) {
135 | e.printStackTrace();
136 | }
137 | return m_nativeLibraryDir;
138 | }
139 |
140 |
141 | public static boolean QtNativeStartApplication(String params,
142 | String environment,
143 | String mainLibrary,
144 | String nativeLibraryDir) throws Exception
145 | {
146 | File f = new File(nativeLibraryDir + "lib" + mainLibrary + ".so");
147 | if (!f.exists())
148 | throw new Exception("Can't find main library '" + mainLibrary + "'");
149 |
150 | if (params == null)
151 | params = "-platform\tandroid";
152 |
153 | boolean res = false;
154 |
155 | if (params.length() > 0 && !params.startsWith("\t"))
156 | params = "\t" + params;
157 | startQtApplication(f.getAbsolutePath() + params, environment);
158 |
159 | return res;
160 | }
161 |
162 | public static native void startQtApplication(String params, String env);
163 | }
164 |
--------------------------------------------------------------------------------
/example/MyTestService/android/src/org/qtproject/qt5/android/addons/qtserviceapp/QtService.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtserviceapp;
2 |
3 | import java.lang.reflect.Method;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 |
7 | import dalvik.system.DexClassLoader;
8 |
9 | import android.annotation.SuppressLint;
10 | import android.app.Notification;
11 | import android.app.NotificationManager;
12 | import android.app.PendingIntent;
13 | import android.app.Service;
14 | import android.content.ComponentName;
15 | import android.content.Context;
16 | import android.content.pm.PackageManager;
17 | import android.content.pm.ServiceInfo;
18 | import android.content.Intent;
19 | import android.os.Bundle;
20 | import android.os.IBinder;
21 | import android.util.Log;
22 | import android.os.Process;
23 | import android.widget.Toast;
24 |
25 | @SuppressLint("NewApi")
26 | public class QtService extends Service {
27 |
28 | /* Private variables */
29 |
30 | public Boolean started=false;
31 | private String[] m_qtLibs = null;
32 | private DexClassLoader m_classLoader = null;
33 |
34 | private Class m_class = QtServiceActivity.class;
35 |
36 | private static ServiceInfo m_serviceInfo = null;
37 | protected static NotificationManager m_notificationManager;
38 | protected static Notification.Builder m_builder;
39 | protected static PendingIntent pi;
40 | private static QtService m_instance;
41 | private static String m_lib_name;
42 |
43 | private static final String ERROR_CODE_KEY = "error.code";
44 | private static final String DEX_PATH_KEY = "dex.path";
45 | private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
46 | private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
47 | private static final String MAIN_LIBRARY_KEY = "main.library";
48 | private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
49 | private static final String LOADER_CLASS_NAME_KEY = "loader.class.name";
50 | private static final String LIB_PATH_KEY = "lib.path";
51 | private static final String ENVIRONMENT_VARIABLES_KEY = "env.variable";
52 |
53 | /* Service methods */
54 |
55 | public void onCreate (){
56 |
57 | Log.w(getClass().getName(), "Service created ...");
58 |
59 | m_instance = this;
60 |
61 | try{
62 | ComponentName myService = new ComponentName(this, this.getClass());
63 | m_serviceInfo = getPackageManager().getServiceInfo(myService, PackageManager.GET_META_DATA);
64 | m_lib_name = splitCamelCase (m_serviceInfo.metaData.getString("android.app.lib_name"));
65 | }
66 | catch (Exception e) {
67 |
68 | e.printStackTrace();
69 | }
70 | }
71 |
72 | public IBinder onBind(Intent intent) {
73 |
74 | return null;
75 | }
76 |
77 | @SuppressWarnings("deprecation")
78 | public int onStartCommand(Intent intent, int flags, int startId)
79 | {
80 |
81 | /* Notification */
82 |
83 | createNotification();
84 |
85 | /* Start the app */
86 |
87 | startApp();
88 |
89 | /* Return */
90 |
91 | return(START_STICKY);
92 | }
93 |
94 | public void onDestroy(){
95 |
96 | Log.w(getClass().getName(), "Service destroyed ...");
97 |
98 | Process.killProcess(Process.myPid());
99 | }
100 |
101 | /* Internals methods */
102 |
103 | private void startApp(){
104 |
105 | if (!started){
106 |
107 | started = true;
108 | Toast.makeText(getBaseContext(), m_lib_name + " starting", Toast.LENGTH_LONG).show();
109 |
110 | try{
111 |
112 | if (m_serviceInfo.metaData.containsKey("android.app.qt_libs_resource_id")) {
113 | int resourceId = m_serviceInfo.metaData.getInt("android.app.qt_libs_resource_id");
114 | m_qtLibs = getResources().getStringArray(resourceId);
115 | }
116 |
117 | if (m_serviceInfo.metaData.containsKey("android.app.use_local_qt_libs")
118 | && m_serviceInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) {
119 | ArrayList libraryList = new ArrayList();
120 |
121 |
122 | String localPrefix = "/data/local/tmp/qt/";
123 | if (m_serviceInfo.metaData.containsKey("android.app.libs_prefix"))
124 | localPrefix = m_serviceInfo.metaData.getString("android.app.libs_prefix");
125 |
126 | boolean bundlingQtLibs = false;
127 | if (m_serviceInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
128 | && m_serviceInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
129 | localPrefix = getApplicationInfo().dataDir + "/";
130 | bundlingQtLibs = true;
131 | }
132 |
133 | if (m_qtLibs != null) {
134 | for (int i=0;i 0) {
150 | if (dexPaths.length() > 0)
151 | dexPaths += pathSeparator;
152 | dexPaths += localPrefix + jar;
153 | }
154 | }
155 | }
156 |
157 | Bundle loaderParams = new Bundle();
158 | loaderParams.putInt(ERROR_CODE_KEY, 0);
159 | loaderParams.putString(DEX_PATH_KEY, dexPaths);
160 | loaderParams.putString(LOADER_CLASS_NAME_KEY, "org.qtproject.qt5.android.QtServiceDelegate");
161 | loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, "");
162 | if (m_serviceInfo.metaData.containsKey("android.app.static_init_classes")) {
163 | loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY,
164 | m_serviceInfo.metaData.getString("android.app.static_init_classes").split(":"));
165 | }
166 | loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList);
167 |
168 | loadApplication(loaderParams);
169 | return;
170 | }
171 | }
172 | catch (Exception e) {
173 | started = false;
174 | e.printStackTrace();
175 | }
176 | }
177 | }
178 |
179 | @SuppressLint("NewApi")
180 | public void loadApplication(Bundle loaderParams){
181 |
182 | try{
183 |
184 | ArrayList libs = new ArrayList();
185 | if ( m_serviceInfo.metaData.containsKey("android.app.bundled_libs_resource_id") )
186 | libs.addAll(Arrays.asList(getResources().getStringArray(m_serviceInfo.metaData.getInt("android.app.bundled_libs_resource_id"))));
187 |
188 | String libName = null;
189 | if ( m_serviceInfo.metaData.containsKey("android.app.lib_name") ) {
190 | libName = m_serviceInfo.metaData.getString("android.app.lib_name");
191 | loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function
192 | }
193 |
194 | loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs);
195 | loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, "");
196 |
197 | m_classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files
198 | getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written.
199 | loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists)
200 | getClassLoader()); // parent loader
201 |
202 | String loaderClassName = loaderParams.getString(LOADER_CLASS_NAME_KEY);
203 |
204 | Log.w(getClass().getName(), "Loader : " + loaderClassName);
205 |
206 | Class> loaderClass = m_classLoader.loadClass(loaderClassName); // load QtLoader class
207 | Object qtLoader = loaderClass.newInstance(); // create an instance
208 |
209 | Method perpareAppMethod = qtLoader.getClass().getMethod("loadApplication",
210 | Service.class,
211 | ClassLoader.class,
212 | Bundle.class);
213 |
214 | if (!(Boolean)perpareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams))
215 | throw new Exception("");
216 |
217 | // now load the application library so it's accessible from this class loader
218 | if (libName != null)
219 | System.loadLibrary(libName);
220 |
221 | Method startAppMethod=qtLoader.getClass().getMethod("startApplication");
222 | if (!(Boolean)startAppMethod.invoke(qtLoader))
223 | throw new Exception("");
224 |
225 |
226 | }
227 | catch (Exception e) {
228 | e.printStackTrace();
229 | }
230 | }
231 |
232 | /* Activity class */
233 |
234 | public void setActivityClass(Class cl){
235 |
236 | m_class = cl;
237 | }
238 |
239 |
240 | /* Notification methods */
241 |
242 | protected void createNotification(){
243 |
244 | Notification note=new Notification(m_serviceInfo.metaData.getInt("android.app.notificon"),"",System.currentTimeMillis());
245 |
246 | Intent i=new Intent(m_instance, m_class);
247 | i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
248 |
249 | pi=PendingIntent.getActivity(this, 0,
250 | i, 0);
251 |
252 | note.setLatestEventInfo(this, m_lib_name ,
253 | "Running",
254 | pi);
255 | note.flags|=Notification.FLAG_NO_CLEAR;
256 |
257 | startForeground(1337, note);
258 | }
259 |
260 | public static void notify(String s)
261 | {
262 | if (m_notificationManager == null) {
263 |
264 | m_notificationManager = (NotificationManager)m_instance.getSystemService(Context.NOTIFICATION_SERVICE);
265 | m_builder = new Notification.Builder(m_instance);
266 | m_builder.setSmallIcon(m_serviceInfo.metaData.getInt("android.app.notificon"));
267 | m_builder.setContentTitle(m_lib_name);
268 | m_builder.setContentIntent(pi);
269 | }
270 |
271 | m_builder.setContentText(s);
272 | Notification note = m_builder.build();
273 | note.flags |= Notification.FLAG_NO_CLEAR;
274 |
275 | m_notificationManager.notify(1337, note);
276 | }
277 |
278 | /* Helpers */
279 |
280 | static String splitCamelCase(String sp) {
281 |
282 | String s = Character.toUpperCase(sp.charAt(0)) + sp.substring(1);
283 |
284 | return s.replaceAll(
285 | String.format("%s|%s|%s",
286 | "(?<=[A-Z])(?=[A-Z][a-z])",
287 | "(?<=[^A-Z])(?=[A-Z])",
288 | "(?<=[A-Za-z])(?=[^A-Za-z])"
289 | ),
290 | " "
291 | );
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/example/MyTestService/android/src/org/qtproject/qt5/android/addons/qtserviceapp/QtServiceActivity.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtserviceapp;
2 |
3 | import com.mycompany.test1.R;
4 |
5 | import android.app.Activity;
6 | import android.app.ActivityManager;
7 | import android.app.ActivityManager.RunningServiceInfo;
8 | import android.os.Bundle;
9 | import android.content.ComponentName;
10 | import android.content.Context;
11 | import android.content.Intent;
12 | import android.content.SharedPreferences;
13 | import android.content.SharedPreferences.Editor;
14 | import android.content.pm.ActivityInfo;
15 | import android.content.pm.PackageManager;
16 | import android.content.pm.ServiceInfo;
17 | import android.content.pm.PackageManager.NameNotFoundException;
18 | import android.widget.CompoundButton;
19 | import android.widget.Switch;
20 |
21 | public class QtServiceActivity extends Activity {
22 |
23 | private Intent i;
24 | private Class m_class = QtService.class;
25 |
26 | @Override
27 | public void onCreate(Bundle savedInstanceState)
28 | {
29 |
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.serviceconfigactivity);
32 |
33 | i = new Intent(this, m_class);
34 |
35 | final Switch sRun = (Switch) findViewById(R.id.switch_run);
36 | sRun.setChecked(isMyServiceRunning());
37 | sRun.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
38 |
39 | @Override
40 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
41 |
42 | if (isChecked)
43 | startService(i);
44 | else
45 | stopService(i);
46 | }
47 | });
48 |
49 | ComponentName myActivity = new ComponentName(this, this.getClass());
50 | ActivityInfo activityInfo = null;
51 | try {
52 | activityInfo = getPackageManager().getActivityInfo(myActivity, PackageManager.GET_META_DATA);
53 | }
54 | catch (NameNotFoundException e) {
55 | e.printStackTrace();
56 | }
57 |
58 | SharedPreferences settings = getBaseContext().getSharedPreferences(activityInfo.metaData.getString("android.app.lib_name"), 0);
59 | final Editor editor = settings.edit();
60 |
61 | boolean startup = settings.getBoolean("runStartup", true);
62 |
63 | final Switch sRunStartup = (Switch) findViewById(R.id.switch_runstartup);
64 | sRunStartup.setChecked(startup);
65 | sRunStartup.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
66 |
67 | @Override
68 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
69 |
70 | editor.putBoolean("runStartup", isChecked);
71 | editor.commit();
72 | }
73 | });
74 | }
75 |
76 | private boolean isMyServiceRunning() {
77 | ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
78 | for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
79 | if (m_class.getName().equals(service.service.getClassName())) {
80 | return true;
81 | }
82 | }
83 | return false;
84 | }
85 |
86 | /* Activity class */
87 |
88 | public void setActivityClass(Class cl){
89 |
90 | m_class = cl;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/example/MyTestService/android/src/org/qtproject/qt5/android/addons/qtserviceapp/QtServiceBroadcastReceiver.java:
--------------------------------------------------------------------------------
1 | package org.qtproject.qt5.android.addons.qtserviceapp;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.ComponentName;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.SharedPreferences;
8 | import android.content.pm.ActivityInfo;
9 | import android.content.pm.PackageManager;
10 | import android.os.Bundle;
11 | import android.util.Log;
12 |
13 | public class QtServiceBroadcastReceiver extends BroadcastReceiver {
14 |
15 | private Class m_class = QtService.class;
16 |
17 | @Override
18 | public void onReceive(Context context, Intent intent) {
19 |
20 | Log.w("Qt", "Starting service");
21 |
22 | try
23 | {
24 | ActivityInfo activityInfo = context.getPackageManager().getReceiverInfo(new ComponentName(context, this.getClass()), PackageManager.GET_META_DATA);
25 | Bundle meta = activityInfo.metaData;
26 |
27 | SharedPreferences settings = context.getSharedPreferences(meta.getString("android.app.lib_name"), 0);
28 | boolean startup = settings.getBoolean("runStartup", true);
29 |
30 | if (startup){
31 |
32 | Intent i = new Intent(context, m_class);
33 | context.startService(i);
34 | }
35 | }
36 | catch (Exception e)
37 | {
38 | Log.e("Qt", "Can't create service" + e);
39 | }
40 |
41 | }
42 |
43 | /* Activity class */
44 |
45 | public void setActivityClass(Class cl){
46 |
47 | m_class = cl;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/example/MyTestService/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char *argv[])
4 | {
5 | QCoreApplication a(argc, argv);
6 |
7 | qDebug("Qt running !");
8 |
9 | return a.exec();
10 | }
11 |
--------------------------------------------------------------------------------