Android Bounty


I’ve decided on your second way and am using your pview as a template to get started on integrating Python correctly. I think I’ve got most of it done – basically what I’m aiming for now is an APK can be built of the Python interpreter, the relevant modules, and Panda all combined together.

The only problem is, your sample works, but when building it exactly as per your instructions earlier (the only difference is I’m using NDK r9c since I noticed there were references to “sources/cxx-stl/gnu-libstc++/4.8” which isn’t present in r8d), the APK is created fine, however when you run the application, it quits out with “Unfortunately, Panda Viewer has stopped.”. I haven’t added Python or anything at that point.

The error shown in the console is similar. I’m using OS Monitor to read the logcat information at the moment, and it shows: FATAL_EXCEPTION … dlopenfailed: cannot locate symbol “panda_android_app” referenced by “”… at [etc]

Do you happen to know what is wrong? Your downloadable APK sample works, but the instructions to build it don’t seem to work for me (I’m using the latest code from GitHub)…

I wonder if it’s a result of the visibility settings we nowadays use when compiling. Try either removing the -fvisibility=hidden flag to makepanda, or add EXPORT_CLASS to the panda_android_app declaration in config_android.h.

In the meantime I’ll see if I can get the NDK set up for me again so I can try building for Android as well.

OK, I pushed a bunch of fixes to master, which fixes a bunch of link issues as well as some runtime crashes in the OpenGL ES 1 renderer. I can now see the animating panda when running pview on my Android again. :slight_smile:

Thanks rdb for all your help, that all builds well on my system too and runs nicely on the tablets.

I’ll let you know how I get on with the Python integration :slight_smile: I’ve been reading up on how to do it, and will be working with the pview example you kindly provided along with other examples that should give me everything I need. I may be off it for a few days but hopefully will soon have something successful to report!

  • Greg

So, has Android port been on hold all these years because of no official Python support?

It’s been on hold because nobody’s been working on it, presumably because people have been paying more attention to the WebGL port, which runs on both Android and iOS (and would therefore be a viable way of deploying to Android).

For WebGL, I made a custom (patched) build of Python and then froze a Python application using pfreeze, and compiled that for the target platform. I imagine a similar approach would work for Android, which would make deployment easier in that the Python interpreter is embedded and Python files would not have to be read from disk; plus, we could reuse much of the tools that I used to build Python programs for the WebGL port.

I haven’t personally made this my primary focus because I feel improving other parts of the engine is more important. I’d rather focus on making Panda a strong engine on a few platforms than a mediocre engine on many platforms. :slight_smile: Still, I welcome and will aid any effort to further the state of Panda on Android.

Isn’t WebGL limited when it comes to certain rendering features as well as slower, even more so on mobile devices? I understand why you’d consider it, but for me these two reasons would make it a bad idea.
Plus, you’d limit yourself to newest IOS and Android versions as well, right?

Please disregard the request that was here. It was down to a circular reference in the Android version of Python 2.7.2, which is now fixed.

The Python DLL is now sucessfully loaded along with Panda’s libraries in the core Activity, however the Python interpreter now doesn’t want to run my test scripts, grr.

Huh, that is strange. It certainly seems that doing loadLibrary(“python2.7”) first is the way to go, and that it depending on itself (whatever that means) is something that needs to be addressed. Not sure how such a thing can even happen, though.

Sorry :slight_smile: we were literally writing at the same time!

It was a buggy build of 2.7.2 that was at fault. I found a later version which built and loaded okay.


I’ve tried several ways I can think of to get this to work, but unfortunately haven’t been successful yet. I feel like I am ‘close’ but every time I get that feeling it seems to jinx it!

I have an APK with two activities – one to install and test-launch Python from the filesystem, which works perfectly with all the Panda libraries, but can’t draw anything, and the Native Activity which you wrote, which launches Python correctly but crashes out upon trying to start the renderer. If Python doesn’t render anything then pview can work as normal with the walking Panda.

So I modified config_android.cxx to reflect the change of APK location and I’ve tried a system() call from a version of pview.cxx’s main() function to launch Python. This sets all the environment variables and launches Python in one line (so the vars don’t get removed). My Python scripts do work when they are run from pview – Panda libraries can be imported, files can be written, etc, but as soon as test = ShowBase() is called, the Python script just exits (even in a try…except to catch all exceptions) and the pview.cxx program continues on to where it draws the walking Panda. The Android debugger outputs (amoungst other things):

