How to build FBReaderJ (Android)

FBReader (https://fbreader.org) is a very well-developed open-source e-book reader. However many issues are met if you download the code and try to build it for the first time.

I made some changes to the configuration files, guide-line as well as some change of the code, etc, so as to make the ant build more smooth. If you check out the github version here (based on 2.5.10), just follow the guideline written in HowToBuild, and you would probably succeed in the building without no much troubles.

Note:  the way I build is still based on the ant build which the original project uses. There are some ports already available to migrate to Android Studio with Gradle build, as shown in this link. However I have not tried that, yet.

Following are the detail steps that I made the changes and built. These steps and changes have been included in the github link above. You need to following below steps again, ONLY IF if you’d like to build based on the official version of FBReader, and before these changes are accepted in the main-stream.


 

I am demonstrating via Linux. Some minor changes of the steps can be made if you build from Windows.

Assumption: required version of JDK, SDK, NDK, etc installed properly.
1. Clone a local copy of the master branch

> git clone https://github.com/geometer/FBReaderJ.git

We assume the folder of FBReaderJ has been exported as an environment variable:

> export $FBReaderJ=<your path after cloning the code>
2. Create local.properties file under FBReaderJ/ folder
This is essential for ant build.

The file include following two lines. Change the path to correct SDK and NDK location.

   sdk.dir=/home/gordon/Android/Sdk
   ndk.dir=/home/gordon/Android/Sdk/ndk-bundle

3. When building in linux, ant build will including the building of native libraries.

Run

> ant release

ant it will run ndk to build the native libraries (take quite some time, be patient)

Now you will meet some errors that the orginal HowToBuild file did not mentioned. Some are easy to solve, just need to understand what it means. But some needs more trouble-shooting.

Here is the solution for each one of the issue:

4. If you meet following error: “Unable to resolve project target ‘android-xx'”

This is because the corresponding version of SDK is not installed.

There are two solutions.

Solution 1, install all required sdk versions:

Run following command:

<sdk.dir>/toosl/android sdk

Then install following versions of SDK. (select, and click install…)

Android 4.4.2 (API 19)
Android 4.0   (API 14)   –  (need to kick ‘obselete’ first to show up)
Android 3.0   (API 11)   –  (need to kick ‘obselete’ first to show up)
Android 2.0   (API 5)    –  (need to kick ‘obselete’ first to show up)

You need to install all of them. This takes quite a long time, but it can be avoided, as shown in solution 2.

Solution 2, change the project.properties settings to use single version of SDK (preferred)

Edit following 5 files:

$FBReaderJ/project.properties
$FBReaderJ/third-party/AmbilWarna/project.properties
$FBReaderJ/third-party/drag-sort-listview/library/project.properties
$FBReaderJ/third-party/SuperToasts/project.properties
$FBReaderJ/third-party/android-filechooser/code/project.properties

Change all lines of “target=android-xx“, to “target=android-19

And just install Android 4.4.2 (API 19) as shown in Solution 1.

After either solution 1 or 2, re-run  ant release under $FBReader folder.

5. If you meet following error:

…../build.xml:55: sdk.dir is missing. Make sure to generate local.properties using ‘android update project’ or to inject it through the ANDROID_HOME environment variable.

That is because the FBReader project contains totally 5 sub-projects actually (FBReader, and four 3-rd party libraries.) It turns out that each sub-project needs to be built seperately, and each of them requires a local.properties file. The command “android update project” as in the prompt message, does not work out for me. So I just simply copy the same local.properties file to each folder of sub-projects.

cd  $FBReaderJ
   cp  local.properties  third-party/SuperToasts/
   cp  local.properties  third-party/android-filechooser/code/
   cp  local.properties  third-party/drag-sort-listview/library/
   cp  local.properties  third-party/AmbilWarna/

6. You SHALL meet the following error, which is now a compile error:
-compile:
[javac] Compiling 34 source files to /home/gordon/FBReader_mastar/FBReaderJ/third-party/android-filechooser/code/bin/classes
[javac] /home/gordon/FBReader_mastar/FBReaderJ/third-party/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/FileComparator.java:16: error: package org.fbreader.util does not exist
[javac] import org.fbreader.util.NaturalOrderComparator;
[javac]                         ^
… … …

This did cost me quite some time to figure out the issue. It turns out that the main FBReader project, and the 3rd party library “android-filechooser” somehow have a loop dependency (each depends on the other).  The FBReader relies on the jar file generated by “android-filechooser”, however the “android-filechooser” depends on a utility class within the org.fbreader.util package.

Normally it shall not happen. It looks like there was some enhancement in “android-filechooser”, and a class “NaturalOrderComparator” was added to support this enhancement, and this classes are used in some other class in org.fbreader, so the new class was added into the org.fbreader.util package. The solution for me, is to move the NaturalOrderComparator class to the android-filechooser.  One may try to compile NaturalOrderComparator first, and resolve the issue of building “android-filechooser”. But it is not ideal.

Solution: requires some change to the code, and moving the file.

In terminal:

Move the file:

mv  $FBReaderJ/fbreader/app/src/main/java/org/fbreader/util/NaturalOrderComparator.java \

            $FBReaderJ/third-party/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/

Edit file NaturalOrderComparator.java, change the first line:
         package org.fbreader.util;
to
         package group.pals.android.lib.ui.filechooser.utils;

Edit file FileComparator.java under the same folder,

delete or comment out the following code line, and save:

     import org.fbreader.util.NaturalOrderComparator;

     Edit following two java files:
$FBReaderJ/fbreader/app/src/main/java/org/geometerplus/fbreader/library/FileTree.java
$FBReaderJ/fbreader/app/src/main/java/org/geometerplus/fbreader/sort/TitledEntity.java

     change the line:

      import org.fbreader.util.NaturalOrderComparator;
to
      import group.pals.android.lib.ui.filechooser.utils.NaturalOrderComparator;

Then rerun “ant release” under the folder <FBReaderJ>

7. When meet following error:

[javac] /home/gordon/FBReader_mastar/FBReaderJ/third-party/drag-sort-listview/library/src/com/mobeta/android/dslv/DragSortCursorAdapter.java:10: error: package android.support.v4.widget does not exist
[javac] import android.support.v4.widget.CursorAdapter;
[javac]                                 ^

It is very obvious, you need to install the Android support library. However, even you have installed the library, the error will be still there. The key is to let the ant build find out the support library. There are some discussions and solutions on StackOverflow, but the only thing works for me, is just to copy the library jar file “android-support-v4.jar” to the folder for the 3-rd party library.
The tricky things is, if you copy the newly installed “android-support-v4.jar” file from your SDK folder, there will be another error telling you a conflict of version. This is because there is already a support library in the folder $FBReaderJ/libs, which is an older version than your newly download one.  So a simple solution, is just to copy this library to the third-party folder, as shown below:

> cp $FBReaderJ/libs/android-support-v4.jar    $FBReaderJ/third-party/drag-sort-listview/library/libs

Then rerun ant release again.

Then finally you shall be able to complete the build with “BUILD SUCCESSFUL”.
You can find out the unsigned apk file in $FBReaderJ/bin

Sign the APK according to the guideline: http://developer.android.com/tools/publishing/app-signing.html