New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Android port of koreader #320
Comments
Ha, I am pretty sure it's going to become the best reader :) But I am not likely to have time working on this until December :( @hwhw is also the author of droidreader, he should have a lot of experience on android development. |
Well, that would attract a lot of developers I think! And new features and fixes for everybody. Nice idea. |
The only thing that bothers me is how to handle our relationship with coolreader (if the android port really happened). It makes me feel bad to just grab coolreader's engine and make another reader out of it in it's main target market :( Is it possible to port our pdf/djvu stack to coolreader? |
A straight port shouldn't be too hard. That would mean keeping our own UI. I'm not sure if that would be desirable... But then, I'm used to it :-P Adding other blitbuffer layouts (color!) would be a logical next step there. It would be a Java shim that creates a pane to blit to, passing events to native code, and let the rest be handled by native code. Since Android 2.something one can directly blit to on-screen surfaces. I agree with houghp that porting our page-based document stack to CR would be an interesting idea, too. |
Actually I remember seeing a djvu branch in coolreader's repo ;p It's author might actually considered adding page-based document stack before. |
We probably could easily use this to make a first try: http://developer.android.com/reference/android/app/NativeActivity.html - we would not have native UI elements, but rather the "original" feel of Koreader. I will concentrate on two other things first: FFI-bindings for input and output, and a multi-bpp blitbuffer implementation. In theory, we could go "colored" in Android then. |
I like the touch-to-go UI of koreader without any fading or animation. So the straight feel is OK for me. :) |
I think the easiest port for Android is creating a launcher in the Android part and use libsdl to handle the input and output like in the emulator. Other parts of koreader are highly portable that should run on virtually any modern handheld computing devices. |
OK, I now had a deep look into this and have made good progress already. I have kind of a "luajit-trampoline", which - as a NativeActivity - loads the LuaJIT interpreter. I verified that LuaJIT can then run as a main thread, doing native Android API calls via FFI (!). This works just great. I already interfaced with the blitbuffer implementation and am able to read input events. I think I'll need about 1-2 days and I'll have some first version ready. It will still be a bit rough around the edges, but it's going great for now. I dumped the idea to use SDL for now. SDL2 has a nice Android implementation, but it comes with a big gotcha: It has a polling event loop, keeping the CPU busy and needlessly eating the battery. For a game, that might be negligible, but for a reader not so much. That said, the Android native activity API is nice enough to just go with it. |
Exciting news!! Cannt wait to see your first demo :) |
That's great! I cannot wait to try it. |
It turns out to be a bit harder than I initially expected. This is not the fault of the approach chosen: That still looks promising. If someone would like to have a try: https://github.com/hwhw/android-luajit-launcher The hard part, however, is to persuade the software stack we are using to work with the Android toolchain, which lacks a few things and cooperates badly with old versions of libtool, config.sub/config.guess and other stuff. It's a bit awful to work through compile and link failures over and over... So it may still take a few days. |
The launcher is really cool. But I failed to load library with |
Hm, I'm just back from a few weeks of vacation, now I need to keep up with a few things and then I really hope I can get back to this. We should be allowed to load libraries from the applications data folder, so we will need to clone the launcher and make it the base of a (specific) Android application, I think. But I need to get back into the remains of my project folders, I think I played a bit with such things already. |
I can load libmupdf with absolute path, but can't force dlopen to search dependencies in app data directory :( |
OK, so we have to manually load all the dependencies in reverse order, heh: EDIT: or we can port lo_dlopen to LuaJit: |
Another thing. Since android port will have a completely different source tree structure, we should maybe start factor out the frontend part from koreader into a separate reusable git repo. |
I was thinking to compile all base libraries into one big static lib to circumvent library dependency hell on Android. |
Yes, I guess this is possible. But licensing issues might prevent this... On 15. Mai 2014 14:10:20 MESZ, Huang Xin notifications@github.com wrote:
Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail gesendet. |
@hwhw , can you explain more about the licensing issue? |
How about loading all libraries in the android_main like here https://github.com/MIvanchev/hx-gameplay/blob/master/haxelib/native-glue/android/src/android-main.cpp#L145. It first resolves the application data directory by fiddling with the jvm and then loads necessary libraries with the absolute path. And it seems to work without big re-factoring of ffi code. local mupdf = ffi.load("mupdf")
A.LOGI("mupdf library loaded "..tostring(mupdf)) The log shows:
|
And I also found a great script to compile GNU world programs in Android. http://forum.xda-developers.com/showthread.php?t=1444792. |
yeah, we can construct the absolute path that way. i don't understand how the |
Since |
Right, but I have to use absolute path, otherwise I will get the error: |
Yes. But if you loaded the "libmupdf.so" before in And I also have a good news. I finally succeeded to compile almost all libraries for Android except |
Oh, I see. Should have read your post more carefully ;p Are you using android emulator right now? |
No. I just compiled the base libraries with a standalone toolchain from NDK and made some minor changes of the makefile. Still don't know if they would run at all. |
But it could be a start I think. I will send a PR and create an android branch tomorrow. |
Hi, pretty cool! I was marching the same path, but didn't get that far. |
The local mupdf = ffi.load("libs/libmupdf.so")
A.LOGI("mupdf library loaded "..tostring(mupdf)) After wrap the ffi.load = function(name, ...)
return ffi.C.lo_dlopen(ffi.cast("char*", name))
end The result goes: I/luajit-launcher(10979): dlopen(/system/lib/libdl.so) = 0x400c40ac
I/luajit-launcher(10979): dlopen(/system/lib/libc.so) = 0x400c4cf8
I/luajit-launcher(10979): dlopen(/data/data/org.koreader.launcher/libs/libjpeg.so.9) = 0x400c9964
I/luajit-launcher(10979): dlopen(/data/data/org.koreader.launcher/libs/libjpeg.so.9) = 0x400c9964
I/luajit-launcher(10979): dlopen(/data/data/org.koreader.launcher/libs/libfreetype.so.6) = 0x400c9a88
I/luajit-launcher(10979): dlopen(/system/lib/libm.so) = 0x400c4f40
I/luajit-launcher(10979): dlopen(/system/lib/libstdc++.so) = 0x400c4e1c
I/luajit-launcher(10979): dlopen(/system/lib/liblog.so) = 0x400c4bd4
I/luajit-launcher(10979): dlopen(/data/data/org.koreader.launcher/libs/libmupdf.so) = 0x400c9bac
I/luajit-launcher(10979): mupdf library loaded cdata<void *>: 0x400c9bac |
Wow, that is pretty cool! |
\o/ So what is left is mapping the input and output between koreader and android? |
Yes, I think so. And that shouldn't be too hard either. The BlitBuffer abstraction is capable of using what Androids provides us with - that would be for output. However, for input, we need to think on what level we want to start. We could synthesize Linux Input style events, just as the emulator does. It's probably the easiest way to start. |
OK. Both Lua C module and native library loading are tested on Android. local mupdf = ffi.load("libs/libmupdf.so")
A.LOGI("mupdf library loaded "..tostring(mupdf))
local leptonica = ffi.load("libs/liblept.so.3")
A.LOGI("leptonica library loaded "..tostring(leptonica))
local tesseract = ffi.load("libs/libtesseract.so.3")
A.LOGI("tesseract library loaded "..tostring(tesseract))
local k2pdfopt = ffi.load("libs/libk2pdfopt.so.2")
A.LOGI("k2pdfopt library loaded "..tostring(k2pdfopt))
local crengine = ffi.load("libs/libcrengine.so")
A.LOGI("crengine library loaded "..tostring(crengine))
local pdf_loaded = require("libs/libkoreader-pdf")
A.LOGI("koreader-pdf loaded "..tostring(pdf_loaded))
local cre_loaded = require("libs/libkoreader-cre")
A.LOGI("koreader-cre loaded "..tostring(cre_loaded)) I/luajit-launcher(16412): dlopen(/system/lib/libdl.so) = 0x400c40ac
I/luajit-launcher(16412): dlopen(/system/lib/libc.so) = 0x400c4cf8
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libjpeg.so.9) = 0x400c9964
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libfreetype.so.6) = 0x400c9a88
I/luajit-launcher(16412): dlopen(/system/lib/libm.so) = 0x400c4f40
I/luajit-launcher(16412): dlopen(/system/lib/libstdc++.so) = 0x400c4e1c
I/luajit-launcher(16412): dlopen(/system/lib/liblog.so) = 0x400c4bd4
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libmupdf.so) = 0x400c9bac
I/luajit-launcher(16412): mupdf library loaded cdata<void *>: 0x400c9bac
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libz.so.1) = 0x400c9cd0
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libpng16.so.16) = 0x400c9df4
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/liblept.so.3) = 0x400c9f18
I/luajit-launcher(16412): leptonica library loaded cdata<void *>: 0x400c9f18
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/liblept.so.3) = 0x400c9f18
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libtesseract.so.3) = 0x400ca03c
I/luajit-launcher(16412): tesseract library loaded cdata<void *>: 0x400ca03c
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libmupdf.so) = 0x400c9bac
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libtesseract.so.3) = 0x400ca03c
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libk2pdfopt.so.2) = 0x400ca160
I/luajit-launcher(16412): k2pdfopt library loaded cdata<void *>: 0x400ca160
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libcrengine.so) = 0x400ca284
I/luajit-launcher(16412): crengine library loaded cdata<void *>: 0x400ca284
I/luajit-launcher(16412): trying to open asset libs/libkoreader-pdf.lua: cdata<struct AAsset *>: NULL
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libk2pdfopt.so.2) = 0x400ca160
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libluajit.so) = 0x400ca3a8
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libkoreader-pdf.so) = 0x400ca4cc
I/luajit-launcher(16412): koreader-pdf loaded true
I/luajit-launcher(16412): trying to open asset libs/libkoreader-cre.lua: cdata<struct AAsset *>: NULL
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libcrengine.so) = 0x400ca284
I/luajit-launcher(16412): dlopen(/data/data/org.koreader.launcher/libs/libkoreader-cre.so) = 0x400ca5f0
I/luajit-launcher(16412): koreader-cre loaded true |
Another thing we need to do is packing all libraries into one zip file (or 7z) in asset and unpack the libraries into application data directory at run time. |
We're there! Well, a bit of work left, but it works nicely! We need to flesh out the things left and then we need to enter the stores - Google Play, probably, and maybe f-droid? Maybe we should ask for reviews on xda-developers, so we have initial feedback for a bunch of devices? That way we could avoid collecting bad feedback on Google Play with end users stumbling over this and that... Or maybe mobileread instead? There are quite a lot of people with Android devices there now and the discussion atmosphere is very friendly. Probably we need to start heavy debugging on our own first. And then maybe start nightly builds for Android. I'm very pleased regarding the low memory footprint. However, due to the animation durations, it feels a bit sluggish. We probably should make these shorter for Android devices. |
Oh - and we should probably allow color rendering... |
Yes. We almost get there. |
Mobileread seems like a good place for testing. XDA-developers seems like a good place for getting more developers. Google play would be nice for the next stable release. I feel we should get a bit more momentum before we enter the fray. All nice and dandy, but can't wait for the time to install it on my old HTC phone. :) |
Yeah, definitely release in hacker communities first before going to google play. But first of first, we need to write some development document! |
Close this now since the first android build is out. |
Support android execute
Given that all thirdparty libraries are available in Android, I think it's time to consider it. And I believe koreader is able to knock out a ton of readers in that platform.
The text was updated successfully, but these errors were encountered: