Home:ALL Converter>How to use HockeyApp SDK with Qt on Android

How to use HockeyApp SDK with Qt on Android

Ask Time:2017-01-24T23:42:12         Author:ssc

Json Formatter

I am trying to integrate the HockeyApp Android SDK in its latest version 4.1.2 into our Qt Android app. I don't know a lot about Android development or Java in general - nor any Qt or HockeyApp internals.

There is some general official documentation on including third party Android (i.e. Java) libraries into a Qt project; however, it mentions a "Create AndroidManifest.xml button in the Deployment settings" which does not exist in the current Qt Creator 4.2.0 version, so I am unsure as to how outdated this documentation is or what parts possibly still apply.

HockeyApp documentation only covers "typical Android development" using Android Studio and their support is not supportive.

On a side note, integrating the HockeyApp iOS SDK took just a couple of hours and was mostly a matter of writing some Objective C bridge code.

Step 1: Add the SDK to the project

First approach

I tried to follow the above documentation and added the unzipped HockeySDK-Android-4.1.2 folder and a project.properties file with contents

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

to a project folder; I also set ANDROID_PACKAGE_SOURCE_DIR in <my project>.pro to that project folder.

Problem: The androiddeployqt build step issues an error message (wrapped for readability)

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

but continues anyway and finally fails with an error message (also wrapped for readability)

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

Running androiddeployqt with a --verbose switch adds significantly more output, but zero useful information.


Second approach

The downloaded HockeyApp Android SDK zip archive contains - besides some documentation - a file libs/HockeySDK-4.1.2.aar; from this response and this comment, I gather the AAR format is simply a zip archive that, among others, contains an AndroidManifest.xml file. I unzipped libs/HockeySDK-4.1.2.aar in place, then removed it; now the first error message in the build is gone.

Problem: The build fails with

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.

Again, adding running --verbose to androiddeployqt adds nothing but noise. Looking into the build.xml locations mentioned doesn't help either.

Update:

I tried simply creating the missing folder from the error message; now the build fails as follows:

-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

I obviously can not just make up some classes.jar file, but there is one single file with that name in <path to build folder>/android-build/HockeySDK-Android-4.1.2/libs, so I can create the missing bin folder and create a symlink in it to ../classes.jar.

The build now succeeds. Step 1 complete.

Step 2: Use the SDK in the project

Going back to the corresponding HockeyApp documentation, I gather I need to modify some code that looks similar to

public class YourActivity extends Activity
  ...

There is one single occurrence of such code in the project in <path to build folder>/android-build/src/org/qtproject/qt5/android/bindings/QtActivity.java:

public class QtActivity extends Activity
  ...

That file is copied there by the androiddeployqt tool (part of the Qt SDK) from its source folder inside the Qt SDK at $QTDIR/src/android/java, i.e. /opt/Qt/Qt_5.7.1/5.7/android_armv7/src/android on my machine.

Looking at the androiddeployqt source code, I see there is no way (e.g. by means of a command line parameter) to change the source folder these .java files are taken from, so it is not possible to provide my own set of files and have androiddeployqt copy that instead. Hence, in order to make this work, I must either extend / fix androiddeployqt functionality (sorry, I won't touch that code - yuck!) or modify the copied files at their source directly - which then obviously affects all projects build with that Qt SDK instance.

As a third approach, I could try patching the Java sources after androiddeployqt copied them to the build folder. Unfortunately, this not only makes the development and build workflow absurdly painful; it is also made entirely impossible by the androiddeployqt "one tool does everything" design fail (see below): There is no point in time in the build process where the Java sources exist in the project and the .apk package has not been built yet. I thought the androiddeployqt --no-build parameter would enable that:

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

but "building" here refers to building the Qt / Java bridge code, not the actual app, so that parameter turns out to be pretty much useless for the task at hand; the build fails with this message - which by itself are a bug as the .apk file from the message does not exist and thus the Android package build was not successful:

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

Sure, I could copy the sources elsewhere, patch and copy them manually to their final destination, but I think this is where I draw the line.

Actually, looking at the androiddeployqt source code is where the buck stops. Too much time has already been wasted trying to get dysfunctional tools to work:

  • I will not comment on how smart it is to write a build tool in C++ in the first place - in a single, ~3000 line main.cpp file
  • I will not comment on the practice of hardcoding the src/android/java path (and many other paths) in the androiddeployqt sources not once, but multiple times - instead of a const QString that at least prepares appropriate (i.e. external) tool configuration
  • I will not comment on how smart it is to violate the ~50 year old best practice of one tool, one purpose - and duplicate large amounts of functionality provided by Qt, Android or Java tools, such as building, signing, deploying, installing packages, etc.
  • However, the fact that this tool has made it past code review into a number of major Qt release is nothing short of frightening - and probably a good indicator that it's time to consider dropping Qt as a technology in general

While I am writing this, the Qt 5.8.0 installation keeps freezing, maxing out one CPU core - and has been doing so for the last ~12 hours. I rest my case.

My questions

  • has anyone had any success with Qt, Android and HockeyApp ?
  • does anyone have any hints / pointers / wild guesses as to what is wrong here ?
  • no further questions; I've seen enough

Step 3: Call SDK Java code from C++

(cancelled due to brickwall in step 2)

Author:ssc,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/41832291/how-to-use-hockeyapp-sdk-with-qt-on-android
ssc :

Answering my own question:\n\nUsing the HockeyApp SDK with Qt on Android is not possible without either patching Qt SDK tool source code or Qt SDK Java template source files.\n\nIn fact, from what I gather, it is not possible to use any third party libraries with Qt on Android if they require Java source code modification.",
2017-01-25T14:51:10
yy