ããã«ã¡ã¯ããããããã¹ïŒ ãã®èšäºã§ã¯ãqtãšandroid studioã§ã®çµéšã«ã€ããŠã話ããããšæããŸãã ã€ãŸããã©ã®ããã«qtã§ããã¹ããæç»ãããããAndroid Studioã«è»¢éããå¿ èŠããã£ããã§ãã ã¿ã¹ã¯ã®åçŽãã«ãããããããããã解決ããã®ã«ããªãæéããããã誰ããã©ããã§å€ãã®æéãç¯çŽãããããããŸããã ããæå³ããã®èšäºã¯èªè»¢è»ãçºæãããšäž»åŒµããŠããããã€ã³ã¿ãŒãããäžã§è§£æ±ºçãèŠã€ããããšãã§ããªãã£ãã èª°ãæ°ã«ããªã-ãã£ãããžããããïŒ
ã¿ã¹ã¯èªäœã«ã€ããŠå°ã
æè¿ãiosããandroidã«ã¢ããªã±ãŒã·ã§ã³ãç§»æ€ããã¿ã¹ã¯ã«çŽé¢ããŸããã ç§»æ€æã®äž»ãªçã¿ã¯ãSDKã¢ããªã±ãŒã·ã§ã³ã§ã®äœæ¥ã§ããã ããã¯Qtã§æžãããŠãããããã¹ã/ç¢å°/ãšãªã¢ãªã©ãæç»ããããã«äœ¿çšãããŠããŸããã ã€ãŸããã¢ããªã±ãŒã·ã§ã³ã¯ç®çcã§èšè¿°ãããqtã©ã€ãã©ãªã䜿çšããŸããããqtãããžã§ã¯ãã§ã¯ãããŸããã§ããã ãããã£ãŠãæåã«ç»å Žããã®ã¯éçºç°å¢ã§ããã ç§ã¯ãã®ããžãã¹ã«å®å šã«æ £ããŠããªãã®ã§ãç§ã®éžæã¯Android Studioã«ãããŸããã ããã§ããç§ã«ãšã£ãŠã¯ã°ã©ãã£ã«ã«ã€ã³ã¿ãŒãã§ã€ã¹å šäœãAndroidã¹ã¿ãžãªã§è¡ãæ¹ãé©åã§ãããqtshnoe SDKã¯ã³ã³ãã¥ãŒãã£ã³ã°ã¿ã¹ã¯ãå®è¡ããŸãã ã€ã³ã¿ãŒãããã§ã¯ãqtãAndroidã«äœ¿çšããããšã«ã€ããŠããŸãæžãããŠããŸããããããã§ã¯qtãšandroid studioãåéã«ããäœæ¥ãè¡ããŸããã ãããšé£æºããã«ã¯ãAndroid NDKã䜿çšããJNIã䜿ââçšããŠãã¹ãŠãå®è£ ããŸãã JNIã§ã®äœæ¥ã¯ãããèªäœããªãè峿·±ããã®ã§ãã neteã§ã¯ããã®ãããã¯ã«é¢ããå€ãã®èšäºãèŠã€ããããšãã§ããŸãïŒããšãã°ã ãã®çŽ æŽããããµã€ã¯ã« ïŒã ãã ããJNIãQtã§äœ¿çšãããšããç¹ã§ã¯ãJNIã«èå³ããããŸãã ç¹°ãè¿ããŸãããåé¡ã¯äœã§ããïŒ é«åºŠãªsorsasã䜿çšããå ±æã©ã€ãã©ãªãäœæããAndroidã¹ã¿ãžãªã®ãããžã§ã¯ãã«æ¥ç¶ããŠå©çãåŸãŸãïŒ ããã§ã äŸãšããŠããã«ã ãããŠããããæ¥œãã¿ãå§ãŸããŸã...
Android Studioã§QTã䜿çšãã
èŠããŠããããã«ãç§ã¯ãããäžã«ç€ºãã
ããã¯Qtã§æžãããããã¹ã/ç¢å°/ãšãªã¢ãšä»ã®ãã¹ãŠãæãããã«äœ¿çšãããŸããã
QTã§ã°ã©ãã£ãã¯ããªããã£ããæç»ããããã«ãQApplicationãŸãã¯QGuiApplicationã®ã€ã³ã¹ã¿ã³ã¹ãäœæããå¿ èŠã¯ãããŸããã QCoreApplicationã§ãã-ãããŠåœŒã¯å¿ èŠãããŸããïŒ ãã ããQApplicationãŸãã¯QGuiApplicationãªãã§ããã¹ããæç»ããå Žåã¯ãäœãã§ããŸããã ããã§ã¯ãåé¡ã¯äœã§ããïŒ ãã®åé¡ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºããããšãã«çºçããŸãã
QApplication a(argc, argv);
ã©ã€ãã©ãªãäœæããå ŽåãQApplicationã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºã颿°ãã©ã€ãã©ãªã«ãããAndroid Studioã¢ããªã±ãŒã·ã§ã³ããJNIãä»ããŠåŒã³åºããããã«æ¬¡ã®ããã«èšããŸãã
ãã®ã¢ããªã±ãŒã·ã§ã³ã¯ãQtãã©ãããã©ãŒã ãã©ã°ã€ã³ãAndroidããèŠã€ããããªãããããŒãã§ããªãã£ããããèµ·åã«å€±æããŸããã
誰ã®ããã§ããïŒ
ã¯ã©ã·ãã¯ããŒãžã§ã³ã ææãåŠã¶ïŒ
ç§ãæåã«ããããšæ±ºããã®ã¯ãã€ã³ã¿ãŒãããäžã®åé¡ã®è§£æ±ºçãã°ãŒã°ã«ã«ããããšã§ããã å®å šã«äžèŽãããã®ã¯èŠã€ãããŸããã§ããããããªãå€ãã®æçš¿ã§ãWindowsãã©ã°ã€ã³ã®åæ§ã®åé¡ã«ã€ããŠèŠæ ãå¯ããããŸããã ããã§ã ããã§èšåãããã¹ãŠã詊ããŸããããæ®å¿µãªãã解決çã¯ãããŸããã§ããïŒç§ã®ããã«åããŠããŸãïŒïŒ
ç§ã®è³ªåãžã®çããæ¢ããŠãã¢ã³ããã€ãã®äžã§èè qtãçè§£ããã®ã§ãç§ã¯ãã®ãããªããªãå¥åŠãªããã°ã«åºäŒããŸããã ããã°ã¯éåžžã«è峿·±ããã®ã§ãããèè ã¯ïŒããã§ããç§èŠïŒC ++ããã®éçºãšqtäœæè ããã®ãã¹ãŠã®è¯ãç©ã®ç«ã¡äžãã«çŠç¹ãåœãŠãŠããŸãã æ£çŽãªãšããããã®ã¢ãããŒãã¯1ã€ã®çç±ã§ç§ã«ã¯åããŠããŸããã§ããïŒQtããJavaéšåããããã°ããããšã¯ã»ãšãã©äžå¯èœã§ãïŒã³ãŒããã³ã³ãã€ã«ããŠãããAndroidã¹ã¿ãžãªããã®æ·»ä»ãã¡ã€ã«ãåŸ ã£ãŠãããããäœãèµ·ãã£ãŠããã®ããèŠãããšãã§ããŸãïŒãã«ã¹ã¿ã ãã¥ãŒãéåæã¿ã¹ã¯ããããããããqtãããžã§ã¯ãã«å ¥ããŠæ£åžžã«ãããã°ããã«ã¯ã©ãããã°ããã§ããïŒ æ£çŽãªãšãããããããŸããã
å®éš
Qtã¢ããªã±ãŒã·ã§ã³ãäœæããŠãAndroidã§å®è¡ããããšããŸããã ç§ã¯ãããqt-creatorã§å®è¡ããŸããããå¥åŠãªããšã«ãå®å šã«èµ·åããŸããã ãããã§ã¹ããã°ã©ãã«ãã¢ããªã±ãŒã·ã§ã³ã³ãŒããã©ã®ããã«é 眮ãããŠãããããã詳ãã調ã¹å§ããŸããã ãããã§ã¹ãã§ãã®ãããªè峿·±ãããšãããããŸããã
<!-- Deploy Qt libs as part of package --> <meta-data android:name="android.app.bundle_local_qt_libs" android:value="1"/> <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/> <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/> <!-- Run with local libs --> <meta-data android:name="android.app.use_local_qt_libs" android:value="1"/> <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/> <meta-data android:name="android.app.load_local_libs" android:value="plugins/platforms/android/libqtforandroid.so"/> <meta-data android:name="android.app.load_local_jars" android:value="jar/QtAndroid.jar:jar/QtAndroidAccessibility.jar:jar/QtAndroid-bundled.jar:jar/QtAndroidAccessibility-bundled.jar"/> <meta-data android:name="android.app.static_init_classes" android:value=""/>
ã€ãŸãããã®æå³ã¯æç¢ºã§ãã apkã¢ããªã±ãŒã·ã§ã³ããã«ããããšããqtã©ã€ãã©ãªãapkå ã«é 眮ããå¿ èŠãããããšã瀺ããããããã¢ããªã±ãŒã·ã§ã³ã«ããŒãããå¿ èŠãããããšã瀺ããŸããã 察å¿ããjar-sãandroidã®ãããžã§ã¯ãã«æ¥ç¶ããqtã«ãããã®ãandroidãããã§ã¹ãã«ç»é²ããjniLibsãã©ã«ããŒã«qtny.soãã©ã°ã€ã³ãé 眮ããŠã广ã¯ãããŸããã§ããã
åŠç¿ãã©ã°ã€ã³
ç§ã¯æçµçã«ããã®äžå¹žãªãã©ã°ã€ã³libqtforandroid.soïŒQApplicationãäœæããåïŒãjavaã«ãã£ãŠããŒãããããšããŸããã
System.loadLibraryïŒ "plugins_platforms_android_libqtforandroid"ïŒ;ãŸã èœã¡ãŠããïŒ ç¢ºãã«ãããã§ã¯äŸå€ã¯ãã§ã«ç°ãªã£ãŠãããããè峿·±ããã®ã§ããã
I / QtïŒqt start
05-17 11ïŒ12ïŒ33.975 11084-11084 /ãããžã§ã¯ãåA / libcïŒèŽåœçãªã·ã°ãã«11ïŒSIGSEGVïŒat 0x00000000ïŒã³ãŒã= 1ïŒãã¹ã¬ãã11084ïŒndroid.gribviewïŒ
05-17 11ïŒ12ïŒ33.978 11084-11084 /ãããžã§ã¯ãåA / libcïŒpidã«åæ¢ä¿¡å·ãéä¿¡ïŒ11084 in void debuggerd_signal_handlerïŒintãsiginfo_tãvoidïŒ
å°ãªããšãããªããèŠãããšãã§ããæãããããããŸãã ããã«qt startã§ãèå³ã®ããã¡ãœãããèŠã€ããŸãã
Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) { QT_USE_NAMESPACE typedef union { JNIEnv *nativeEnvironment; void *venv; } UnionJNIEnvToVoid; __android_log_print(ANDROID_LOG_INFO, "Qt", "qt start"); UnionJNIEnvToVoid uenv; uenv.venv = Q_NULLPTR; m_javaVM = Q_NULLPTR; if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "GetEnv failed"); return -1; } JNIEnv *env = uenv.nativeEnvironment; if (!registerNatives(env) || !QtAndroidInput::registerNatives(env) || !QtAndroidMenu::registerNatives(env) || !QtAndroidAccessibility::registerNatives(env) || !QtAndroidDialogHelpers::registerNatives(env)) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed"); return -1; } m_javaVM = vm; return JNI_VERSION_1_4; }
ãã°ãã倿ãããšãregisterNativesã®1ã€ã«èœã¡ãã®ã§ãããã§ããïŒåregisterNativesã«ãã°ãç»é²ããŸããïŒã 圌ã¯èœã¡ã
registerNatives(env)
ããªãã¡ïŒ
jmethodID methodID; GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "activity", "()Landroid/app/Activity;"); __android_log_print(ANDROID_LOG_INFO, "Check Class 8", "activity "); jobject activityObject = env->CallStaticObjectMethod(m_applicationClass, methodID); __android_log_print(ANDROID_LOG_INFO, "Check Class 9 ", " methodID "); GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "classLoader", "()Ljava/lang/ClassLoader;"); __android_log_print(ANDROID_LOG_INFO, "Check Class 10", " classLoader "); if(activityObject!=nullptr) { __android_log_print(ANDROID_LOG_INFO, "No tull activityObject", " Not Null "); } if(methodID!=nullptr) { __android_log_print(ANDROID_LOG_INFO, "No tull methodID", " Not Null "); } m_classLoaderObject = env->NewGlobalRef(env->CallStaticObjectMethod(m_applicationClass, methodID)); if(m_classLoaderObject!=nullptr) { __android_log_print(ANDROID_LOG_INFO, "No tull m_classLoaderObject", " Not Null "); } clazz = env->GetObjectClass(m_classLoaderObject);
èœäžã¯æåŸã®è¡ã§çºçããŸããã classLoaderObjectã¯nullã§ããããšã倿ããŸããã ãŸããactivityObjectãnullã§ããããšãçºçããŸããã ããã£ã ãã®äžéãªãã©ã°ã€ã³ãããŒãããåã«ãJNIã®ã¢ã¯ãã£ããã£ãäœæããŠã¿ãŸãããã ãããè¡ãã«ã¯ãJavaã³ãŒãã§æ¬¡ã®è¡ãèšè¿°ããŸãã
QtNative.setActivity(this, null); QtNative.setClassLoader(getClassLoader());
å°ããªäœè«ã QtNativeã¯ã©ã¹ã¯ããããžã§ã¯ãã«æ¥ç¶ããjarãã¡ã€ã«ã«ãããŸãã ããã«ãããã¯éåžžã«è峿·±ãã¯ã©ã¹ã§ãã ã¡ãœããããããŸãïŒ
QtNative.loadBundledLibraries(); QtNative.loadQtLibraries();
å¿ èŠãªãã©ã°ã€ã³ãããŒãããå¿ èŠããããŸãã ä»ã®ãšããããããèŠããŠããã©ã°ã€ã³ãæåã§æ¥ç¶ããããšã«æ»ããŸãã QtNativeã®ã¡ãœããsetActivityããã³setClassLoaderãåŒã³åºããšã次ã®ããšãå®çŸã§ããŸãã
registerNatives(env)
ããããåŸ ã¡äŒãã¯ãã§ã«QtAndroidInput :: registerNativesïŒenvïŒã«ãããŸããã keyDownã€ãã³ãã®é¢æ°ã·ã°ããã£ãäžèŽããŸããã§ããã åºæ¬çã«ããã©ã³ã以å€ã¯å¿ èŠãªãã®ã§ãã³ãŒãã®æ¬¡ã®ã»ã¯ã·ã§ã³ãã³ã¡ã³ãã¢ãŠãããŸããã
if (!registerNatives(env) /* || !QtAndroidInput::registerNatives(env) || !QtAndroidMenu::registerNatives(env) || !QtAndroidAccessibility::registerNatives(env) || !QtAndroidDialogHelpers::registerNatives(env)*/) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed"); return -1; }
ãã®ãã©ã°ã€ã³ã¯å®å šã«ããŠã³ããŒããããããã§ãã ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããã©ã°ã€ã³ãããŒãããQApplicationãåŒã³åºããŠã
ãã®ã¢ããªã±ãŒã·ã§ã³ã¯ãQtãã©ãããã©ãŒã ãã©ã°ã€ã³ãAndroidããèŠã€ããããªãããããŒãã§ããªãã£ããããèµ·åã«å€±æããŸããã
ãŸããææŠ
QtNative.loadBundledLibraries(); QtNative.loadQtLibraries();
ãŸããåé¡ã解決ããŸããã§ããã ããã ããã£ã ç§ãã¡ã¯ãã³ã³ã¹ãã©ã¯ã¿ãŒãäœæãããšããçš®é¡ã«ç»ããŸãã äŸå€ãšããŠãã¡ãœããããã°ããèŠã€ããŸãïŒ
static void init_platform(const QString &pluginArgument, const QString &platformPluginPath, const QString &platformThemeName, int &argc, char **argv) { // Split into platform name and arguments QStringList arguments = pluginArgument.split(QLatin1Char(':')); const QString name = arguments.takeFirst().toLower(); QString argumentsKey = name; argumentsKey[0] = argumentsKey.at(0).toUpper(); arguments.append(QLibraryInfo::platformPluginArguments(argumentsKey)); // Create the platform integration. QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath); if (QGuiApplicationPrivate::platform_integration) { QGuiApplicationPrivate::platform_name = new QString(name); } else { QStringList keys = QPlatformIntegrationFactory::keys(platformPluginPath); QString fatalMessage = QStringLiteral("This application failed to start because it could not find or load the Qt platform plugin \"%1\".\n\n").arg(name); ....
ããã ãã®ã¡ãœãããã©ãããåŒã³åºãããæ¢ããŠããŸãïŒ
void QGuiApplicationPrivate::createPlatformIntegration() { // Use the Qt menus by default. Platform plugins that // want to enable a native menu implementation can clear // this flag. QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true); // Load the platform integration QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH")); QByteArray platformName; #ifdef QT_QPA_DEFAULT_PLATFORM_NAME platformName = QT_QPA_DEFAULT_PLATFORM_NAME; #endif QByteArray platformNameEnv = qgetenv("QT_QPA_PLATFORM"); if (!platformNameEnv.isEmpty()) { platformName = platformNameEnv; } QString platformThemeName = QString::fromLocal8Bit(qgetenv("QT_QPA_PLATFORMTHEME")); // Get command line params QString icon; int j = argc ? 1 : 0; for (int i=1; i<argc; i++) { if (argv[i] && *argv[i] != '-') { argv[j++] = argv[i]; continue; } const bool isXcb = platformName == "xcb"; QByteArray arg = argv[i]; if (arg.startsWith("--")) arg.remove(0, 1); if (arg == "-platformpluginpath") { if (++i < argc) platformPluginPath = QLatin1String(argv[i]); } else if (arg == "-platform") { if (++i < argc) platformName = argv[i]; } else if (arg == "-platformtheme") { if (++i < argc) platformThemeName = QString::fromLocal8Bit(argv[i]); } else if (arg == "-qwindowgeometry" || (isXcb && arg == "-geometry")) { if (++i < argc) windowGeometrySpecification = QWindowGeometrySpecification::fromArgument(argv[i]); } else if (arg == "-qwindowtitle" || (isXcb && arg == "-title")) { if (++i < argc) firstWindowTitle = QString::fromLocal8Bit(argv[i]); } else if (arg == "-qwindowicon" || (isXcb && arg == "-icon")) { if (++i < argc) { icon = QString::fromLocal8Bit(argv[i]); } } else { argv[j++] = argv[i]; } } if (j < argc) { argv[j] = 0; argc = j; } init_platform(QLatin1String(platformName), platformPluginPath, platformThemeName, argc, argv); if (!icon.isEmpty()) forcedWindowIcon = QDir::isAbsolutePath(icon) ? QIcon(icon) : QIcon::fromTheme(icon); }
ã€ãŸãããã®ãã©ã°ã€ã³ãæ¢ãå ŽæãšããŠargcããã³argvãä»ããŠåŒæ°ãæž¡ãããšãã§ããŸãã ããã«äºçŽãå ¥ããŠãqtãããã¬ãŒã§androidã®ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããããšããŸããããargcãšargvã¯ããããçããã§ãã1ãšqtãåéããlibrary_ã®ååã§ããããã©ã°ã€ã³ã¯åéããŸããã argcãšargvã«é©åãªå€ãå²ãåœãŠãŠã¿ãŸãããã
char *SDKEnvironment::argv[] = {"-platform libplugins_platforms_android_libqtforandroid.so:plugins/platforms/android/libqtforandroid.so -platformpluginpath /data/app-lib/__jniLibs"};
ããããããŸããããŸããã§ããã
解決ç
æ£çŽãªãšãããç· ãåããè¿«ã£ãŠããŠãäœãã©ãã§æ©èœããªãã£ãããç ç©¶ããããã«-ç§ã«ã¯æéã®
- qtã§apkã§ã¯ãªããaarãäœæããŸãããã ãããè¡ãã«ã¯ãqt Creatorã«ç§»åããŠgradleãã¡ã€ã«ãèŠã€ãããã®äžã®
apply plugin: 'com.android.applicatioin'
è¡ã倿ŽããŠapply plugin: 'com.android.applicatioin'
ãapply plugin: 'com.android.library'
ã ãããã£ãŠãapkã§ã¯ãªãaarãã¡ã€ã«ãäœæããŸã - 次ã«ãAndroid Studioã®ã¢ããªã±ãŒã·ã§ã³ã«è¿œå ããŸãã New-> Moduleã«ç§»åããimport aarãéžæããã¢ãžã¥ãŒã«ãå³ã¯ãªãã¯ããŠOpen Module Settingsãéžæããdependencyã¿ãã«ç§»åããŠqtã¢ãžã¥ãŒã«ã«äŸåé¢ä¿ã远å ããŸãã
ãããããAndroidã¹ã¿ãžãªã«ããjniããã¹ãŠqtã«è»¢éããŸããã QApplicationãååºŠäœæããããšããŸããããããŸããããŸããã
ãŸãšã
ãã®åé¡ã解決ããå¥ã®æ¹æ³ããããšç¢ºä¿¡ããŠããŸãã ç§ãã©ããééãããã誰ããææããã°ãããã¯çŽ æŽãããããšã§ãã ã€ã³ã¿ãŒãããã§åé¡ã®è§£æ±ºçãèŠã€ããããªãã£ãã®ã§ãèªåã§è§£æ±ºçãæäŸããŸãã