[not quite a guide] Run Cuberite natively on Android
#1
This is introduction. You can skip it if you like.
Quote:Some time ago I was having a thought about running Minecraft server on Android devices. Why? Because it's seems to be simple and available for anyone who has Android device. Not to mention that nowadays Android can be found on big range of devices, from small phones to powerful 8-core devices. You don't need to find and by it somethere, it's already in your pocket.
But there was a obvious problem: no official build for Android. There is a official PE edition and that's all. With help of MCP I've tried to rebuild official server for Android, but encountered some problems (I can't exactly say that it was, I forgot already. Maybe something related to restriction on number of methods in one DEX file, or something similar). Besides that, what about mods? It will not be trivial to install them. So I searched for alternative servers, but most of them had their source code closed or were abandoned long time ago. One of the promising was MCServer (and I even managed to compile it), but there was another problems. Maybe with stability, maybe this something else - can't remember, it was several years ago, two or free, maybe. At that time I dropped this idea. But several days ago, while cleaning my HDD from old files, I found folder "MCServer" and decided to try it again.

It seems that there is no official build of Cuberite available for Android devices yet. And I can't figure out how to build it. I never liked cmake and git, especially it's "module" feature. I already forgot how to deal with complex projects in Android NDK (And I hate that too). So I've chosen simple way: run already existing binaries. "But there isn't any binaries available for Android, didn't you mention that?" - can you ask. Yes, there isn't. But there is a everyday binary build for Raspberry Pi available. It's not Android? Who cares? This is powered by Linux kernel, and that is powered by Linux kernel. Both are ARM (ARMv7 with hard-float support, to be precise). And that's all that matters.
So, that do you need to run Cuberite natively on Android device?
  1. Of course, you will need Cuberite. You can get most recent build from buildbot here: Cuberite for Raspberry Pi
  2. Cuberite is compiled against some system libraries, and of course, you will need them too. You can get list of libraries by examining executable with ldd Unix tool. To put it simply, you will need libgcc, libc6 and libstdc++ packages from Raspbian repository. Be aware that library names in executable refers to symlinks; real names of .so files differs. Be sure to rename them correspondingly.
  3. I would like to say "that's all you need", but it's not that simple. To be precise, you need to somehow provide this libraries to executable. Now you have two choices: 4) modify your Android system or 5) modify executable
  4. If you decided to modify system, it's not that hard, and should be done only once. Later you will only need to download recent build of Cuberite and run it. Cuberite, as a normal Linux dynamic executable, expects to find libraries in /lib or /usr/lib directory of file system. (To be precise, it's not Cuberite but dynamic linker that will search for libraries. You can specify library location with LD_LIBRARY_PATH environment variable, but path to dynamic linker is hardcoded into executable, so it must reside at /lib.) Unfortunately, there is no such directories in Android, and even worse: using root access you can create /lib directory, but it will disappear after reboot, because all changes to / only affects it's temporary memory copy. At this point you again have two ways: modify your boot.img firmware image to create /lib directory there or use already modified boot.img with init.d support and write a script that will at every boot create /lib directory and put neccessary files there. I leave this up to you, it's not very hard, but can be somethat dangerous if you have no experience in Android modding.
  5. If you decided to modify Cuberite executable, you should be aware that you will need to do this every time you download new build. But it's not very complicated; in reality, it is only one shell command. The tool that you will need for that task is a Patchelf. If you using any modern Linux distro, it should be already in its repo. Unfortunately, official builds of Patchelf fails to work with ARM bianries, and I'm not sure is Debian/Ubuntu version fixed or not (at least Gentoo version isn't). You can download source for patched version from this Github repo and compile it by yourself. After you got it, just say patchelf --set-interpreter /path/to/where/you/placed/dynamic/linker to specify where linker that should be used to load executable is located. In my case, it will be /sdcard/Cuberite/Libraries/ld-linux-armhf.so.3, but yours may differ. And again, you have two options: hardcode path to other libraries to executable (see --set-rpath option of Patchelf) or specify it on a runtime with LD_LIBRARY_PATH. It's up to you.
To show that this conception is working, I've written shell script that will automatically download (about 10 Mb), extract and place all neccessary files in their locations. It will also use prebuilt ARM binary patchelf-arm to correct paths to linker and libraries in executable. You can just download attached archive, unpack it somewhere on you device memory card (I've used /sdcard/Cuberite path as you can see, but you can choose any; just don't put spaces, semicolons or other unusual symbols in directory names) and then run ./install.sh script from ADB prompt or your favorite terminal emulator for Android. You will not need root access for this, but busybox is supposed to be installed and symlinked as /system/xbin/ash. This script comes with number of prebuilt binaries; if you as paranoid as I am (=D), you can build them by yourself, it's just usual GNU Wget (taken from where), Busybox (built by myself following this instruction) and Patchelf (also built by myself, link is given above). Also you can run this script on your Linux machine with slight modifications; for that case there is a prebuilt version of Patchelf for x86_64 (but, again, you can build it by yourself), please see comments in script.
So, that's all you need to run Cuberite natively on Android device. So many words but it's really very simple =)
P.S.: I though that it will be boring to go through this WALL of text just to figure out that you don't want to try this, so there is some screenshots for fun!
            
