[Android-development] Attempting a port to Android - Notes and Suggestions

Patricia Aas paaas at cisco.com
Mon Feb 25 13:52:44 CET 2013


Hi!

First of all a big thanks to eskil, paulot and bogdan on the #necessitas
irc channel for invaluable help.

My apologies for the _way_ too long mail, first I will give a short
Summary of Suggestions, in the Long Story you can read why I am suggesting
them, in the Epilogue ;) I wrap it up

Summary of Suggestions ( The letter refers to the Long Story section below
:D )

A ) Maybe some docs around shared libs in android would be nice in a
porting guide
B ) Assets should be loaded automatically, without the assets:/ prefix,
will probably require changes to AndroidAssetsFileEngineHandler
C ) Loading of QDeclarativeExtensionPlugin should be possible with the
plugin lib in libs and the qmldir folder structure in assets:/imports,
will require changes to the handling of QML_IMPORT_PATH. And both libs and
assets:/imports should be in the QML_IMPORT_PATH by default
D ) Loading of QGenericPlugin to be possible with the plugin lib in libs,
might be enough to put libs in the plugin path by default (I will test
this soon)
E) Custom QtActivity.java::APPLICATION_PARAMETERS should be passed first
to main before any other parameters needed by the android port

Long Story :

I have been asked to try the android port by porting an existing Qt
application. Now not really knowing how much I am allowed to say (NDAed
and such) I will keep it a bit cryptic (sorry).

First a short description of the project :

It is currently running on linux, it has a few shared libs (5-6), a couple
of plugins (QGenericPlugin) and a few qml plugins, a few proprietary
plugins (using a proprietary interface that we load ourselves), quite a
few of pngs used for the ui (450'ish), qmls as qrcs (version 1), a bunch
of translation qm files and of course our own font :D Not all of these
things are in order yet in my hacked attempt at a port.

I was playing with necessitas first and then moved over to the Qt5 port.

Quite a bit of time was spent on Android things :

1) A lot of fiddling with shared library dependencies (readelf -d) to make
sure they are acceptable to Android and making sure all so's are loaded in
right order.

2) Learning the limitations of the packaging system and getting the
package right

3) Finding alternatives when Android libs/system api's didn't exist or
were different somehow (eg. backtrace(..) from execinfo.h)

Given the above (especially #2) I have ended up with this structure in my
package :

* libs are packaged in libs as per Android packaging - and that is the way
qmake sets it up also
* all other resources are in assets - this is because of the fact that we
have a directory structure in our resources, which is also needed: we have
over 500 resource files - most of them images

Looking at my diff, my changes can be grouped as follows :

A ) Setting lib dependencies up and ordering the loading so that Android
is happy (which is fine I guess)

Suggestion : maybe some documentation on this would be nice in a porting
guide, but this is not really a Qt issue.

B ) A lot of resource file path fiddling : this is because all of my
resources are in assets - which means file paths are all broken, Qt seems
to assume they are in files, which is completely empty, unless you
actually copy stuff there. Path fiddling results:

for cpp : If I change everywhere to use assets:/ then they are found, but
all my code as #ifdef __ANDROID__ everywhere
for qml : I don't even know if I can have #ifdefs in qml files, so what I
did was copy all of my pngs into files on startup, in java code, which
takes forever (see AssetHandler.java attached for how I did that)

Suggestion : The Qt port should transparently handle all paths to be in
either files or assets, and relative paths should work across these - see
point D about qmls in qrc's.

C ) QDeclarativeExtensionPlugin :

C.1 : It doesn't find my plugin in libs unless I add libs to
QML_IMPORT_PATH. That could maybe be ok...
C.2 : It doesn't find my qml folder structure in assets (containing my
qmldir), adding "assets:/imports" to QML_IMPORT_PATH doesn't fix it,
probably (at least) because it has a colon in it, and the QML_IMPORT_PATH
is split on ':'
C.3 : Even if C.1 and C.2 had worked, it still wouldn't work, because when
it does find the qmldir, it looks for the plugin lib in the same directory
and doesn't search the whole QML_IMPORT_PATH for it making it impossible
to have them separated.

Now to work around C.2 I copied my whole imports directory from assets
into files in java code, now the qmldirs could be found, but because of
C.3 it still didn't work. So I had to copy all of the plugin libs into
files aswell (see AssetHandler.java attached for how I did that)

Second possibility that I have not managed to make work is to make a
directory structure in libs/armeabi-v7a where the qmldirs are placed, this
has two issues even if I could make it work : 1) it is very non-standard
Android 2) because of 1 the tools support will be non-existent

Suggestion : loading of QDeclarativeExtensionPlugin should be possible
with the plugin lib in libs and the qmldir folder structure in
assets:/imports and both of these should by default be in QML_IMPORT_PATH

D ) qmls in qrc's:

Now given the following hack for C) : I copied my imports folder from
assets into files and my qml plugin so's into the folders containing the
corresponding qmldir (see AssetHandler.java attached for how I did that)

So now I got my plugins up and running.

None of my images were available because the qmls are qrc's and the images
are in assets, the path in the qmls was "file:images/..." and that
apparently meant the files directory - which now only contains the imports
directory I copied.

I have three choices : 1) copy all of the images from assets into files 2)
change all of the "file:images/..." to "assets:/images" or 3) make some
qml code that depended on a property in cpp that used an #ifdef __ANDROID__

Number 2) is not possible - it would break existing products and, even if
it didn't, I tried it, and it still did not find them, relative paths
across qrc and assets apparently is not ok.
Number 3) would not fly with the rest of the developers, they felt I had
already too many ifdefs ;)
so left with Number 1) that is what I did, now that will not fly either :
the startup delay with copying the files is not acceptable.

So I have no workaround that is acceptable for production.

Suggestion : Mentioned in B already, but relative paths from qrc to assets
would have to work, plus the resource files would have to be found even
though they are in assets, without the "assets:/" being hardcoded in the
qmlfile

D ) QGenericPlugin loading, Qt doesn't seem to find it and/or load it when
I package it in libs.

Now this did not work out of the box, and I ended up loading it myself,
but after the round with QDeclarativeExtensionPlugin in C), I am hoping
that setting the plugin path to libs would make this work out of the box.
*fingers crossed*

Suggestion : Plugin path should automatically include the libs directory

E ) Order of command-line arguments :

Now this is a silly thing in our code really, but we need to support
existing client code. Our main expect to get two parameters first in the
command line args, now I can add command line args in
QtActivity.java::APPLICATION_PARAMETERS but these are added after the
"-platform android" parameter added automatically. I added #ifdef
__ANDROID__ to fix that up :D

Epilogue :

It seems to me that a lot of the trouble above stems from the way Android
demands that its install look like, and that this does not fit well with
other platforms Qt runs on. The special opaque "assets" idea and rigid
directory layout breaks a lot of seamlessness when porting. Now I think
that this could probably be hidden in a more ambitious
AndroidAssetsFileEngineHandler and in a more liberal handling of
QML_IMPORT_PATH and lastly in a realization that HOME really should have
been in assets, but assets is not a directory.

Thank you very much for your time,

-- 
Patricia Aas
Developer
Cisco
-------------- next part --------------
A non-text attachment was scrubbed...
Name: AssetHandler.java
Type: application/octet-stream
Size: 7691 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/android-development/attachments/20130225/e8cdb8ac/attachment.obj>


More information about the Android-development mailing list