I/DEBUG   ( 2111):     #00  pc 00028d44  /data/app-lib/
I/DEBUG   ( 2111):     #01  pc 00265cfb  /data/app-lib/ (GraphicsWindow::set_properties_now(WindowProperties&)+110)
I/DEBUG   ( 2111):     #02  pc 00029ff9  /data/app-lib/
I/DEBUG   ( 2111):     #03  pc 00265c2b  /data/app-lib/ (GraphicsWindow::process_events()+82)
I/DEBUG   ( 2111):     #04  pc 00029fbb  /data/app-lib/
I/DEBUG   ( 2111):     #05  pc 002556eb  /data/app-lib/ (GraphicsEngine::process_events(ov_set<PointerTo<GraphicsOutput>, IndirectLess<GraphicsOutput>, pvector<PointerTo<GraphicsOutput> > > const&, Thread*)+26)
I/DEBUG   ( 2111):     #06  pc 00255cb7  /data/app-lib/ (GraphicsEngine::WindowRenderer::do_windows(GraphicsEngine*, Thread*)+26)
I/DEBUG   ( 2111):     #07  pc 0025fa9f  /data/app-lib/ (GraphicsEngine::open_windows()+70)
I/DEBUG   ( 2111):     #08  pc 0026037f  /data/app-lib/ (GraphicsEngine::make_output(GraphicsPipe*, std::string const&, int, FrameBufferProperties const&, WindowProperties const&, int, GraphicsStateGuardian*, GraphicsOutput*)+1026)
I/DEBUG   ( 2111):     #09  pc 0025aaa9  /data/data/
I/DEBUG   ( 2111):     #10  pc 0008dec8  /data/app-lib/ (PyCFunction_Call+296)

I’ve tried putting the system() call in different locations in the C++ program in the hope that Python will find the viewer created by C++ (knowing this was unlikely), or maybe it could find the NativeActivity if launched straight away in pview’s main(). It never does :frowning:

My Python script definitely is importing the Panda libraries correctly. These Python commands work when launched via pview. I tried using ctypes as suggested before to verify the DLLs are loaded, and it worked this time, from inside pview (it didn’t when I ran it from the shell).

	      from ctypes import CDLL

	      import panda3d.core
	      from panda3d.core import ConfigVariableString, loadPrcFileData, loadPrcFile
	      from direct.showbase.ShowBase import ShowBase

I’ve checked that plugin-path has been set correctly by writing it out to a file. It does point to all the Panda lib*.so libraries, and is in there. ExecutionEnvironment.getDtoolName() always returns ‘unknown’ though, which is confusing, even though it knows where to find the library and the CDLL parts worked.

The Python script always gets to test = ShowBase(), but then completely quits and then the pview C++ program continues.

If you run the Python side via adb shell exactly the same as in pview, you can see Python all works, although it’ll fail when you try to do ‘test = ShowBase()’ with the usual claim that there is no valid graphics library to draw with (like I mentioned a while ago), instead of just quitting. That’s okay because I didn’t expect it to find/launch the NativeActivity if I’m launching Python from a PC via the shell, but I thought it might find it if I launched it via Panda’s NativeActivity & pview.

Another way I tried – I followed the Python embedding manual – if I include Python.h in pview, and try to embed Python code, Py_Initialize(); works, but Py_Finalize(); or any other Python-related command causes the main() function to not run at all. Meaning I can’t seem to run a Python script that way either. I’m still not sure if calling Python this way will make the renderer work though!

As usual, if you have any ideas I’d be very grateful!

  • Greg

A bit of additional info that validates I have indeed loaded the renderer, if I launch Python from the shell it seems to find the renderer now, but then crashes with a segfault upon running any other Python code. I didn’t expect this to work but it would be kinda cool if you could control the renderer on the device from the PC shell!

I still have the problem just mentioned though!

Known pipe types:
(all display modules loaded.)
:ShowBase: Default graphics pipe is AndroidGraphicsPipe (OpenGL ES).
Segmentation fault

Following the stack trace, it seems like it might be happening in AndroidGraphicsWindow::set_properties_now in panda/src/android/androidGraphicsWindow.cxx. This in particular looks suspect:

