Qt android 浅析
Qt5支持编写Android应用。
典型main:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
这会在Android设备上显示一个空白窗口。
但是:
问题1, main函数“冲突”。我们知道Android进程源于zygote的fork,作为进程入口的函数main早就执行过了,那么上述代码这中Qt的入口函数main又何时怎么被执行的呢?
问题2,Android activity的生命周期是如何转化为qt的生命周期的?
问题3,qt主线程和Android主线程的关系是什么样的?
helloworld工程分析
在qtcreator新建一个helloworld的工程,编译后,在qt的build目录下,可以看到目录结构:
- android_build/
- libhelloworld.so
- main.o
- mainwindow.o
.o文件显然对应各个cpp文件,so文件是.o文件的“集合”。android-build的目录经过简单的查看,可以知道是一个gradle组织的android工程。
所以qt的Android支持,简单看就是将我们写的qt代码生成so文件,并通过自动生成的Android模板工程来最终生成一个apk文件。
看下android_build中的build.gradle:
……
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
……
build.gradle中通过sourceSets调整了com.android.application插件的默认源码、资源路径。
主要引入了qt5AndroidDir目录下的src、aidl和res。
qt5AndroidDir定义在gradle.properties:
qt5AndroidDir=/Users/xxxx/Qt5.10.1/5.10.1/android_armv7/src/android/java
一般指向qt安装目录中的android_armv7/src/android/java.
看下libs目录:
libs
├── QtAndroid-bundled.jar
└── armeabi-v7a
├── gdbserver
├── libQt5Core.so
├── libQt5Gui.so
├── libQt5Widgets.so
├── libgdbserver.so
├── libgnustl_shared.so
├── libhelloworld.so
├── libplugins_imageformats_libqgif.so
├── libplugins_imageformats_libqicns.so
├── libplugins_imageformats_libqico.so
├── libplugins_imageformats_libqjpeg.so
├── libplugins_imageformats_libqtga.so
├── libplugins_imageformats_libqtiff.so
├── libplugins_imageformats_libqwbmp.so
├── libplugins_imageformats_libqwebp.so
├── libplugins_platforms_android_libqtforandroid.so
└── libplugins_styles_libqandroidstyle.so
qt运行所需的几个核心so拷贝被拷贝到了libs目录下,这样就会被打包到最终的apk中。还引入了一个QtAndroid-bundled.jar依赖。
总结
qt编写的代码会生成为一个动态库,以工程名命名
qt生成Android应用的策略是借助了一个模板工程
不难猜测,qt应用的运行模式是,通过模板工程生成的Android应用,以native调用方式执行qt代码
启动流程
上节分析可知,Android代码主导了整个进程的运行。那么寻找Qt应用入口就从Android代码入手。
Android应用入口一般是Application,模板工程android-build中,QtApplication继承了Applicaiton,但是浏览一遍并没有发现加载libhelloworld.so的地方,先略过。
Application加载后会会执行“主Activity”,也就是指定有category.LAUNCHER的那个Activity,在模板工程中是QtActivity。
这样,主Activity的onCreate就不亚于第二入口:
@O