Solved Thread and Android activity issues: WARNING: QApplication was not created in the main() thread
-
I believe that warning is normal. Has something to do with how the Android Activety starts/loads the Qt-Part.
I think one gets thats warning even with a simple Hello World program.
If your programm crashes with a SIGSEGV than you most likly have a different error.
Did you start it via USB-Debugging and a debugger attached? should help narrowing down the problem. -
@jsulm
There is an instance of QApplication in main.cpp:#include "mainwindow.h" #include <QApplication> #include "CameraControllerX.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
Could I do something good with my QApplication instance to get my program work? Like passing it to MainWindow w; . Anyway QApplication feels a bit abstract and I don't know how to use it. :/
@J.Hilk
Yes, I am doing a debug-build and running it on a physical Android tablet via USB-dubugging.EDIT 2018-04-05 10:07:
@J.Hilk
I did a "release"-version but i still get "WARNING: QApplication was not created in the main() thread."I also searched a bit about "WARNING: QApplication was not created in the main() thread." on Android" and found something on the Qt Bug Dashboard.
They say something like that it is recommended to delay a call to some thread-fiddling concepts. So now i start my activity from a QButton called triggerActivityBtn just for testing and see what happends.
Now i get other errors like:
.... W libCameraProjectJNIx.so: (null):0 ((null)): WARNING: QApplication was not created in the main() thread. W libCameraProjectJNIx.so: (null):0 ((null)): QObject::setParent: Cannot set parent, new parent is in a different thread W libCameraProjectJNIx.so: (null):0 ((null)): QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: Receiver is QAndroidInputContext(0xe2457bcc) W libCameraProjectJNIx.so: (null):0 ((null)): QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: Receiver is QAndroidInputContext(0xe2457bcc) W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::startTimer: Timers cannot be started from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread W libCameraProjectJNIx.so: (null):0 ((null)): QObject::killTimer: Timers cannot be stopped from another thread
When i google on these i don't find anything good. :( And i still dont't know how to refactor things in the main.cpp about QApplication. :/
Thanks for any help!
-
You have global
QObject
s? -
@kshegunov
No I don't think so. Anyway, I have not instantiated global QObjects. There might be some hidden in the included Qt source code? -
@pga4711 said in Thread and Android activity issues: WARNING: QApplication was not created in the main() thread:
No I don't think so.
Could you check, any global can be a problem if it contains a
QObject
, so you may've hiddenQObject
instantiations. So let me rephrase it: do you have any globals?There might be some hidden in the included Qt source code?
I really doubt that.
-
Ok, then i am sure that it is no global QObject's in my code.
Hmm, soo. In this main.cpp-file we have this:
#include "mainwindow.h" #include <QApplication> #include "CameraControllerX.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
I really wonder a lot about this.
-
Where is the connection between the QApplication a and MainWindow w? Something is hidden here.
-
Is QApplication only used when we have instances of QMainWindow, QDialog or QWidget?
-
You could not use QGuiApplication with QMainWindow, QDialog, QWidget?
-
QGuiApplication is for the most used in QML applications?
-
QCoreApplication = ? Could you use things like QMainWindow, QDialog and QWidget with QCoreApplication?
-
QCoreApplication is not used with GUI: "The QCoreApplication class provides an event loop for Qt applications without UI". What do they mean? But when i start a Qt Quick Template there is a QCoreApplication in all of them :D . Something is hidden here also, or maybe i missed something.
-
There are cool stuff in QCoreApplication and its subclasses like sendEvent(...) . Maybe i should use that when i start an activity? :o But i dont know if that is the right way, i have missed some basics here.
Explanations are apreciated :)
-
-
Looking at
main.cpp
isn't enough, you can still have globals inCameraControllerX.h
or inmainwindow.h
.@pga4711 said in Thread and Android activity issues: WARNING: QApplication was not created in the main() thread:
I really wonder a lot about this.
- Where is the connection between the QApplication a and MainWindow w? Something is hidden here.
What connection do you have in mind?
QApplication
provides some basic initialization and the message pump (started withQApplication::exec
), beyond thatMainWindow
(or anyQWidget
subclass) will get the events it registers to internally.Is QApplication only used when we have instances of QMainWindow, QDialog or QWidget?
Yes. For console applications one uses the base -
QCoreApplication
or for QML -QGuiApplication
You could not use QGuiApplication with QMainWindow, QDialog, QWidget?
No, you couldn't.
QGuiApplication is for the most used in QML applications?
Indeed.
QCoreApplication = ? Could you use things like QMainWindow, QDialog and QWidget with QCoreApplication?
No. Console applications only. It's the base for the other application types.
QCoreApplication is not used with GUI: "The QCoreApplication class provides an event loop for Qt applications without UI". What do they mean?
Exactly that - applications without graphical user interface, a.k.a. console applications.
But when i start a Qt Quick Template there is a QCoreApplication in all of them :D . Something is hidden here also, or maybe i missed something.
I think it should be
QGuiApplication
, which is the type used for QML.There are cool stuff in QCoreApplication and its subclasses like sendEvent(...) . Maybe i should use that when i start an activity? :o But i dont know if that is the right way, i have missed some basics here.
I don't know, as I don't develop for android, but this particular warning means there's some mismatch in the order of initialization. There shouldn't be any
QObject
s that are created beforeQApplication
is instantiated. -
@kshegunov
Thank you for the clarification aboutQCoreApplication
and its subclasses. (And thanks for your implicit help with acute accent/grave accent-character to get fresh looking code related keywords)And now to the things I wonder about. First, your comments:
@kshegunov said in Thread and Android activity issues: WARNING: QApplication was not created in the main() thread:
I really wonder a lot about this.
- Where is the connection between the QApplication a and MainWindow w? Something is hidden here.
What connection do you have in mind?
QApplication
provides some basic initialization and the message pump (started withQApplication::exec
), beyond thatMainWindow
(or anyQWidget
subclass) will get the events it registers to internally.I don't understand how my
MainWindow
and myQApplication
and communicates with each other. Inmain.cpp
i can't see something like. a.connect(w); or w.connect(a); (Sorry for ugly pseudo-code, but you might get the point? :> In programming languages you often combine two objects with some kind of function/method. Or there might be something hidden, something internal, like you said: "...events it registers to internally"
I wonder a bit about how it works, there are something behind the scenes. (:@kshegunov said in Thread and Android activity issues: WARNING: QApplication was not created in the main() thread:
Looking at
main.cpp
isn't enough, you can still have globals inCameraControllerX.h
or inmainwindow.h
.
....
... this particular warning means there's some mismatch in the order of initialization. There shouldn't be anyQObject
s that are created beforeQApplication
is instantiated.Actually, i might have found something related to a
QObject
instance. According to Qt Bug 35153, there are sometimes problems with QObject instances. I have found that my mainwindow.h haveCameraControllerX *ccx = new CameraControllerX()
And in
CamerControllerX.h
we can seeclass CameraControllerX : public QObject, QAndroidActivityResultReceiver
Omg, it seems like i have some sort of QObject-instance on a error prone place? @.@ 0_o
Hmm, but the
MainWindow w;
is inmain.cpp
. AndCameraControllerX *ccx = new CameraControllerX()
is inMainWindow.h
. So then theCameraControllerX
-instance would be inmain.cpp
? (Maybe a far-fetched assumption because of the hidden things going on betweena
andw
)And in main.cpp there are a line
QApplication a(argc, argv);
that seems to instantiate aQApplication
. And that is happening beforeMainWindow w;
I dont think thatCameraControllerX *ccx = new CameraControllerX();
inmainwindow.h
runs beforeQApplication a(argc, argv);
.Sorry for the dizzy text.
But what do you think? Should i move out
CameraControllerX *ccx = new CameraControllerX();
tomain.cpp
? -
@pga4711 said in Thread and Android activity issues: WARNING: QApplication was not created in the main() thread:
I don't understand how my
MainWindow
and myQApplication
and communicates with each other.You need to understand how the event loop works. To that end you should look here, here and most importantly here.
In
main.cpp
i can't see something like. a.connect(w); or w.connect(a);There's none, as it isn't necessary. The call to
w.show()
posts an event on the event loop that the window should be shown, that's enough. Thereafter the window will receive events from the OS's window manager about it being resized, mouse moves and such. There's no connects needed at that point, because Qt will do the window manager integration (including events abstraction) for you.Actually, i might have found something related to a
QObject
instance. According to Qt Bug 35153, there are sometimes problems with QObject instances. I have found that my mainwindow.h haveCameraControllerX *ccx = new CameraControllerX()
In what header or source this is is more or less irrelevant. What is important is if this is inside a class or it's floating freely? If it's the latter, then you have the explanation - you create a global
QObject
.Hmm, but the
MainWindow w;
is inmain.cpp
. AndCameraControllerX *ccx = new CameraControllerX()
is inMainWindow.h
. So then theCameraControllerX
-instance would be inmain.cpp
? (Maybe a far-fetched assumption because of the hidden things going on betweena
andw
)Post the
MainWindow.h
file so we could look at it, please.But what do you think? Should i move out
CameraControllerX *ccx = new CameraControllerX();
tomain.cpp
?Nope, not at this stage of the discussion, as I don't know enough to advise you properly.
-
Very good. I will have a look at the links you recommend.
Did you see my links to the project in the first post? (:
Here are my project:
https://github.com/pga4711/QtCameraProjectJNIx
By the way, do you use git much? I am very new to git.Actually, i got the inspiration to my "CameraControllerX" from someone on GitHub: https://github.com/minixxie/examples/tree/master/qt-for-mobile/TestExternalAndroidCamera1
Here are my current code:
mainwindow.h
:#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <CameraControllerX.h> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void invokeCCX(); private slots: void on_triggerActivityBtn_clicked(); private: Ui::MainWindow *ui; CameraControllerX *ccx = new CameraControllerX(); }; #endif // MAINWINDOW_H
More code are on github :)
-
@pga4711 said in Thread and Android activity issues: WARNING: QApplication was not created in the main() thread:
Did you see my links to the project in the first post?
Nope, completely slept through that part.
By the way, do you use git much?
I wouldn't say much, I muddle through.
Here are my current code
I couldn't see anything out of order, but then again I don't develop for android so I might have just missed something. Honestly I don't know what the problem is. Especially as your code seems to be (almost) the same as the one you sourced as inspiration. Have you tried building the example you linked, the one on github? Did it work?
-
I tested Minixxie's TestExternalAndroidCamera1 and it works quite well. For example i do NOT get warnings and SIGSEGV like this (these printouts are from my application):
W libCameraProjectJNIx.so: (null):0 ((null)): WARNING: QApplication was not created in the main() thread. W libCameraProjectJNIx.so: (null):0 ((null)): QObject::setParent: Cannot set parent, new parent is in a different thread W libCameraProjectJNIx.so: (null):0 ((null)): QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: Receiver is QAndroidInputContext(0xe69b259c) W libCameraProjectJNIx.so: (null):0 ((null)): QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: Receiver is QAndroidInputContext(0xe69b259c) … W libCameraProjectJNIx.so: (null):0 ((null)): QSocketNotifier: Invalid socket 1 with type Write, disabling... F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x1c in tid 31187 (QtMainThread)
Minixxie's program are build in QML. Maybe QML are more stable and "thread-safe". But in my opinion i think Qt Widget should work with Android too. I might migrate to QML-development in the long term, but i would like to get things work in Qt Widget first :> ^^.
Actually, now i tried to move out the
CameraControllerX
-instance tomain.cpp
and write some more code to get the camera to work. Now i can open the camera from my program. But i still get thread-warnings and SIGSEGV in my program (like above). And when the photo is taken, i get "CameraTester has crashed" in Android. I don't think that the move of the instantiating ofCameraControllerX
tomain.cpp
damped the warnings and errors. (I don't know if i did it right, i had problems with pointers and references; & and *. Now i created theCameraControllerX
instance on the heap, and wanted to pass the reference of it intoMainWindow w
)Soo i think that all of my warnings and errors appears when i run
QtAndroid::startActivity(...)
.I read a bit in your links about
QThread
,QRunnable
,QtConcurrent
, Events, main event loop. Maybe i should do something likeQCoreApplication::processEvents()
or do something withQtConcurrent::run()
. Or even trickier, do something withQMutex
,QWaitCondition
,QThread
:o . I don't know yet. And i have not understand everything about how the threads and event loops and the main event loop in Qt works. I should read a bit more. And i think i am going to post something here soon: https://bugreports.qt.io/browse/QTBUG-35153 -
@pga4711
I'm not an java expert,
but you try to start a new activity, that is declared as an extension of the main (QtActivity), is that possible in the first place? -
@J.Hilk
Now in theStartCameraActivity.java
i changedStartCameraActivity extends org.qtproject.qt5.android.bindings.QtActivity {
topublic class StartCameraActivity extends Activity {
and the warning disappears :O I took a look inQtActivity.java
that is located onC:\Qt\5.10.1\Src\qtbase\src\android\java\src\org\qtproject\qt5\android\bindings
on my drive. InQtActivity.java
we can see a lot ofQtApplication
-stuff, maybe that is why i get warnings and SIGSEGV?Maybe this org.qtproject.qt5.android.bindings.QtActivity are some kind of singleton that only should be used by Qt behind the scenes in a hidden manner??
I found some things on different places about QtActivity and Activity.
-
In Minixxiee TestExternalAndroidCamera2 i found a line with
MyActivity extends org.qtproject.qt5.android.bindings.QtActivity {
. When i compile the project, the Application Output tells usWarning: QML import could not be resolved in any of the import paths: QtQuick.Extras.Private.CppUtils
and an old gradle are used in the project. By default Minimum sdk are API 9 and Target sdk are API14 in theAndroidManifest.xml
. Not so fresh project.
Note that i tested TestExternalAndroidCamera1 when i wrote in some previous posts here. That project's Activity-starters was made in pure JNI i think and there are no subclassing ofActivity
/QtActivity
. This TestExternalAndroidCamera2 are made in some JNI and a more Android Java-files. -
In this BogdaVatan on page 22 they mention
src/org/qtproject/qt5/android/bindings/QtActivity.java
, they say it is the "application activity class", but they don't say that "You don't make a subclass of QtActivity in your Activity.java-like-file. You should always make a subclass of android.app.Activity in your java-file" -
Here they do something with extend QtActivity. But i don't know if it works really.
-
Here in the topic Calling QCoreApplication methods from Android activity onCreate method someone trying to do something with
public class MyActivity extends org.qtproject.qt5.android.bindings.QtActivity
, but i dont understand what he trying to achieve.
I am really looking for some documentation about this QtActivity and when to use it, when to extend it and not. :>
-
-
My guess is as good as yours. Maybe looking at the examples in the documentation might give you hint (although they're for QML).