ANativeActivity_setWindowFlags(_app->activity, add_flags, del_flags);

You might want to add a cerr line to print out the values of _app and _app->activity like this:

cerr << "DEBUG _app is " << _app << endl;
cerr << "DEBUG _app->activity is " << _app->activity << endl;

This will make sure that those pointers are initialized properly. In particular, since _app is initialized from panda_android_app, it seems like perhaps you are not initializing the panda_android_app properly in the android_main() function? This pointer is required in order to do any kind of interaction with the Android windowing system.

Note that this means that you cannot open a Panda window from a subprocess that is not forked from Android’s zygote. Android just isn’t designed to support that.

It certainly seems that embedding the interpreter is the way to go. Perhaps you can share the code you’re using for embedding so I can take a look at it?

It might be possible to try and run pfreeze to ‘freeze’ the Python sources, which will generate a .c file containing a main() function that preloads the bytecode for the Python modules and embeds the interpreter. This is the approach I’ve taken for the WebGL port, and it may be the easiest one to get started with (and also suitable for production use).

Thanks, you’ve been most helpful, rdb. That was enough of a hint to get things working.

I looked at your/my android_main function, and you were right of course. Additionally, my application was crashing because of a link that hadn’t been correctly set up (by me) in makepanda. It’s weird how Py_Initialize worked if left on its own without any other code, and yet Py_Finalize would cause the built library to silently fail without any info from logcat, but it doesn’t matter now, since it’s fixed. It’s always something simple, but as I’m still learning about how Panda works ‘under the bonnet’ I can miss the obvious sometimes. This is why I haven’t uploaded anything yet, because I keep changing things and experimenting, my code is very messy and will get an overhaul.

Anyway, my Python scripts now run on Android and I now appear to have all of the main libraries working. Just got to get packaging into APKs working, Bullet, ODE, OpenAL and the like.

What do you think?

EDIT: Just to say the artefacts don’t appear on the actual device, it’s just the way Android can’t screenshot the GL background.

Wow, thats pretty cool! Just wondering, how fast does it run?

Awesome! Great work!

If all this works out 2.0 is going to be an epic release, the biggest since I joined back in 1.5.3.

Hey Tobias, I’m a fan of your Render Pipeline!

All of the demos I tried above hit 60FPS (when I put the FPS counter back), besides Roaming Ralph which runs at about 38FPS average. That was on a “Who-Are-We” MediaPad M1 8.0 with everything as ARMv5. It would be a bit faster under ARMv7a, of course.

Update: OpenAL now working (sans Vorbis decoding at the mo).

Hello all :slight_smile:

I’ve just released a project called Cub3D, on the Play Store. It has Panda3D at the core.

There is a Python editor, Bullet and ODE Physics, working OpenAL audio, virtual joysticks, multi-touch, very fast sensor support, and many other features, all bundled into a nice Applet manager. You can write Panda3D, and/or Cub3D-specific code and see changes, in literally, an instant.

Currently it runs Python 2.7, and retains as much compatibility with the current release of Panda3D as possible. This means projects can co-exist on both Panda3D and Cub3D with minor changes or conditionals. The Python version on Cub3D may be upgraded when necessary, and we may add installation support for more third-party packages soon.

Please understand that whilst I know Panda3D is a free project, the Cub3D project has been worked on for a commercial company, and there was simply no way for us to do so without some sort of investment. We have made a huge effort to keep the core Panda3D features free, rather than simply charging for everything outright. As a result, many features we added are on in-app purchases. This version, also, cannot currently create APKs on the device (yet), but it can create other packages you can share.

All the regular Panda3D samples are included (along with the physics examples), and credits to authors are retained.

You can now play Ball in Maze (the Bullet version) using the accelerometer, at 60FPS. Roaming Ralph is playable too (without a keyboard)!

Have fun :slight_smile:

Nice work! You’ve gone above and beyond just porting Panda to Android, but you’re offering a complete development environment. That’s pretty cool. Congratulatons on the release!

Would you consider making the package installable on Android TV devices as well? This requires a few modifications to the AndroidManifest.xml, such as adding the LEANBACK_LAUNCHER category to your main intent filter, as well as declaring touchscreen as not being required. I ask because I do a fair amount of Panda dev on my Nvidia Shield.