P.P.S: It seems that I can't upload files larger than 1024k to forum, so I put archive here. It's only slightly larger than 1Mb, maybe 1.5Mb or so.
Reply
Thanks given by: LogicParrot
#2
This is amazing! Thank you very much for sharing.
Reply
Thanks given by:
#3
Didnt tigerw have an apk?
Combustible lemons and potato batteries, that's the future.Big Grin
Reply
Thanks given by:
#4
He did, and I had it on my phone until saturday. I don't know what happened to the project.

Anyway, @Barracuda72 Great work, and I hope we can get an official android app out soon.
Reply
Thanks given by:
#5
@bearbin, if I got Cuberite running just by providing required libraries to it, usual static build for ARM with high probability should run on most ARM-powered Android devices just fine. Only thing need to be done is some kind of Java-based launcher/updater within APK package.
Reply
Thanks given by:
#6
Thanks for your guide.

Schwertspize Wrote:Although I couldnt use it, I took a look at your script and used it in @bearbin s vps (like downloading packages, modifying binaries)
I am now working on a real app and on a script for the build server. IMHO the build server should take the Raspberry PI builds and modify them until they are usable in android (= lib path fixed,..) then the app only has to download that without the struggles of extracting deb archives on a phone (I got that) or so. We'd better use a Debian host which is capable of apt and manage our libraries through that.
 

I thought about it again. We actually have 3 parts. 1. A one time download of the Server directory (or, if something changes like the crafting, we have to think about it). A nearly onetime download of the libraries needed. Only if they are updated (and used on the build server) through repositories they get updated. A many-time download of only the cuberite binary initiated by the user


I will keep you informed

Checklist:
[99%] getting it to run via command line
[95%] getting it to run via an app
[10%] implement a Downloader into the app
[00%] write a script which patches binary and copies libraries. i found out that there is no need of patching the binary
[---%] extend the script so It uses apt. Not gonna do
[40%] provide a shiny app
[00%] setup build server & homepage
Reply
Thanks given by: tonibm19
#7
i promised to keep you posted. Basically i can run it now via an app, but i got the porblem that i get a Segfault instead of the app starting. i suppose it has something to do with the libraries, but the pathes are set up the right way. anyone (or @Barracuda72) has any idea? obviously there is no log, etc, but i got a core dump uncompressed fascinating 172KB. I hope someone can look into it.

Thanks in advance

ps: executable is in the archive, too

EDIT: hmmm i wanted to attach the file, but didnt work. however https://qraut.alkaid.uberspace.de/android-core.tar.gz 3MB
Reply
Thanks given by:
#8
sup. fixed that issue, it was somehow unrelated to cuberite.

running from console works fine as root, from app works not fine. i can run the command i assume is cuberite, i can kill it but i cant connect to it (on console i had to use root in order to bind to the port) and something worse, i cant get any output nor log.

everything is resolvable
Reply
Thanks given by:
#9
(02-20-2016, 05:45 PM)Schwertspize Wrote: IMHO the build server should take the Raspberry PI builds and modify them until they are usable in android.
If you have an access to build server, most easiest solution will be just to relink object files (*.o) compiled for RPi into static execitable. I believe just slight modification of CMake scripts is required; however, I'm not familiar with CMake and have no interest in learning it. Binary patching isn't good example of how things should be done; I just demonstrate that they _can_ be done, nothing more. Clean compilation is always preferred way.
BTW, script should be 100% working on Linux PC; I've developed it on host machine before trying to run on device. All you need to do is just set ON_DEVICE=0, change interpreter to /bin/bash (or busybox, if you prefer that), change "./busybox" to "busybox" at line 46 and make sure that busybox is available in your system. Of course, you can use Debian's APT and DPKG in script. I just have Gentoo on my machine and don't want to install Deb utils.
At last but not least: good luck in you work! And please keep us informed =)
Reply
Thanks given by:
#10
(02-22-2016, 02:04 AM)Schwertspize Wrote: on console i had to use root in order to bind to the port
Do you use port from range 0-1023? They are privileged and can be only opened with root permissions (or another tricks). Use ports 1024+, they can be listened from user applications freely.
Reply
Thanks given by:




Users browsing this thread: 2 Guest(s)