Google I/O 2011: Bringing C and C++ Games to Android
Articles Blog

Google I/O 2011: Bringing C and C++ Games to Android

September 16, 2019


Galpin: Hello, and welcome to Bringing C and C++ Games
to Android. I’m Dan Galpin.
I’m a developer advocate on the Android team
working with game developers. So about this talk– um, we’re gonna expect that you guys
are C and C++ developers. If you don’t know C and C++,
you probably shouldn’t be here. Hopefully, you’ve gotten
some Android background, because we’re not gonna cover
all the basics here. This is considered
a higher-level talk. Um, game development–
the development experience is awesome. We are not gonna teach you how to become a game developer
here, either. And, however,
we are going to expect that you may or may not have
ever touched the NDK or, in that case, JNI. So our agenda for today is going
to be programming Android and C and C++, using the NDK,
bringing your game to Android, troubleshooting tips and tricks,
and tongue twisters and best practices. So to start off, um, Programming Android
in C and C++. Um, and I’m gonna be joined,
by the way, by Ian Ni-Lewis, who’s also
a developer advocate here on the Android team
doing game development– uh, helping game–
helping out game developers. So to start off with, the NDK provides support for C and C++ development. NDK is
the Native Development Kit, and the idea is
people write code in other languages than Java. [inhales sharply] I know.
It’s kind of shocking. And sometimes–
sometimes this code works, and they want to reuse it, so we–so we’ve made
the NDK partially because there’s tons and tons
of great code out there, whether it be open-source code, whether it be code
that you’ve developed, that you’re gonna want to reuse. Also, as it turns out, Java is not the best language
for everything. There are times when you’re doing things
that are really math-sensitive. There are times
in which you are doing things that are seriously hard-core where you’re gonna want
to accelerate things, and you’re gonna want to take
advantage of things like VFP. You’re gonna want to take
advantage of things like NEON, okay, for–for supercool stuff. And of course, I have heard
that there are other platforms that people write games for
other than Android. And–I know. It’s shocking.
[laughter] Galpin: Um, but you might want
to port those entire games over, and you want to–a method
of doing that that allows you
to get high performance and consistent quality. So let–let me let Ian
take it away from here, and he’s gonna talk about
what’s in the box. Ni-Lewis: I haven’t been
this embarrassed since I, uh, started teaching
class at DigiPen and thought that it started
a week after it actually did. I found out that all my students
wanted to kill me. Uh, I apologize for being late,
but yes, um, as Dan was saying,
the, uh, the NDK is a way to program C and C++
in Android. How many of you have used
the NDK? Okay, awesome. The rest of you, you know,
bless your lucky stars. Um…
Galpin: [laughs] Ni-Lewis: The NDK was actually
kind of difficult to use in the past. It’s gotten a lot better
this year, and we’re actually
pretty excited about the changes
that we’ve made. Here’s what the NDK is. It starts out with a toolchain, and if you’re familiar
with, uh, Linux programming or Mac programming,
this sort of toolchain is not gonna seem
at all out of place. It’s basically GCC
and–and Make and Build and all these nice things
that you’re used to. It also has a build system. Uh, you’re not
actually required to use this as a–as an NDKr5. And, at first glance, it seems
a little overengineered, but it’s based on
the same platform build system that we use for Android. And it makes it
really, really easy to write modular code and–and build up an application
of multiple shared libraries in C++. And I’m told that, if you try and do the whole
toolchain from scratch yourself, it’s considerably
more difficult. So you might want to at least
start with the made files that we’ve got for you. Um, and there’s also a set
of headers and libraries, so libraries that interface
with the underlying system. Now this is
a really important point. In fact, it’s actually the most
important piece of the NDK, and you might be asking
yourself, “Why?” In fact, if you’re like me,
you’re probably saying, “Well, wait a second,
I heard Android’s Linux, “and Linux has always been C++, so why do I even need
this stuff,” right? Well, it turns out that, although Android
is based on Linux, Android processes have a very important
difference, um, and that’s the–you know,
we’ve always had the Dalvik VM, and every Android process
loads the Dalvik VM. Application code is expected
to run in the VM, over the top of this set
of frameworks, um, that is the Android SDK,
in Java. Now what the NDK is trying to do is let you get some code
down here under–underneath that layer, uh, where only C and C++ code have–have been written before. And the problem with this is that, for a long time,
the Android operating system has been on, uh, able to rely
on this framework layer for backwards
and forward compatibility. So the problem with just
sticking some code down there, which you know,
you know, you can do– you’re not dumb, you can–you can
compile C code on Linux– but if you do it
without the NDK, you’re gonna have
a real problem here, because the set of system
libraries that we talk to, uh, that–that implement
the Android system in C and C++
have never been stabilized. There’s never been a reason
for them to be stable. We change them every time
we revise the operating system. We’re continually
making them better and switching things around based on the needs
of the underlying OS. So what we needed with the NDK
more than anything else, uh, was to create a stable ABI, and with that stable ABI, then we could finally get
the framework classes out of the way
and let your application code live in both Java land
or Dalvik land and C and C++ land. With first revision of the NDK, we–we launched
some basic libraries. Basically, the things that we thought were gonna
be most interesting to high-performance,
uh, programmers– you know, obviously,
the basic stuff like–like libcs,
math libraries, uh, and OpenGL. Now with Froyo,
we also introduced a library called libjnigraphics which let you talk directly
to the 2-D rendering layers, uh, in a bitmap layer,
as well as the 3-D OpenGL stuff, and with Gingerbread, we actually made
a concerted effort to make the NDK, and–and the Android system
in general, more attractive
to game programmers, so we introduced
some new input models. Um, we used libEGL, which is a–the standard way of getting OpenGL contacts. Um, we introduced OpenSL, so finally, you didn’t have
to go back to Java just to do sound. And we introduced a library
called libandroid, which allows you to access
some of the SDK framework from C++. Uh, most notably, it’s now
possible, in Gingerbread, to write, uh, an activity completely in C++, and it’s, uh,
it’s also possible, in Gingerbread to access the AssetManager
from C++, which, if you ever tried
to access the AssetManager from–from C in previous
versions of the NDK, it was incredibly difficult. So we’re excited
to see those changes. Well, now that we’ve talked
a little about what the NDK is, we should probably make it
really clear what it’s not. This is not the end of Dalvik. Dalvik is still a great way
to program Android, and it will always
be the–the premier way of programming Android. You always have, uh, SDKs
written in Dalvik first. But… it does give you a way
to–to write C– C and C++ code if you’ve got
an, uh, an investment in that. It’s not always gonna
be higher performance. Dalvik is a fast
virtual machine, and not everything is gonna
benefit from NEON instructions or from hand-tuned
assembly code. So it’s not always gonna be
the right choice for every game. Is it the right choice
for your game? That’s gonna depend
on a lot of things. Keep this in mind– Dalvik is the premier
development environment for Android. It’s a productive
development environment. It has garbage collection
and lots of nice libraries. But on the C and C++ side, uh, lots of programmers
know C and C++ that don’t know
a Dalvik language. Uh, it can be faster, and it can leverage
existing libraries like open-source libraries that
have been written in C and C++ and are available for free. So it may or may not be
the right choice for you. Fortunately,
you don’t have to make an all-or-nothing choice. And we’ll talk a little bit
about how Java and C and C++ can coexist. By the way, I do apologize
for my voice. I was way too enthusiastic
yesterday. Whoo! Google I/O! Um… Let’s talk about
how to use the NDK. All right, first off,
you’re gonna have to install it. This is a really simple step
unless you’re on Windows, in which case,
you’re kind of screwed. [laughs]
No, I–so on any system, you’re–you’re gonna
want to make sure you’ve got Java
and Ant up to date. I don’t know,
on my MacBook Pro, I had to do, like, a-a MacPort
to get for these things. Um, but on Windows, you’re almost certainly
gonna want to download Cygwin. Um, that’s not–
that’s not a restriction we put on regular
Android programming, but, you know, the build scripts
for the–for the NDK just have never been ported
for Bash. Um, it is actually possible to build without Cygwin. Um, I’ll mention
a couple of ways in a bit
on how to do that, but it’s highly recommended. So then there’s a sort of
a nice flow that we go through. You set up a project. Um, you write some makefiles. You’re gonna write
some interface classes and glue them up
with some JNI magic. Um, and then you’re gonna go into sort of your build,
deploy, and debug cycle that–that characterizes
any software project. Let’s drill down on these
a little bit. All right,
to create the project, there’s actually several ways
you can do this. The one on the slide
is the out-of-the-box way. You run
Android create project, and that gets you,
as I’m sure you’re aware, an Android project. There’s also a couple
of third-party projects that I want to mention
just because they’re so cool. There’s a product
called vs-android on Google code that, uh, will
create an Android project in MSBuild,
so a lot of game developers use Visual Studio. If you like that sort of thing,
um, that’s a possibility. There’s also a project
called Sequoyah that’s part
of the Eclipse project. If you load that
as an Eclipse extension, it will actually help you
create, uh, an NDK project using the confer
to C++ project wizard in, uh, in Eclipse. Can you tell I’m a V–
a Visual Studio guy, ’cause I just said “wizard”? Do they even call it that
in Eclipse? I don’t even know. Um, but it’s gonna create the–
either way, you’re gonna–you’re gonna get
a few different files created. There’s–there’s an XML file
that Ant uses. There’s a couple
of properties files that you usually don’t need
to care about. Um, and you are also actually
gonna have to create a couple of files yourself,
unless you use that Sequoyah, uh, project
that I talked about earlier. Um, it’s two makefiles. These are actually
fairly standard makefiles in–in the sense that they used
new make syntax, but they fit
into that fancy build system that I mentioned earlier. So they don’t require nearly as
much work as a normal makefile. The first makefile
is called Android.mk. It’s mandatory. The build system
expects to find this, and if it doesn’t,
it will complain. And it just contains the names of the files
that you’re compiling and any flag overrides
that you want to do, so, you know, you want
to set C flags for your project, fine, you can do it here. There’s also a somewhat optional
makefile called application.mk. Um, the idea is you might have
several modules in your application, you know,
several different libraries. Each one
gets its own Android.mk, and then the application.mk
pulls it all together. But the application makefile also does some–
some other important things. It’s a–it’s a place to set your
global debug flag settings, um, and more–more importantly
than anything else, it’s a place to set up your STL. And one of
the great new features that we’ve finally been able
to add in NDKr5 is real STL support, including exceptions, uh, that you get with just
this one line of code in your makefile. Now you need to write
an interface, because remember that, unless
you happen to be targeting the 4% of devices
that run Gingerbread right now, you’re probably gonna
want to start out in Java and then call in to C++. So you write a Java interface that’s gonna wrap your C++ in
something that looks like Java, and to do that,
you use the native keyword. This is actually really easy. You just decide which functions
are gonna be, uh, implemented in C++, and then you use
the native keyword to do–um,
to define those functions inside your Java file. After that, you just need
to generate stubs in your C and C++ code which you can do
with a variety of tools. Eclipse has a tool for this. There’s also a command line tool
in the JDK called javah, and it just generates a file
that looks a little like this. Remember that–oh, darn,
these little slides. Uh, remember we had
two public native void– or public data functions
in our sample code. If we passed the class
with these functions in them to javah, it’s gonna generate
code that looks like this. Basically, you have a couple
of JNI export functions and… the, um, the names of the functions
are a concatenation of the class path
and the class name and the function name,
all separated by underscores. And the parameters
to those functions are transformed
into JNI types that–that are in C– you know, jint, for instance. Uh, and then there’s a couple
of extra parameters. One’s a pointer
to a JNI environment, which is sort of the object that you use to talk
to the Java system from C++, and there’s also gonna be
a handle to your object. Or, if the function is static
in Java, there’s gonna be a handle
to your class. We’ll show you how to use that
in just a second. Now you might
be thinking to yourself, that looks really easy,
and it is. Just by giving the function
the proper name, the Java compiler
and the–and the Runtime know exactly how to find it
in your c–C and C++ code. And they find it
with a name lookup in–on a vtable that’s sort of
automatically generated for you. But… there are times that you might
want to do this manually. For instance, let’s say
that you’ve got some functions that you know you want
to implement in C, but you don’t know exactly what the implementation is
until Runtime. A good example of this would be if you’ve got some
really heavy-duty math library, and you’ve got an implementation
that uses NEON and then another implementation
that doesn’t. Well, not all CPUs have NEON, so you might want to delay
the binding of that function until you know what your
instruction set is going to be. If you wanted to do
something like that, it’s also actually fairly easy. You just make your own
function table. Um, it’s just an array
of structures that has the name
of the function. It has this cryptic
little string. That’s just telling you
what the function signature is. In this case, uh, two integers,
uh, or the function takes two integers
and returns void. If you don’t want to memorize this particular bit
of gobbledygook, you can use a, uh, tool
called javap to generate that,
or, once again, Eclipse has a menu item
that does this for you. Um… and then finally, the last thing
in that structure is just the point
of the function. Once you’ve created that table, when you’re ready to register
up your–your interface, you just call a function
called register natives, and you pass in a pointer
of that table that you created. And that way,
you could actually have multiple
different implementations of the same functions
inside the same library being hooked up at Runtime
to your Java code. Of course, it’s cool that you
can call C++ code from Java. It’s also kind of nice
to be able to go the other way. That’s not super–I’m not gonna
tell you that’s easy, because it’s not one line
of code, but it is
pretty straightforward. And this is where we use that
class or, uh, object handle that we talked about earlier. Um…
using object handle, you can get a handle
to its class. Using class handle, you can get a handle
to a method, and once you’ve got a handle
to a method, you can use a function
on that JNI environment, uh, one of the call method family of functions that differ by return type. And–and that allows you
to actually make a call from C and C++
back into Java. Excuse me. Mm. So that’s all the coding. Now we get to build,
and that’s pretty normal. If you’ve done any Java
or–excuse me– any, uh, Android
programming before, you probably know
the second two steps. It’s the first step
that’s a little different. You run ndk-build,
which is a shell script that just launches
all those makefiles, stitches everything together, copies everything
to the right directories, and makes sure that all of the C and C++ code
that you’ve compiled is where the packager
expects to find it. Then run Ant to package it,
run Ant deploy or– I’m sorry–Ant install
to deploy it, and we’re ready to debug. Now this is actually
the most important, cool thing that we’ve done in the past year
with Androids. We actually made it possible
to run a real instance of GDB and do multi-threaded debugging on Android devices. The NDK GDB script
is a shell script that does a whole lot
of heavy lifting. It starts by sanity checking
your setup and making sure that you can actually debug
the code that you think you can, um, and then it’s gonna
start your application in an instance of GDB server. The GDB server
is this tiny little thing that just communicates with a real GDB across,
in this case, a named pipe. Why is it a named pipe
instead of a socket? So we don’t have to ask for
internet privileges to debug. So GDB connects to this,
uh, named pipe on your host. It thinks there’s a socket
on the host, because it’s been, um, aliased. And once GDB is running,
you can attach to that with any tool
that supports GDB– I know of at least three. Eclipse supports GDB. Um, Visual Studio supports GDB if you buy an add-on
called WinGDB. Xcode, which I’ve never used,
but I hear it’s cool, also, uh, it supports GDB. So you can use these IDEs or you can use
the, uh, command line interface to GDB, as well. Now I’m just about to turn it
back over to Dan, and we’re gonna talk
about some tips and tricks, and it’s really actually
the most interesting part of the talk,
but before we do, I want to leave you
with one tip of my own, just from experience debugging. Make sure that, when you
start debugging the NDK, you have a Gingerbread device. No matter
what you’re targeting, the debug support
pre-Gingerbread was not phenomenal. Gingerbread changes all that,
and it allows you to actually debug
multithreaded applications and have a hope
of actually figuring out what’s wrong with your code. So remember to do that, and then I’m gonna turn this
over to Dan for some ideas on how you can
bring your games to Android. Galpin: Thanks, Ian.
[applause] Galpin: Um, so this part
of the talk is subtitled
“Saving Ian’s Voice.” And, uh, but, uh,
it’s really good– it’s really great
to have him here to talk about, uh, a lot of the stuff
that’s going on in–in the NDK. So this part of the talk,
we’re gonna be talking about actually bringing your game
to Android and what that actually involves. So let’s first talk
about what devices have been accessing
Android market. This is basically
the freshest data. It’s a 2-week period.
We published it just this week. And as you can see,
it’s really exciting. We’ve had great uptake
for Android 2.2. 65.9% of devices
checking into market are now running Froyo, and 94.7% are running Android 2.1
or higher. So this is fantastic, because it means
that you can take advantage of many of the latest features
of Android without having to eliminate
much of the market at all. But NativeActivity
is just starting. Right now, we’re at 4.3%, so for
non-tablet-specific titles, things that are not going
to require Honeycomb, we want to be able to take
advantage of NativeActivity when it’s useful,
and I’ll give you an example. Um, how many people here have
heard about the Xperia PLAY? Okay. Cool device. Um, it has a touch pad on it,
and that touch pad is only accessible right now
through NativeActivity. So a lot of people
are in a position where they want to write
an application that’s compatible that can take advantage
of those touch pads, but they still want to hit
the rest of the market. So let’s talk about
how to do that. So we can do something called
platform-specific resources, and we can define
boolean values there. And this is how that works. We create resources
in a values– in a values-v9 directory. Inside of there,
we create two values, one called, in this case,
“atleastGingerbread” and the other called
“notGingerbread.” From there, we can just go into
the manifest. Now we enable one activity, if atleastGingerbread is true, and one activity
if notGingerbread is true. Voil�,
We have an application that now can run NativeActivity
on Gingerbread and will run whatever standard
activity on everything else. Now there are some things you’ll
want to do in your native code to take advantage of this. Oh, let me actually show you– there’s what
I was gonna show you there. Um, there’s some things
you’re gonna want to do to take advantage of this. One is you’re gonna want
to create stub interfaces to your game engine. Obviously, you do not want
to HardCode the dependencies to NativeActivity
in your game engine and include
the whole thing twice. It’s gonna make the download
a lot larger. It also means maintenance
can potentially be larger. So what we’re going to do is we’re going to create
some stub libraries. We’ll talk about that
really fancy build system we had before. This is what the Android.make
looks like now. As you see,
it just contains a pointer to three other libraries
we want to build. There’s
the application.makefile. It actually lists
each one of those libraries. Inside of
the individual directories, We also contain
and have other makefiles. In the Android.make,
we have this one, and in the Native Android.make,
we have this one. This one, of course, only refers
to libraries that are in Froyo, and this one refers to libraries
that are actually available in Gingerbread and beyond. And what’s important is both of them use
the same local shared library, and that’s where
the primary amount of our code will actually sit. So we do have one problem, and that is Android
does not support dynamically loaded libraries
that are automatically linked. We don’t do dependency checking. So we have to have a way
of loading that other library before NativeActivity kicks off. The good news is that we actually provide
a method for doing that. We can extend NativeActivity. So all we’re doing in our–
in NativeActivity is creating a static member that loads
our primary dynamic library. Now in our standard
JNI-based version, we simply load them in order. And that’s it. With this, you can actually have
two–two different activities that share
the same native code path but target different devices. Now let’s talk about
what you need to do in order to write a game. Well, you need to deal
with the Android Lifecycle. You’re gonna deal with–
you’re gonna have to have– deal with Input, Graphics,
Sound, and, of course, Assets. And the reason I want to bring
up the activity lifecycle is it is so important. The framework does a lot to help
you with the activity lifecycle, and I’m sure many of you have
seen a diagram like this. Someone comes in front
of your activity. It’s visible. It get shut down.
It comes to the foreground. It gets restarted. You know,
all this stuff happens, and there’s always one line
that has been missing from this diagram,
and that’s this one. Okay, and that happens
when something in your process actually changes
the configuration. So you’re at–so look
at all the different ways your application
can go through this chart. But here’s what’s interesting– There’s only one in which your
process actually gets killed. Most of the time, your native process
is never going to get killed. Your library is not going
to get reloaded, and this means that you actually
have to be a little bit smart, because Android tries to keep
your process around for as long as possible, so even
if you finish your activity, your native process
is going to continue running. It’s gonna continue
to get a bunch of CPU cycles. What does this mean? It means if you actually
continue that running, it’s gonna be bad. Now visible activities
are given high priority, so it’s not the end
of the world, but it is something
that is very important to note. So what does this mean? Be careful
with static initializers. Your library
will not be unloaded as long as your process
is active. So this means that
when your activity restarts, you need to be able to manually
reinitialize anything that you might be relying
on static initializers to do. So in general, don’t use them. Uh, also,
be careful with threads, because threads are tied
to your process. They’ll continue to run even
if your activity has ended. And what that means is that
people will be using the device, and they’ll find that
it’s slow and terrible, and they’ll look
in the battery life meter, and they’ll realize that
your application is the one that’s sucking up
all the battery life and then they’ll go
on Android Market and they’ll give you a one-star
review and say that you suck. I mean, they might
do that anyways, but at least let’s not give them
a reason to do it. Um, other things to note is that Gameplay should stop
during onPause, but your application
might still be visible, and I’ll tell you, the most
standard way that can happen is if you’re using
In-app Billing, you’ll bring up–it’ll–it’ll
actually bring up an intent that’ll cause an activity
to show up not full screen. Well, your application
is technically paused, but still visible, so it might make sense to do
some more stuff in onStop than you were doing in onPause. Still save all your state, but maybe you don’t want
to trash all of your GL variables
in onPause in that case. Finally, in onDestroy, you want to make sure all
your native code is cleaned up. And a lot of people
are like, “Well, onDestroy never gets
called, right?” I mean–but it does. There are definite ways
in which it can get called, especially if you’re not
handling orientation changes or changes in–in, uh,
in devices, like, when a keyboard is
attached or something like that, and it tries to restart
your activity. So you’ve got two choices–
you can either handle all those–all those
configuration changes, or you can be really,
really vigilant about this– one of the two. So let’s talk a bit–
just go quickly about all the things
you’ve got to handle. You’ve got to handle input,
okay? Key handling is important. A lot of devices
have capacitive buttons, and what this means is that
we actually madea change in Android 2 that said, instead
of just relying on onKeyDown, we actually went,
and you have to get a cycle of onKeyDown and onKeyUp. This prevents you from accidentally swiping
into a button and clicking it when you don’t
mean to a lot of the time. It doesn’t mean that it doesn’t
happen, but it helps. Another thing to do is,
if you’re gonna do things like handle key repeats,
use the actual functions that are built
into the framework so you–so you get the same
key repeat counts and the same behavior
you would expect from an Android application. Touch and Multitouch handling
is similar. We have things
like GestureDetector. Use those so that
your application behaves like a non-native application
whenever possible, when it makes sense. And then finally
and probably most importantly– dealing with Multitouch. Now most devices
now support Multitouch, and most devices can actually
track distinct points, but you can query to find out
whether or not that’s true by checking this variable– “FEATURE_TOUCHSCREEN_
MULTITOUCH_ DISTINCT.” You can also use it as a filter
in Android Market. If you want to make sure
your device supports true
2-finger multitouch, you can. We also add a feature in
Gingerbread called Jazz Hands, which allows you to see if you application supports
5-finger multitouch. So these are all–all things
that you can do to help configure your why
to make sense for your user. Now even if you don’t support
distinct multitouch, you can do things,
like have virtual D-pads. You just want to put them in
opposite corners of the screen so that they
will never intersect. It is cool to handle things
like trackballs. For the devices that have them,
I love it when it’s an option. And, of course, um, everyone’s
gonna want to use things like sensors, you know. When people are gonna want
to take advantage of the Xceleron or the Gyro.
You just want to make sure that it’s disabled
when you’re not using it. You’re also gonna want to make
sure to “Androidify” your game, and what I mean is don’t break
the hard buttons. So, you know,
“Back” should do something. There’s nothing worse than when
you’re on the title screen of a game, you hit the “Back”
button and nothing happens, and just, you know,
the Pease Electric goes off to let you know that
you’re hitting the button, but the game is not responding
or doing something. Make sure it does something. Uh, you know, Menu could–
should probably do something, and if someone accidentally
swipes the Home key, there’s nothing worse
than when the game goes away. So the result–and volume
buttons are very similar. We don’t want to eat
those messages. You–you actually have to return
them to the framework, and you want to set
the volume control stream. And then again, don’t let the hard buttons
bake–break your game. You want to save your state.
It’s very, very important. You know, these buttons
do things that are relevant. OpenGL–Let’s talk
very, very quickly about this. The coolest thing about OpenGL
and Android is that you can actually create
your surface inside of Dalvik and take advantage of it
directly from within the NDK, and that’s awesome,
because, actually, it’s a lot of work to create OpenGL stuff– OpenGL context compatibly
across Android. And GLSurfaceView–if you ever
look at the source code, and, of course,
what’s awesome is that you can, um, actually contains
a whole bunch of stuff that you don’t want
to have to rewrite that works around
a lot of issues that can possibly happen
in the GL driver. So I definitely recommend
using it. Now it’s not the most efficient
way to multitask, because it’s going
to automatically release your context during onPause if you call its onPause state
during the onPause. That’s when it does the work
for you. You might want to call it
during onStop if you know you’re gonna
be using a In-app Billing– one thing to think about. But also with, um, Honeycomb, you can actually say, “I want it to preserve
my state,” and it will. So we added that as a feature
in Android 3.0. And when your context is lost, you’re gonna have to do
a lot of work. You’re gonna have to reload
your resources– things like textures,
buffer optics, and shaders, and your names
don’t even persist. So these are all things
that are important to remember when you’re using OpenGL. The marketing way
of describing this is that Android encourages
innovation in hardware. [laughter]
Galpin: [laughs] What this means is that you have
a problem as a developer. You’ve got to deal
with potentially different kinds of proprietary texture
compression formats, and if you want
the best quality, you will, because your–
your other solutions are not all that great. You can use
uncompressed textures, but what that means is that you are going
to get a lower frame rate, because you’re gonna be using
more memory bandwidth. You can use ETC1, but ETC1 doesn’t compress
all data very well. It’s mostly good for data that does not have
sharp color transitions and it does not support Alpha. You can use Multi-APK, which, as we announced earlier,
will be available soon, or you can put textures
on an asset server, detect support at Runtime, and downtoad–
download to each device. In the previous session
before this one, we talked about how to secure–
securely deliver assets from an asset server in order to
avoid people leeching bandwidth. So if you want
to know about that, there’s some information
on that. So some–some small tips
about drawing for performance. Draw order is important,
especially if you’re not on a– on a tile-based renderer, or a-a specific type of tile-based renderer
in this case. So definitely draw
front to back. It really helps. VBOs are critical
for performance. You want to avoid
unnecessary state changes. And finally, you need to use
power of 2 sized textures, because if you don’t, it can either be very slow, or it’s just going to take
an enormous amount of memory, because it’s just going
to scale your texture up to the next power
of 2 sized textures automatically inside the driver. Or it’s just not gonna work. Um, and then, of course,
writing compatible shaders, and this–this slide is actually
contributed by my friend Kim over at Sony Ericsson, because
he–they’ve done a lot of work on this, but, uh,
it’s very, very important to query for the number
of attributes, and the varying, and the uniforms
that are supported when you’re writing
your shaders. And just because they’re there doesn’t mean they’re actually
going to perform well, but if it’s not there and you try to write a shader
that does that, it’s going to crash your
application, and that’s not fun. Uh, and of course, you want
to avoid things like conditions and discard as much as possible, ’cause it’s really going to slow
down the performance of your shaders. Mobile shaders are just in the
beginning on their lifecycle, and they are going to do
very, very cool things, but right now, we have to be
a little cautious when we write them. Quickly into sound– Android includes a bunch
of options for sound. It can be a little confusing, so let’s go through them
super quickly. We have MediaPlayer, which is really
a full-track media solution. We have SoundPool, which allows
you to play sounds from memory, and it’s actually the only way to play compressed audio
from memory. That is not yet supported
in native OpenSL. We also have,
of course, AudioTrack, which is something we introduced
in–in… Android 1.5…
[inhales sharply] I think, and, uh, it, uh, allows you to play PCM audio only
with minimal latency, and it’s really meant
for applications that are generating
their own audio. And finally,
we have OpenSL, yes, which does require
Android 2.3 or higher, but it combines the capabilities
of MediaPlayer and AudioTrack, and it allows you to do all
of your audio from native code. And it–and the interface
is actually a little nicer in terms of generating audio, because it actually calls you
back when it needs a buffer. So it’s a very,
very straightforward interface to use. And I’m sure, going forward,
it’s gonna become even more and more powerful
and important. So let’s talk quickly
about assets. One of the things that people
want to be able to do is pull resources and assets
out of their APK file. And I went to the Android team,
and I said, “All right, “there are many ways
we can do this. “What is the way that is most likely to still
be compatible in the future?” And they suggested
this method. So what we’re going to do
is get our APK file name, uh, using this SourceDir. Then we’re going to use
the AssetManager code. And that AssetManager code
allows us to get something called an AssetFileDescriptor. All an AssetFileDescriptor is is a standard
native file descriptor that includes extra parameters
for offsetting length. We can read them, open
the APK file from that offset, and there we are. We’re reading our–our resources
right out of native code without any additional overhead, which–and the overhead
we’re trying to avoid, of course,
is having to buffer things between Dalvik and native code. You can, of course,
use a native Zip Utility in a very similar way. It’s a little–it’s a little
less future-proof, but it’s probably going to work
as well. Um, and it’s probably
gonna be faster, as long as you do things
like cache the Zip directory. And then finally, of course,
you can use native AssetManager on Gingerbread and beyond. All right,
my tongue twister slide– “Troubleshooting, Tips,
and Tricks: Targeting tricky, trying tasks.” So Threading, Dalvik,
and the NDK– all context are per-thread. You’ve got to be careful
to check your threading. If you take that same context and reuse it
across multiple threads, bad things will happen,
because the JNI context tries to do smart stuff
for you, like clean up objects
that you’re not using anymore. So you want to use one
JNI context per thread, or you want to take advantage
of a game loop that actually takes
your messages, threads them
into another thread. It’s also useful
if you’re calling the framework, ’cause many of the framework
classes don’t like to be called from anything other
than the UI thread. As far as performance, you can
check for older hardware, and there’s multiple ways
of doing that– checking for ARM7, checking
for support for OpenGL 2. And then you can use Fallbacks. You can use things
like 16-bit textures. Um, you can actually
convert them on the fly using BitmapFactory. You can also use
a smaller render target using
SurfaceHolder.setFixedSize. Of course, there are other ways
of doing that within OpenGL, but this actually does it
at the optimal place, which is at the compositor. Pixels are very, very expensive, especially on tablets,
so this really will help, but if all else fails,
we do have market filters, such as Device Availability,
which was announced today, platform release, GL version,
and instruction set. And you can–you can filter
on instruction set by only building a library for ARM5 or ARM7. And here are just general tips. Start small. Don’t make me
download a big file. Use the backup/restore service, can support
multiple control schemes, install to SD–
I’m not gonna go through these, but you should all consider
these, things like profiling. You know, make the game
render up and do better stuff, if I–if it detects that
it’s running on a cool system. Hooking into social networks
is, of course, really important for viral spreading
of your application. Building a live wallpaper
is so cool and so few applications do it. But, like, like,
isn’t that awesome? You get to own
the user’s home screen. I mean, what other platform
allows you to do that? That’s so awesome. Um, analytics–definitely find
out where your customers are. Find out how
they’re using your title. Like, this is awesome,
awesome information. Find out where–use–use it
to do things like finding out even where someone is dying
in the middle of your game. Like, you’re like, “Hey, “that level’s way harder
than I thought it should be. What’s going on?” Or, “Only on this device people
are having problems.” All that kind of stuff
you can find out. And, of course, In-app payments,
we went through that in the last presentation
I just did. We are now seeing amazing
traction in app payments. If you look, we just added a new category in Market
for top-grossing applications and three out of the top five are top-grossing
only through In-app payments. So some tools–I’m gonna throw
these up here very quickly so that when this slide–
when this is played back and put on–on, uh, on the web,
you’ll be able to get these, but this is some of the stuff
we’ve talked about, and, of course, we have
some performance tools. Each one of the chips
at manufacturers has now come out
with performance tools, and they can be very useful. Some of them require
a routed device. Now we’ve got a very short
period of time for Q&A. So, uh, I went through those
a little fast at the end, so if you have a question, this
is the time to stop me on it. And, uh, thank you very much. [applause] Galpin:
And I recommend everyone stay around in the room
after this, because, um, there’s gonna
be something special for all of you, so…
[chuckles] Free cake?
That sounds good to me. All right, next. man: Hi, uh, I work on
the open source port of Freeciv, if I can just give
a quick shout-out. Galpin: Awesome.
man: So it’s–it’s open source. It’s, I think, one
of the largest NDK applications you can–you can freely
get the source to. Um, there’s a lot
of terrible ideas in there, but hopefully, there’s one
or two, uh, good ones. Galpin: Cool.
man: Uh, I had a quick question. It was something I’d seen
when–when loading a resource. One–one of the goals
of that project was to be able to drop my app, even let it
be killed and have it, like, spring back as quickly as
possible to where you left off. Galpin: Right.
man: And so I spent a lot of time optimizing
how I loaded my art assets. Galpin: Mm-hmm. man: I found something
really counterintuitive. It seems JPEGs load about
three times faster than PNGs. Is that, um… sensible?
Galpin: Is that– Is that based on the file size?
‘Cause– man: Uh, it–what I found
was when benchmarking this on a Samsung tab…
Galpin: Mm-hmm. man: was only about
1 millisecond per–per file was taken up in file I/O.
Galpin: Mm-hmm. Mm-hmm. man: And that was effectively
the same whether PNG or JPEG. Definitely the PNGs were larger.
Galpin: Hmm. man: The JPEGs were smaller. It was the actual–apparently,
it was the actual time spent, like, converting
from the compressed stream into a bitmap. Galpin: Hmm. Interesting.
I-I haven’t experienced that. But, you know, I-I– Ni-Lewis: PNGs aren’t on
the no-compress list, are they? Galpin: No. Yeah, they’re–
they’re both–they’re both on the no-compress list, yeah.
Ni-Lewis: Okay, I thought so. Galpin: So that’s–
the only thing that would cause that normally
is that–is that, you know, in the zip file, uh, you know,
things,resources can be compressed,
but both of those files are automatically
not compressed. I’m–I’m obviously pretty
surprised you’re seeing that. But I-I–you know, I don’t
actually know the answer. That’s a cool thing to note.
man: Yeah, and– Shift–even shifting
that around, it didn’t, like, if–if I was on the SD card,
the only thing is if it was on the SD card,
it would seem to take about twice as long
as if it was on flash memory. Galpin: Yeah, see, that–that
would–that would really make me think that it actually
was, on some level, file I/O. man: Yeah.
Galpin: It might be even, uh, just–just because,
uh, uh, that would be my first– my first guess is it’s entirely
I/O bound, but, um– man: Right. But, uh, three
times, and I mean, you know, these weren’t very large files.
Galpin: Yeah. man: I mean, it was–it–
I don’t know. And it could also be–I know
that it’s the OMAP platform and they have
optimized JPEG decoder, so maybe out floating
some of that to a DSP. Galpin: I don’t think so,
but that’s, uh, that’s it. I think–I think it’s–
Ni-Lewis: And it could be, you know, loading it through
and optimizing code paths. There are two different
code paths for it, but I-I– Galpin: It could be loading it
through–yeah. man: Oh. Yeah, I did actually
try compiling the libJPEG and using, like, instead
of loading it from, um, Java, pushing it into a texture,
and then pulling it up through there.
Galpin: Yeah. man: I-I tried
the libJPEG thing and–and it even seemed
like using just a bog standard compiled libJPEG
performed better than PNG, but performed worse than–than
pulling it up through Java. Galpin: Oh, interesting. Cool.
man: All right, well, thank you. Galpin: No, that’s interesting.
That’s good to know. Ni-Lewis: It’s a mystery.
Galpin: It is. man: Um, so question– Uh, I have downloaded NDK
using the JNI, but I find out that debugging
is extremely difficult. So I saw that we can do
the complete, uh, Android application
in C and C++ only, without using Java. Uh, so that makes the debugging
much easier. Can you show me, uh,
some way in the future we can support only C and C++
for entry application? Ni-Lewis: Ging–
with Gingerbread, you can support that, but let me sort of lay things
on the line for you. The, um, the debugger
for C and C++ is, uh, honestly,
a little flaky. Um, every single version
gets so much better, it’s just amazing.
man: Mm-hmm. Ni-Lewis: Um, but it
also depends a lot on what you’re using with it. Um, so for instance, were–
were you using, like, stock GDB, or were you using Eclipse or… man: Uh, many use,
uh, Eclipse, yes. Ni-Lewis: Okay, so right now, um, if you–if you use Eclipse, and you either–there’s–
there’s instructions on the internet for how to get
it to work with–with any GDB, or you can also, um, use
NVIDIA’s plug-in for Eclipse. It sets up the debugger for you. The–the–the only disadvantage
to that is your device has to be rooted,
uh, right now. Um, hopefully, they’ll fix that. Um, then actually, it’s–
it’s fairly easy to debug. You can bounce back and forth
between Java and, uh, JNI, right–oh, and your–
and your C++. Galpin: Yeah, there’s–there’s
no–well, I was gonna say the main answer is that
there’s really no reason why–why you can’t debug
native code that’s being called
from–from JNI. It actually works–it works,
as far as I can tell, just as well as–
as fully native code. Ni-Lewis: Yeah,
and–and the bad news is going to full-on C++
would not help anything, because it’s not the–it’s not
bouncing back and forth between Java and C
that’s the problem. It’s just the debug layer,
and C is–is a little flaky with Eclipse. man: Okay, thank you.
Galpin: Mm-hmm? man: Uh, I have a question
regarding Google TV in the NDK.
Galpin: Mm-hmm. man: And that, uh, after talking
to the Google TV guys, the NDK is not supported for,
uh, Google TV. Galpin: Mm-hmm.
man: Is that ever going to change and…
Galpin: I think that’s kind of– I think that’s kind of up
to the Google TV team. Um, as–
as a C and C++ developer, I would love it to change,
but, uh, but that’s– that’s–that’s up to them. Ni-Lewis: Yeah, actually,
you’re not the first person to answer–to ask this question. Um, and I’ve worked closely
with the–the Google TV team. They–basically, they’re not
making any announcements. Um, they haven’t ruled it out
one way or the other. Um, but they–they have said
on many occasions that they understand that it’s a-a desire
that a lot of people have. man: Yeah,
especially with regard to, uh, some sort of, like, Xbox live arcade style gameplay. Galpin: Absolutely. No, it’s
totally–I’m there with you. Ni-Lewis: We–we think
that would be cool, too. man: So–so with each version, indicates you guys
are really progressing… [speaking indistinctly] so good direction. But the question is about
accessing the MediaPlayer, the video player back, actually,
from native code, so… Galpin: Yeah, so–so right now, there’s–there’s no way
to do it, uh, directly. Um, I’d love to see that change, but, uh, that’s still the way
things are, so you still have to go back and bounce back into,
uh, into Dalvik to do that. man: But that’s on
your road map, right? Galpin: [laughs]
man: [laughs] Galpin: I would really like it
to happen. man: [chuckles] man: Uh, first of all,
let me say thank you for multithreaded GDB
and Gingerbread. Uh, other–before,
it was just a pain having to call things
on the main thread. Galpin: Yeah.
man: Um, I actually, um– Galpin: Thank David–
thank David Turner and the–and the–and the Dalvik and the–and the Android,
uh, Kernel team, actually. They made that happen.
They’re both awesome. man: I actually don’t
work on games, but I imported an extremely large
engineering app from C++, um, and we needed, um, we were
using the CrystaX before, because we needed wide string.
Galpin: Yeah. man: And we needed,
like, a full SDL, but for Gingerbread,
we’ve actually switched now to using new–the SDL,
but the problem is, the, um, the one that’s part
of the NDK5 doesn’t export any of
the actually wstring functions. Um, if you–it builds,
but it doesn’t link to wstring. Uh, and I tried
really, really hard, and I looked around,
and eventually, what I had to do was I had to download
the NDK source code and change the build scripts
to get wstring to export, and it’s like
a meg and a half bigger, and it’s fine, um, but actually,
my question is this… Galpin: Yeah.
man: Um, so I changed that. Do I have maybe–I may need
to ask a lawyer this, but do I have, like,
an affirmative GPL obligation? ‘Cause I only changed
the build scripts. I didn’t change GCC, but I’m
using my own version, I guess, now of the NDK, not the source–
not the one that was… Galpin: Well, all of, I mean,
I’m–I’m not an attorney. man: Yeah.
Galpin: But my understanding is all of Android is licensed
under a, uh, license that doesn’t force you
to contribute your changes to all of–all of–
man: Well, ’cause I didn’t know if GCC–yeah.
Galpin: Yeah, if you’re using a GCC stuff, you know,
it’s interesting. I don’t actually know
what the answer is–on that. But I’m surprised the wide
string stuff isn’t working. You should file that as a bug,
because I just spoke to it. man: Okay.
Galpin: So that was one– that was one
of the desired changes. Ni-Lewis: That–yeah, well, we–
I talked to David about that. Galpin: Yeah.
Ni-Lewis: Yeah, I think– now he said that he actually
couldn’t get the command line, that there were like two
mutually exclusive options where wide string didn’t work.
Galpin: Yeah. man: Uh-huh, there are,
and I actually had to HardCode one of them.
They’re like boolean opposites. Galpin: Yeah.
Ni-Lewis: Okay. man: And I went into one
of the makefiles, and I figured, yeah, and I basically
had to manually override it. Galpin: Right.
Ni-Lewis: And this is really good–
this is one of the things that you should speak up, uh, on
the forums or e-mail us about. man: Okay.
Galpin: Yeah. Ni-Lewis: Because–because
as you can see– so really difficult build,
uh, solution that ends up making your code
a mega and a half bigger. Galpin: Yeah.
man: Mm-hmm. Ni-Lewis: And maybe isn’t all
that desirable by most people. man: Yeah.
Ni-Lewis: You know, you can probably see why that choice
was made. man: Yeah, absolutely.
Ni-Lewis: But if we’ve got more feedback about that,
more data points, you know, that might be something we want
to do–support in the future. Galpin: Yeah, absolutely.
man: Thanks. man: Okay, quick one.
Galpin: Mm-hmm. man: Uh, any plans to access
the camera API through the– through native code?
Galpin: [sighs] Yeah, it would be–it’s another–
it’s another “nice to have.” I think, you know,
I think ultimately, here’s– here’s the issue. I mean, the–the general–
the general thought is if there isn’t a
strong performance reason, for the most part, um, you know,
the–the goal is to make it something that you have to get
through, uh, through Dalvik, because that is the primary– the primary platform
for development for Android. That being said,
there’s a lot of people who want to do really cool stuff
with the camera that, if you had a native interface,
you could do it a lot better. So I-I think that’s–I think
that’s an important one to–to bring up, and–and again,
keep requesting it. Keep complaining about it.
Hopefully, it will happen. man: Thank you. Galpin: All right,
so that being said, uh, I’d like to, uh,
to mention, uh, that, uh,
how many of you guys here are game developers
or want to be game developers? Okay, well… Ni-Lewis: Everybody wants
to be a game developer. Galpin: Uh, well, yeah. Well,
you know, it’s–it’s–it’s– it’s a tough job. Um, so we have something
very special for you. We’ve, uh,
Sony Ericsson has come today, and, uh, they are here to make sure
that every one of you has the ability to develop
really, really great games. And so they want you to have
a device that has support
for a modern GPU, has the support
for a lot of different controls. They want to see what you can do
with it. So, without further ado,
on your way out, you will be getting a card, and you will be able
to exchange that card for your own–very own
Xperia PLAY. [cheers and applause] Galpin: So… our–our only ask, and it’s that
we want to make sure you guys do really,
really cool stuff with it. If you do, uh, and you’re gonna want to go
a couple things– one is you’re gonna want to go
to sonyericsson.com/developer, and–and they’ve written
a lot of articles about how to get to the special
features of that device. The second thing
you’re gonna want to do is, if you do something cool,
go to standout.sonyericsson.com, and let them know
that you’ve done something cool, because they’re always looking
for people who are doing cool stuff
with the Xperia PLAY. So, uh, with that,
I hope you all enjoy it, and I’m very excited and a little jealous
for you all. And, uh,
and there we have it. Ni-Lewis: Thank you.
[cheers and applause] Galpin: Thank you.

