Sunday, May 22, 2016

How to build KStars Lite for Android

Intro

 If you want to test KStars Lite without building then download the pre-built .apk file here (API 14, armeabi-v7a). Please, give me the feedback about it if possible (did you manage to run it, was the performance good enough, etc.)

Required dependencies

  • Qt for Android - You can download it here. Later we will point CMake to the folder with Qt libraries compiled for Android.
  • Setup Android environment:
    • Follow the instructions provided here to setup the environment
      • Most probably you will find ant in you distros repositories.
      • I had problems with ant when using OpenJDK but no problems with the latest Oracle JDK (version 8)
  • KF5 for Android - You have to build it yourself using following instructions (you can also find instructions here):
     cd /opt/android  
     git clone git://anongit.kde.org/scratch/cordlandwehr/kdesrc-conf-android.git  
     mkdir -p extragear/kdesrc-build  
     git clone git://anongit.kde.org/kdesrc-build extragear/kdesrc-build  
     ln -s extragear/kdesrc-build/kdesrc-build kdesrc-build  
     ln -s kdesrc-conf-android/kdesrc-buildrc kdesrc-buildrc  
    
    Now open the kdesrc-buildrc file in any text editor and change the following lines:
    1. line 15: -DCMAKE_PREFIX_PATH= "path to Qt5 Android libraries. Example: /home/polaris/dev/Qt5.6.0/5.6/android_armv7"
    2. Line 42 "use-modules..." : If you want to save some time then comment it with # and add after it "use-modules kconfig ki18n kplotting". Thus only modules needed by KStars Lite will be built.

    Now set environment variables and run the script:
     export ANDROID_NDK="Your path to Android NDK folder"
     export ANDROID_SDK_ROOT="Your path to Android SDK folder"
     export Qt5_android="path to Qt5 Android libraries. Example: /home/polaris/dev/Qt5.6.0/5.6/android_armv7"
     export PATH=$ANDROID_SDK_ROOT/platform-tools/:$PATH
     export ANT="path to your ant installation (/usr/bin/ant on Ubuntu)"
     export JAVA_HOME="path to your JDK (choose from the folders at /usr/lib/jvm/ on Ubuntu)
     ./kdesrc-build libintl-lite extra-cmake-modules frameworks-android  
    

    Note: It is important to have libintl-lite as a first parameter. I spent some time on figuring out that it is not built if I don't specify it explicitly. It is a dependency of KI18n without which it won't be built!
    Note 2: All the environment variables set here will be used for compiling KStars Lite so please make sure that they are set before proceeding further.

