如何在Android上使用冰球应用程序SDK和Qt



我正在尝试将最新版本4.1.2的HockeyApp Android SDK集成到我们的Qt Android应用程序中。我对Android开发或Java总体上不太了解,也不了解Qt或HockeyApp的内部结构。

有一些关于将第三方Android(即Java)库纳入Qt项目的通用官方文档;然而,它提到了">创建AndroidManifest.xml按钮在部署设置中"在当前的Qt Creator 4.2.0版本中不存在,因此我不确定该文档有多过时,也不确定哪些部分可能仍然适用。

HockeyApp文档仅涵盖";典型的Android开发";不支持使用Android Studio及其支持。

顺便说一句,集成HockeyAppiOSSDK只花了几个小时,主要是编写一些ObjectiveC桥接代码。

步骤1:将SDK添加到项目中

第一种方法

我尝试遵循上面的文档,并添加了解压缩的HockeySDK-Android-4.1.2文件夹和内容为的project.properties文件

android.library.reference.1=HockeySDK-Android-4.1.2/libs/

到项目文件夹;我还将<my project>.pro中的ANDROID_PACKAGE_SOURCE_DIR设置为该项目文件夹。

问题androiddeployqt构建步骤发出错误消息(为可读性而包装)

Error: <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs
is not a valid project (AndroidManifest.xml not found).

但无论如何都会继续,最后失败并显示错误消息(也为了可读性而包装)

BUILD FAILED
/opt/Android/android-sdk-macosx/tools/ant/build.xml:573:
HockeySDK-Android-4.1.2/libs/ resolve to a path
with no project.properties file for project <path to build folder>/android-build

使用--verbose开关运行androiddeployqt会显著增加更多的输出,但没有任何有用信息。


第二种方法

下载的HockeyApp Android SDK zip档案除了一些文档外,还包含一个文件libs/HockeySDK-4.1.2.aar;从这个回复和这个评论中,我发现AAR格式只是一个zip档案,其中包含一个AndroidManifest.xml文件。我拉开libs/HockeySDK-4.1.2.aar的拉链,然后把它取下来;现在,构建中的第一条错误消息已经不见了。

问题:构建失败

BUILD FAILED
/opt/Android/android-sdk-macosx/tools/ant/build.xml:597:
The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:649:
The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:655:
<path to build folder>/android-build/HockeySDK-Android-4.1.2/libs/src does not exist.

同样,将运行中的--verbose添加到androiddeployqt只会增加噪声。查看上述build.xml位置也没有帮助。

更新:

我试着简单地从错误消息中创建丢失的文件夹;现在构建失败如下:

-dex:
[dex] input: <path to build folder>/android-build/bin/classes
[dex] input: <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs/bin/classes.jar
[dex] input: <path to build folder>/android-build/libs/QtAndroid-bundled.jar
[dex] input: <path to build folder>/android-build/libs/QtAndroidBearer-bundled.jar
[dex] Pre-Dexing <path to build folder>/android-build/libs/QtAndroid-bundled.jar -> QtAndroid-bundled-a06280f40655c27b25038380a4d7f67c.jar
[dex] Pre-Dexing <path to build folder>/android-build/libs/QtAndroidBearer-bundled.jar -> QtAndroidBearer-bundled-a69fa323dbfa477411ea082423128813.jar
[dex] Converting compiled files and external libraries into <path to build folder>/android-build/bin/classes.dex...
[dx]
[dx] UNEXPECTED TOP-LEVEL EXCEPTION:
[dx] java.io.FileNotFoundException: <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs/bin/classes.jar (No such file or directory)
[dx]     at java.util.zip.ZipFile.open(Native Method)
[dx]     at java.util.zip.ZipFile.<init>(ZipFile.java:219)
[dx]     at java.util.zip.ZipFile.<init>(ZipFile.java:149)
[dx]     at java.util.zip.ZipFile.<init>(ZipFile.java:163)
[dx]     at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:244)
[dx]     at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
[dx]     at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
[dx]     at com.android.dx.command.dexer.Main.processOne(Main.java:677)
[dx]     at com.android.dx.command.dexer.Main.processAllFiles(Main.java:574)
[dx]     at com.android.dx.command.dexer.Main.runMonoDex(Main.java:311)
[dx]     at com.android.dx.command.dexer.Main.run(Main.java:277)
[dx]     at com.android.dx.command.dexer.Main.main(Main.java:245)
[dx]     at com.android.dx.command.Main.main(Main.java:106)
[dx] 1 error; aborting
BUILD FAILED
/opt/Android/android-sdk-macosx/tools/ant/build.xml:888: The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:890: The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:902: The following error occurred while executing this line:
/opt/Android/android-sdk-macosx/tools/ant/build.xml:283: null returned: 1