Only registered users can comment.

  1. @lunardust201 actually it was the PNGs that were slower and it was an interesting question. Seeing as how the DCT transformations for decoding the JPGs should take more CPU time than the PNG decoding. Maybe he should've let it go after it was clear that they didn't know why but no reason to get upset. Just chill.

  2. OMG… Now I understand how noob at C++ I am…
    I need to continue learning! I want to develop something for android… 🙂

  3. I would not attend such a session, the questions people ask at the end are dumb as fuck heh. Half of them reflect a sort of "Hey look at me, give me attention" desperate need, their one spot at getting recognition from these people instead of using.. oh what.. the standard mailing lists 🙂

  4. @ChristopheMcGuinness lol sir don't be stupid google android is a joke haha its apps are coded in JAVA!!!! BIG TIME FAIL!

  5. @chillipepper117
    Your missing the point the development process is a lot easier and you can now program I'm C/C++ Young Developers can get there foot in the door, its never been so easy to make apps.

  6. i am going to look into the new NDK. i've got an x86 PC emulator that I wrote in plain old C that i would love to port to android, and i sure as hell am not going to rewrite THAT in java. can you imagine an interpreting x86 CPU emulator running in java on the processors that you find in a phone? :shudders:

  7. can any 1 recommend me some c sharp tutorial. i was learning c++, but then i realized that unity3d doesnt support c++, so i switched to c sharp.

  8. Don't be silly now. We all know the best, fastest, easiest way is to write the bytecode yourself, which is how any real programmer would do it!

  9. thanks for this very helpful overview. i have an windows/c++/mfc application called tabtrax youtube id q0N019VHshc that i want to put on an android tablet. it uses simple 2D graphics and a custom ttf font for rendering music notation to screen. would you recommend i use C++ and the NDK or the other more native thing, Dalvic? for my "port" (maybe re-write is a better word). thanks

  10. Looks like no matter what managed layers there are, there is always people looking for more control. I cant see C++ ever going away 🙂

  11. can someone tell What is current state of the fixes for those problems questioned at end part of video. Also: is it not exaggerated how much they want support Native Code / C++ , like i keep hearing?

  12. goooood very goood …..Hello .. possible help if you allow .. method of connecting opencv  with eclipse  Mokth blow up the program correctly .. I hope that you will help me out of necessity. Thank you

  13. I know I'm saying this 6 years later but this could've all been avoided if Android's entire API was written entirely in C and THEN adding that C api into Android's native JNI… That would've made everything so much damn simpler than having to tack on C/C++ into the JNI just to get good performance…

Leave a Reply

Your email address will not be published. Required fields are marked *