Building instructions

  • Go to your KStars source folder and set the path to source directory:
     export kstars_DIR=`pwd`  
    
  • Create in a desired location 2 folders - build for final build and export for files that will be included in apk along with the code (textures, data, icons etc.). After that set env. variable for export
     cd export
     export kstars_PRODUCT_DIR=`pwd`
  • Now run CMake to configure make files:
    I use ccmake to see which parameters are missing
     ccmake "${kstars_DIR}" 
    /opt/android is a location where you downloaded and built KF5 for Android
     -DCMAKE_TOOLCHAIN_FILE=/opt/android/kde/install/share/ECM/toolchain/Android.cmake
     -DCMAKE_BUILD_TYPE=Release
     -DCMAKE_PREFIX_PATH="${Qt5_android}"
     -DCMAKE_INSTALL_PREFIX="${kstars_PRODUCT_DIR}" 
     -DQTANDROID_EXPORTED_TARGET=kstars
     -DANDROID_APK_DIR="${kstars_DIR}"/apk 
     -DBUILD_KSTARS_LITE=ON
     -DKF5Config_DIR=/opt/android/kde/install/lib/cmake/KF5Config/ 
     -DKF5Plotting_DIR=/opt/android/kde/install/lib/cmake/KF5Plotting/
     -DKF5I18n_DIR=/opt/android/kde/install/lib/cmake/KF5I18n
    Now this is important as you wont' be able to compile config file if you set this wrong. Use the path to KF5ConfigConfig.cmake on your system. This is needed to use host system kconfig_compiler rather than the Android version.
     -DKF5_HOST_TOOLING="Path to KF5Config cmake files e.g. /usr/lib/x86_64-linux-gnu/cmake/"
    Optional: Set Android API. By default is 14. Set if your want to compile for specific Android version (e.g. API level 9 for devices >= 2.3.1)
     -DANDROID_API_LEVEL=14
    Obviously cmake has to be executed in one line with all the parameters but without comments
  • Compile KStars Lite by executing:
     make
  • You think we are done? Not yet :) Now we have to create apk file and bundle all resources in it.

    Allow inclusion of all extra files in apk
     make install/strip
     make create-apk-kstars
  • Your apk is in "build/kstars_build_apk/bin/" with the name "QtApp-debug.apk"
  • If you want to install it to your device from your PC do the following:
    • Check that your device has USB debugging switched on and connect it via USB to your machine.
    • Make sure that adb is installed (or use one from android-sdk-linux/platform-tools/adb) and run:
       adb install -d kstars_build_apk/bin/QtApp-debug.apk
    Well, that's it! You now should have KStars Lite apk file. If you want to compile KStars Lite for desktops just pass -DBUILD_KSTARS_LITE=ON to cmake and enjoy it :)

    Saturday, May 21, 2016

    KStars Lite comes to Android

    Let's start this post by watching two videos :) I have finally got KStars Lite working on Android.


    Sorry for bad quality, but it seems to be everything my old smartphone is capable of.
    And here comes the corresponding screen video! (Don't forget to set 720p)



    As you can see there are a lot of things to do - pinch to zoom right now works as scrolling with wheel, so I need to tweak it a bit. Interface will be changed completely and right now it is just my proposal prototype. Loading of files seems to take more time than on my laptop, but I'm happy to see that with asteroids and comets it still performs well on tablet (need to try it on other devices).

    And now I will tell you a small story about what has been done since the previous my post and how did I compile Android version:

    1. All nodes that are responsible for drawing graphics are now reparented to the class RootNode (later there may be used its subclasses for the same purpose). RootNode handles QSGTexture generation for stars and also clipping. The problem with clipping was that in QtQuick Scene Graph you can't draw ellipse as OpenGL draws everything in triangles. To do it I found C++ triangulation algorithm implementation specifically tailored for QQuickItem, but it was designed to handle all kinds of polygons so it required a lot of resources and made SkyMapLite really slow. Later I found much simpler solution: choose some corner (in the case of ellipse any its point) and create a triangle from this point to the next 2 points. Simple but works perfectly.
    2. Added asteroids and comets. To do it I changed the structure of nodes a bit. So now there are 2 types of SkyNodes - PlanetNode and PointSourceNode. Both of them reflect to SkyPainter's functions drawPlanet and drawPointSource. For all objects in PlanetItem and some of the objects in AsteroidsComet PlanetNode is used, while CometsItem uses only PointSourceNode to draw comets as stars. After adding asteroids and comets performance didn't fall down. I even tried to draw all of them as bright stars without any checkings on magnitude/zoom level and everything worked well.
    3. Android build - well, that is a long story :) Initially I thought about it as something easy to do and haven't even included to my tentative timeline in proposal, but I was totally wrong. First there was a problem with KF5 dependencies because less than a half of KF5 modules are available for Android.
      My mentor, Jasem Mutlaq, made a great thing and got rid of KIO dependency, without which I was able to compile Android version. Even after that it didn't work and I got only a black screen. I spent a lot of time trying to setup debugger as you can't debug CMake project for Android from Qt Creator. The only feedback from my tablet that I am able to get now is looking at log output (which seems to be sufficient as all major errors are there).
      After spending a plenty of time on searching for a cause of black screen, I found out that "include(KDECompilerSettings NO_POLICY_SCOPE)" in top CMakeLists.txt file seems to cause the error. Without it everything worked fine, but still I had to tackle a few minor bugs before I was able to see SkyMapLite on my tablet.
      I also started to work on pinch to zoom as you can see from my video. 
    You will find instructions on how to compile KStars Lite for Android in my next post (which will be published tomorrow I hope). For now, I will run Android build in various Android emulators to see whether it works fine everywhere and then I will port PlanetMoons to KStars Lite. Stay tuned!

    Sunday, May 8, 2016

    Starting from the shore of cosmic ocean

    This week I made the first commit to KStars Lite branch (gsoc2016-kstarslite). This commit includes everything that I made during my first week of coding:
    1.   My mentor and I agreed that code for KStars Lite will be included to the main branch using #ifdef KSTARS_LITE macro condition. Though this solution is not beautiful the amount of code duplication is significantly reduced this way. However, some of the functionality still needs separate classes so I created KStarsLite(KStars), SkyMapLite(SkyMap) and a bunch of new classes for handling planets. The only modification to KStarsData was to add parameter name in signal void progressText ( const QString& text ); because in QML you can't handle unnamed signal parameter.
    2. KStarsLite - It initializes SkyMapLite and KStarsData. Apart from the code for SkyMapLite instantiation most was copied from KStars because of the same functionality.
    3. SkyMapLite - The pan and zoom functions were copied from SkyMap. Added functionality for displaying and updating SolarSystemSingleComponent on SkyMapLite. Moved cache for star images from SkyQPainter to this class. Currently, only LambertProjector is available because I wait for an answer from KStars community whether I can move Projection enum from SkyMap to Projector class so I can use it in SkyMapLite without including skymap.h
    4. Added support for displaying planets on SkyMapLite. Like in SkyMap, the planets can be drawn either as stars (using cached star images) or as planet images. Apart from storing star images in the cache, we can cache QSGTexture objects that are created from images. So with my initial approach where each planet has its own QQuickItem derived object I wouldn't be able to use cached QSGTextures for all planets. Finally I ended up with the following:
      1. PlanetNode that holds an image of star and image of planet
      2. PlanetItemNode that stores all PlanetNodes, creates QSGTexture objects from cached star images and caches it upon its creation. 
      3. PlanetItem - QQuickItem derived class that holds pointers to SolarSystemSingleComponent objects, displays all nodes and is a visual child of SkyMapLite.
      4. Every SolarSystemSingleComponent upon its creation calls SkyMapLite::addPlanetItem(SolarSystemSingleComponent* ) to add PlanetNode in PlanetItemNode. Based on zoom level PlanetNode hides and shows picture of planet or star image. It turns out that this approach won't be so complicated as I thought about it. To make some things clear to me I asked a few questions on Qt Interest mailing list.
    5. Moved Splash screen to QML. Splash screen might be later replaced by full screen version that is more suitable to different screen sizes of mobile devices.
    Only planets are currently displayed. (Click to zoom)

    Next thing to do

    Right now I struggle to make Options class available for use from QML because for some reason I get an error while compiling config files with support for QML so I wrote an e-mail to one of the developers of KConfig compiler asking how can I solve this problem.
    In the upcoming week, I plan to implement clipping polygons for all projection systems, make it possible to display planets as ellipses, introduce asteroids and comets to SkyMapLite and setup CMake project for compilation for Android. Asteroids and comets will bring interesting results as QtQuick version of KStars will show its performance on displaying a lot of objects (not that many as there are stars but still something to measure:) ).