我显然不能只编一些classes.jar文件,但在<path to build folder>/android-build/HockeySDK-Android-4.1.2/libs中有一个同名文件,所以我可以创建缺少的bin文件夹,并在其中创建一个指向../classes.jar的符号链接。

现在构建成功。完成步骤1。

步骤2:在项目中使用SDK

回到相应的HockeyApp文档,我想我需要修改一些看起来类似的代码

public class YourActivity extends Activity
...

<path to build folder>/android-build/src/org/qtproject/qt5/android/bindings/QtActivity.java:中的项目中有一次出现此类代码

public class QtActivity extends Activity
...

该文件由androiddeployqt工具(Qt SDK的一部分)从位于$QTDIR/src/android/java的Qt SDK内的源文件夹(即我机器上的/opt/Qt/Qt_5.7.1/5.7/android_armv7/src/android)复制到那里。

查看androiddeployqt源代码,我发现没有办法(例如通过命令行参数)更改这些.java文件的源文件夹,因此不可能提供我自己的一组文件并让androiddeployqt复制它。因此,为了实现这一点,我必须扩展/修复androiddeployqt功能(对不起,我不会碰那个代码——是的!),或者直接修改复制文件的源代码——这显然会影响使用该Qt SDK实例构建的所有项目。

作为第三种方法,我可以尝试在androiddeployqt将Java源代码复制到构建文件夹后对其进行修补。不幸的是,这不仅让开发和构建工作流程变得异常痛苦;由于CCD_ 26〃;一个工具可以做任何事情";设计失败(见下文):在构建过程中,项目中没有Java源代码,.apk包尚未构建。我以为androiddeployqt--no-build参数会启用:

--no-build: Do not build the package, it is useful to just install
a package previously built.

但是";建筑物;这里指的是构建Qt/Java桥接代码,而不是实际的应用程序,因此该参数对手头的任务几乎没有用处;此消息导致构建失败-这本身就是一个错误,因为消息中的.apk文件不存在,因此Android包构建不成功:

Android package built successfully in 1.011 ms.
-- File: <path to build folder>/android-build//bin/QtApp-release-unsigned.apk

当然,我可以将源复制到其他地方,手动修补并复制到它们的最终目的地,但我认为这就是我的底线。

事实上,查看androiddeployqt源代码是问题的症结所在。试图让功能失调的工具发挥作用已经浪费了太多时间:

  • 我不会评论在C++中编写构建工具有多聪明——在一个3000行的main.cpp文件中
  • 我不会评论在androiddeployqt源中对src/android/java路径(和许多其他路径)进行硬编码的做法——不是一次,而是多次——而不是至少准备适当(即外部)工具配置的const QString
  • 我不会评论违反一个工具,一个目的的50年最佳实践,并复制Qt、Android或Java工具提供的大量功能,如构建、签名、部署、安装软件包等,这是多么明智
  • 然而,事实上,这个工具已经通过了代码审查,进入了许多主要的Qt版本,这简直令人恐惧——这可能是一个很好的迹象,表明是时候考虑放弃Qt作为一项技术了

在我写这篇文章的时候,Qt 5.8.0的安装一直处于冻结状态,最大限度地消耗了一个CPU核心,并且在过去的12个小时里一直如此。我的案子到此为止。

我的问题

  • 有人在Qt、Android和HockeyApp方面取得过成功吗
  • 有人对这里出了什么问题有任何暗示/指点/胡乱猜测吗
  • 没有进一步的问题;我已经看够了

步骤3:从C调用SDK Java代码++

(由于步骤2中的砖墙而取消)

回答我自己的问题:

在没有修补Qt SDK工具源代码或Qt SDK Java模板源文件的情况下,在Android上与Qt一起使用HockeyApp SDK是不可能的。

事实上,据我所知,如果Qt需要修改Java源代码,就不可能在Android上使用任何第三方库。

FWIW这是我用于应用程序的AndroidManifest.xml,但没有外部库依赖关系。你可以尝试添加+修改它以使部署工作吗?

文件结构:

/my-project-dir
├── android
│   ├── AndroidManifest.xml
│   └── res
│       └── drawable-mdpi
│           └── icon.png
├── my-project.pro

AndroidManifest.xml:

<?xml version="1.0"?>
<manifest package="my_package_name" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="my_app_name" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="my_app_name" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<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="-- %%USE_LOCAL_QT_LIBS%% --"/>
<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="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!--  Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!--  Messages maps -->
<!-- Splash screen -->
<!--
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
-->
<!-- Splash screen -->
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
<!-- %%INSERT_PERMISSIONS -->
</manifest>

最新更新