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

Patricia Aas paaas at cisco.com
Mon Feb 25 15:44:38 CET 2013


On Mon, 25 Feb 2013 14:36:51 +0100, Eskil Abrahamsen Blomfeldt  
<eskil.abrahamsen-blomfeldt at digia.com> wrote:

> On 02/25/2013 01:52 PM, Patricia Aas wrote:
>> 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.
>
> Most paths you specify in Qt are file system paths, i.e. relative to the
> working directory. This is not so easily solvable, I think, because we
> don't have the concept of search paths (where passing a relative path to
> e.g. QPixmap would make it search a set of different root paths for
> instance.)
>
> I wonder how much would break if the "working directory" was the assets
> root...

For porting ease that would make a lot of sense, the only problem is that  
assets is not a directory. On the other hand using files as root makes no  
sense either, it is like using /tmp as HOME.

> I think the main cross-platform way of doing this if you can't store
> your resources as qrc, is to have some platform-specific path resolving
> mechanism in your code (which would limit the number of #ifdef ANDROID
> to 1). Then it would resolve to assets in Android, to the working
> directory on desktop, etc. I think other mobile platforms might have the
> need for similar customization. You would have to expose it as a
> property in QML and update all the paths there (file:/ for desktop,
> assets:/ for Android, etc.).

This is a hard solution for making a cross platform application, it  
requires really a porting layer for Qt aswell, and I think that should be  
avoided if possible. Most things in this category are abstracted away by  
Qt normally. And I assume would be an issue for most applications trying  
to port.

> Or it might be possible to add a new storage location to (the aptly
> named) QDesktopServices, but the code you have which specifies loading
> from the file system will still have to be updated.

I will have to look into this.

>> 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.
>
> Would it be possible to put one qmldir for the plugin next to the plugin
> in lib/, and another for the QML files next to the QML files in assets?

The android idea for the lib directory seems to be a pure shared lib  
thing. So this will be kind of strange in Android. And I don't think it  
would work without code changes in Qt either because it takes the qml  
plugin include, splits on '.' and replaces it with '/' (if I remember it  
correctly), then searches the path for a qmldir within this subpath, then  
tries to load the plugin in that directory.

>> 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
>
> It will also mean duplicating the QML files in the import for every
> architecture you want to support, I guess.

Yes, though I assume that could be handled in a packaging arranging step,  
but it still would be very nonstandard even if it did work.

>>
>> 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 think this is a down-side of specifying file system paths in the QMLs
> explicitly.

But I don't see a way I can keep the qmls as qrc's and not have the images  
as qrc's and have cross platform code. Am I missing something?

>>
>> 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.
>
> When you use the file:/ scheme, you are telling QML to load the files
> from the file system. That's what the scheme is for. This is probably a
> work-around for wanting to have the QML-files in the qrc and the images
> stored on the file system relative to the executable. Maybe it's because
> the qrc files became to large for the compiler (in which case it might
> work to split it up in several qrcs instead, since Qt's resource system
> can easily adapt to that.) If there are limitations to the size of the
> application binary that make it impossible to put the resources in the
> qrc, it's also possible to make an external resource file which could be
> bundled with the application. On Android, if you have a very large set
> of resources, this will usually be distributed as a separate
> downloadable file (.obb) since the possible size of an .apk is very
> limited in Google Play. There is no out-of-the-box solution for this in
> the tooling yet though, so it would mean editing the Java code.

The choice for keeping them separate, as far as I understand, was for a  
different product/platform, and is therefore a very big change for us, so  
we would like to keep this separation if possible.

> To minimize the impact for other platforms, what I would do would be to
> add a platform abstraction file (android: SOURCES +=
> platform_android.cpp else: SOURCES += platform_desktop.cpp),  with an
> asset-scheme property which is exposed to the QML code. In the desktop
> implementation it will be "file:" whereas it will be "assets:/" on
> Android. Then you can update the QML to use the correct scheme for
> loading the files based on this property. You could also make a special
> AssetImage.qml or something which automatically prepends the scheme to
> the paths, so that you can easily update it later if you need to.

Yes, I could do that, but it places quite a heavy burden on the  
application port, which I really think should be supported "out of the  
box" by the Qt port :)

>>
>> 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
>
> We did have a suggestion to enable qrc:/ to also load from assets:/ so
> that you can have a single resource prefix, but in your case that
> wouldn't work since you are explicitly telling QML to load from the file
> system with the file: prefix. So far we've opted against it, since it
> would be a little bit too magic and we thought qrc:/ would be the scheme
> of choice for writing cross-platform resource handling.

I see, and I think I agree with you on the qrc != assets. But I do think  
that assets and filesystem is the same thing for a port, and the fact that  
assets is a strange animal should, if possible, be hidden from application  
authors. Though I am not sure what I think the solution should be.

>>
>> 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
>
> Ah, I think removing "-platform android" and making it the default is
> needed. We shouldn't really force command line arguments on the apps.

Good :)

> Thanks for being so thorough in documenting the problems you had. I
> think a lot of this should be addressed and you have good suggestions. I
> do think your code needs to be updated a bit as well, though, to make it
> more generic, since the idea of accessing files using file:/ does not
> seem portable to me, since not all platforms will support the idea of a
> regular file system and definitely not the idea that the application
> bundle is a regular directory structure in the file system. Overriding
> file:/ for Android code would break any case where you specifically want
> to load a file from the file system (which is also possible on Android).

Because of the need to explicitly load a file from files, is the reason  
why I am not sure what the right solution should be. I would have to play  
around with it for a while. But at least for us, that is hardly a  
use-case, but loading our own resources is a big one, and right now that  
just doesn't work properly.

> Do you think any of the suggestions I've made would be helpful to you?

Yes, and thank you for you time. I will continue to work on this,  
hopefully I can come up with a solution that will work for both cases.

> -- Eskil
> _______________________________________________
> Android-development mailing list
> Android-development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/android-development


-- 
Patricia Aas
Developer
Cisco



More information about the Android-development mailing list