bringing c and c++ games to android

107
1

Upload: others

Post on 12-Sep-2021

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Bringing C and C++ Games to Android

1

Ian Ni-LewisDan GalpinGame Developer AdvocatesMay 11 2011

Feedback httpgooglNudVsAndroid

Bringing C and C++ Games to Android

About This Talk

Audience

ndash CC++ Developers

ndash Android background

ndash Game development experience

ndash No prior NDK knowledge needed

Agenda

ndash Programming Android in CC++

ndash Using the NDK

ndash Bringing your game to Android

ndash Troubleshooting tips and tricks

ndash Best practices

3

Native development on phones tablets and beyond

Programming Android in CC++

4

The NDK Provides Support for CC++ Development

NDK = Native Development Kit

Scenarios

ndash Reuse existing libraries

ndash Accelerate key subroutines

bull Access VFP and NEON

ndash Port entire games

5

C++

Whatrsquos in the Box

Toolchain

ndash Standard gcc cross-compilers

Really fancy build system

ndash Primarily written in GNU make

ndash Based on Android platform build system

Headers and libraries

ndash C and C++ runtimes

ndash Stable system interface

6

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 2: Bringing C and C++ Games to Android

Ian Ni-LewisDan GalpinGame Developer AdvocatesMay 11 2011

Feedback httpgooglNudVsAndroid

Bringing C and C++ Games to Android

About This Talk

Audience

ndash CC++ Developers

ndash Android background

ndash Game development experience

ndash No prior NDK knowledge needed

Agenda

ndash Programming Android in CC++

ndash Using the NDK

ndash Bringing your game to Android

ndash Troubleshooting tips and tricks

ndash Best practices

3

Native development on phones tablets and beyond

Programming Android in CC++

4

The NDK Provides Support for CC++ Development

NDK = Native Development Kit

Scenarios

ndash Reuse existing libraries

ndash Accelerate key subroutines

bull Access VFP and NEON

ndash Port entire games

5

C++

Whatrsquos in the Box

Toolchain

ndash Standard gcc cross-compilers

Really fancy build system

ndash Primarily written in GNU make

ndash Based on Android platform build system

Headers and libraries

ndash C and C++ runtimes

ndash Stable system interface

6

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 3: Bringing C and C++ Games to Android

About This Talk

Audience

ndash CC++ Developers

ndash Android background

ndash Game development experience

ndash No prior NDK knowledge needed

Agenda

ndash Programming Android in CC++

ndash Using the NDK

ndash Bringing your game to Android

ndash Troubleshooting tips and tricks

ndash Best practices

3

Native development on phones tablets and beyond

Programming Android in CC++

4

The NDK Provides Support for CC++ Development

NDK = Native Development Kit

Scenarios

ndash Reuse existing libraries

ndash Accelerate key subroutines

bull Access VFP and NEON

ndash Port entire games

5

C++

Whatrsquos in the Box

Toolchain

ndash Standard gcc cross-compilers

Really fancy build system

ndash Primarily written in GNU make

ndash Based on Android platform build system

Headers and libraries

ndash C and C++ runtimes

ndash Stable system interface

6

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 4: Bringing C and C++ Games to Android

Native development on phones tablets and beyond

Programming Android in CC++

4

The NDK Provides Support for CC++ Development

NDK = Native Development Kit

Scenarios

ndash Reuse existing libraries

ndash Accelerate key subroutines

bull Access VFP and NEON

ndash Port entire games

5

C++

Whatrsquos in the Box

Toolchain

ndash Standard gcc cross-compilers

Really fancy build system

ndash Primarily written in GNU make

ndash Based on Android platform build system

Headers and libraries

ndash C and C++ runtimes

ndash Stable system interface

6

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 5: Bringing C and C++ Games to Android

The NDK Provides Support for CC++ Development

NDK = Native Development Kit

Scenarios

ndash Reuse existing libraries

ndash Accelerate key subroutines

bull Access VFP and NEON

ndash Port entire games

5

C++

Whatrsquos in the Box

Toolchain

ndash Standard gcc cross-compilers

Really fancy build system

ndash Primarily written in GNU make

ndash Based on Android platform build system

Headers and libraries

ndash C and C++ runtimes

ndash Stable system interface

6

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 6: Bringing C and C++ Games to Android

Whatrsquos in the Box

Toolchain

ndash Standard gcc cross-compilers

Really fancy build system

ndash Primarily written in GNU make

ndash Based on Android platform build system

Headers and libraries

ndash C and C++ runtimes

ndash Stable system interface

6

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 7: Bringing C and C++ Games to Android

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 8: Bringing C and C++ Games to Android

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 9: Bringing C and C++ Games to Android

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 10: Bringing C and C++ Games to Android

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 11: Bringing C and C++ Games to Android

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

System Libraries

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 12: Bringing C and C++ Games to Android

7

Application Code

Framework Classes

Runtime

Linux Kernel

JNI

Why are Headers and Libraries So Important

Your Libraries

Stable ABI

System Libraries

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 13: Bringing C and C++ Games to Android

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 14: Bringing C and C++ Games to Android

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

JNI Graphics libjnigraphics

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 15: Bringing C and C++ Games to Android

8

Feature Library

C runtime libc

C++ runtime libstdc++

Math libm

Dynamic Linking libdl

Logging liblog

Zlib compression libz

OpenGL ES 11 libGLESv1_CM

OpenGL ES 20 libGLESv2

EGL libEGL

OpenSL ES libOpenSLES

Native framework NativeActivity) libandroid

JNI Graphics libjnigraphics

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 16: Bringing C and C++ Games to Android

What the NDK is Not

Not the end of Dalvik

Not always higher performance

Not necessarily the right choice for every game

9

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 17: Bringing C and C++ Games to Android

Dalvik vs C++

10

C++

Flexible

Easily Extensible

Android APIAccess

AutomaticMemory

Management

Fast

Low-Level

Common onOther Platforms

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 18: Bringing C and C++ Games to Android

How to Use the NDK

11

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 19: Bringing C and C++ Games to Android

Installing the NDK

Download NDK from developerandroidcomsdkndk

ndash Add NDK folder to your path

ndash Install Java JDK

ndash Install Ant

Windows

ndash Install Cygwin

bull Required for debugger

bull Recommended for build scripts

12

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 20: Bringing C and C++ Games to Android

Development Flow

13

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 21: Bringing C and C++ Games to Android

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 22: Bringing C and C++ Games to Android

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Development Flow Project Setup

14

Created by $amp($))+$)(

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 23: Bringing C and C++ Games to Android

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 24: Bringing C and C++ Games to Android

Development Flow Project Setup

15

Run $amp($))+$)(

ndash Ant script

ndash Common directories

ndash Resources

ndash Per-machine settings

OR $amp-+)+$)(

ndash For existing code

Created Manually

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 25: Bringing C and C++ Games to Android

Development Flow Makefiles

16

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Set up project

Write makefiles

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 26: Bringing C and C++ Games to Android

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 27: Bringing C and C++ Games to Android

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 28: Bringing C and C++ Games to Android

Development Flow Makefiles

16

$amp$()+-00+1234567

58094+-$lt=$ltgt7

$A++++)+05BC0DE85$F$Ggt++++)+3H66I6$gtltFJgt+)+C0I4KLL$JMgt++++)+300IC+30GgtND

58094+-MAJgt($ltJMlt$ltO7

$ampampampltPamp$(+)+-00+1234567QL6IER$ampampAgt++++++)+05BC0DE85$ampampampJ++++++++)+4B9C$ampamp$MJ++++++++++)+61B5+61B53NS

APP_STL = gnustl_static

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 29: Bringing C and C++ Games to Android

Development Flow Interface Classes

Write interface in Java

ndash Use amp) keyword

17

LTC+I1K846I54KC0DE85U

QQ+H6LL6+VI6+8R5N+05B662

L9B05+0WW+GDPXJ5B+YR84W+$R5N5R2+Z

++WRR5+Z++++gt2WR1K0I45B662-[C0DE85[7U++

++Q]]+++]+^L61+_54R`+R`+9668R+N5_+_54R`+++]+^L61+`5C`R+R`+9668R+N5_+`5C`R+++]Q+++L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7U+++L9B05+WRR5+8R5N+NI54+WRL-7U

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 30: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 31: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 32: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 33: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 34: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 35: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 36: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 37: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 38: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 39: Bringing C and C++ Games to Android

Generate with javah tool 0(12$amp2345amp2675897amp

bull Eclipse Source|Generate C files from Java class

L9B05+8R5N+NI54+585R-58R+_54R`a+58R+`5C`R7UL9B05+WRR5+8R5N+NI54+WRL-7U

b58094+cE85K`dQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++585R++++gt5C8R96)+-JJ7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]a+EIBERa+E58Ra+E58R7UQ]+]+0WW)+++++I1846I54C0DE85GDPXJ5B+]+R`I4)++++WRL++++gt5C8R96)+-7=+]QPXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5BWRL++-PXJ8N+]a+E0WW7U

Development Flow JNI Glue

18

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 40: Bringing C and C++ Games to Android

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 41: Bringing C and C++ Games to Android

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 42: Bringing C and C++ Games to Android

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 43: Bringing C and C++ Games to Android

Get native signatures from class file with javap -s +lt=lt+$amp)(12$amp2345amp2675897amp

WRR5+PXJXR5NR`I4+CR`I4Wfg++Z++Z+[585R[a+[-JJ7=[a+-NI54]7+8R5NG1J85R+a+++Z+[WRL[a+[-7=[a+-NI54]7+8R5NgtRL+U

++`6]+0WWX1++[I1Q846I54QC0DE85QGDPXJ5B[U++E0WW+0hh++8N3dF5840WW-0WWX17U++5V+-0hh++XA7+Z++++846I540ICL658R-$XltJGltltlta+[$_WI1G1[a++++++[XR5N+6C5WR6R5I8+98B0+RI+V584+0WW+ijWik8[a+0WWX17U++6R968+PXJF$gtU++++5V+-8N3dltC5WR6XR5NW-0hha+CR`I4Wa+891R`I4W7+c+l7+Z+ 846I540ICL658R-$XltJGltltlta+[$_WI1G1[a+ ++[ltC5WR6XR5NW+V504+VI6+ijWik8[a+0WWX17U++6R968+PXJF$gtU++

Development Flow JNI Glue with Manual Registration

19

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 44: Bringing C and C++ Games to Android

PXJeamplt+NI54+PXJ$+PNI1846I54C0DE85GDPXJ5B585R++-PXJ8N+]LPXJ8Na+EIBER+IBEa+E58R+a+E58R+B7+Z

++E0WW+0W++-]LPXJ8N73dGRBER0WW-LPXJ8Na+IBE7U

++E1R`I4J+54++-]LPXJ8N73dGRR`I4J-+++++++++++++++++++++++++++++LPXJ8Na+0Wa+[RTm2N8RW[a+[-n7=[7U

++-]LPXJ8N73d00=I54R`I4-LPXJ8Na+IBEa+54a+PXJltA7U

Development Flow Calling Dalvik Code Within CC++

20

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 45: Bringing C and C++ Games to Android

Development Flow Build and Deploy

gt=0Alt-amp49BCDBEFG6HI

ndash Builds C libraries and emits so files

gt)-3

ndash (or ant release)

ndash Builds Java classes apk package

gtamp=44

ndash Deploys to emulator or device

21

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 46: Bringing C and C++ Games to Android

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 47: Bringing C and C++ Games to Android

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 48: Bringing C and C++ Games to Android

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdbgdb-rsp over named pipe

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 49: Bringing C and C++ Games to Android

gt=0Alt3

ndash Sanity checks your setup

ndash Starts gdbserver on device opens named pipe

ndash Forwards pipe to socket on host

ndash Starts gdb client on host connects to socket

Host

Development Flow Debug

22

Device

gdbserver

application

gdb

EclipseVS

gdb-rsp over named pipe

gdb-MI

Set up project

Write interface classes

Write JNI glue

Write makefiles

Build Deploy

Debug

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 50: Bringing C and C++ Games to Android

Important Tip

B)-36amp3)$$)J23

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 51: Bringing C and C++ Games to Android

Bringing Your Game to Android

24

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 52: Bringing C and C++ Games to Android

Devices Accessing Android Market

25

Android 16

Android 15

Android 23

Android 233

Android 30

Two Week Period Published May 2011

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 53: Bringing C and C++ Games to Android

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 54: Bringing C and C++ Games to Android

Great uptake for Android 22

ndash In ten months 659 of devices checking in to Market running Froyo

ndash 947 of devices running Android 21 or higher

NativeActivity is just starting

ndash 43 of checking-in devices can utilize it

ndash For non-tablet-specific titles we can take advantage of NativeActivity without becoming incompatible

Devices Accessing Android Market

25

Android 22(Froyo)

Android 21(Eclair)

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 55: Bringing C and C++ Games to Android

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 56: Bringing C and C++ Games to Android

Using NativeActivity Compatibly

26

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

Platform-specific Resources

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 57: Bringing C and C++ Games to Android

Using NativeActivity Compatibly

27

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dV0WcQBII0d++++cBII0+81[8IRG58C6B64[dR69cQBII0dcQ6WI96Wd

coY10+N6W5I8[pKl[+8I458C[9RV3q[odc6WI96Wd++++cBII0+81[RWRG58C6B64[dR69cQBII0d++++cBII0+81[8IRG58C6B64[dV0WcQBII0dcQ6WI96Wd

Using NativeActivity Compatibly

28

Platform-specific resources

ndash can be used to define boolean values

bull activities can be enabled based upon these values

cR5N5R2+846I54)81[Kgt$XR5N$R5N5R2[+++846I54)8B04[^BII0QRWRG58C6B64[d++c1R34R+846I54)81[846I54KLLK05B81[+++++846I54)N09[W8R5N[+Qd++++++++++++++++++++++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6d++++++++++++cQR5N5R2dcR5N5R2+846I54)81[K1I$R5N5R2[+++846I54)8B04[^BII0Q8IRG58C6B64[d++c58R8R3V50R6d++++cR5I8+846I54)81[846I54K58R8RKR5I8K$JX[Qd++++cRCI62+846I54)81[846I54K58R8RKRCI62K$AX(lt[Qd++cQ58R8R3V50R6dcQR5N5R2d

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

29

Dynamic libraries

ndash create stub libraries as interfaces to your game engine

PXJltFlt+ )+-00+123456758094+-PXJltFlt7Q05BW88C0WQ$846I54K1T58094+-PXJltFlt7Q05BW8R5NQ$846I54K1T58094+-PXJltFlt7Q05BWE85Q$846I54K1T

$ampampamp$Flt+)+846I543r$ampampAgt+)+05BW88C0W+05BW8R5N+05BWE85$ampampampJ+)+60W$ampamp$MJ+)+61B5+61B53NS

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

Using NativeActivity Compatibly

30

Dynamic Libraries

ndash create multiple libraries as interfaces to your game engine

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+WE85$F$Ggt+)+3$XltJXm$gtltFJgt+ )+LL3846I54K$JMgt+)+30GgtND+3040+300IC$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7

$amp$(+ )+-00+123456758094+-$lt=$ltgt7$A+)+W8R5N$F$Ggt+)+3$XltJXm$gtltFJgt+ )+C09R50WK+k+ LL3846I5438R5NK$JMgt+)+30GgtND+3040+300IC+30G+30846I54$gt$JJMlt$ltJgt+ )+846I548R5NLLC09$gt($ltJMlt$ltJgt+ )+W88C0W58094+-MAJgt($ltJMlt$ltO7-00+51LI6R31I490a846I54Q8R5NLLC097

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

Using NativeActivity Compatibly

31

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

LTC+I1KY1L0KW88C0WU

L9B05+0WW+gt$XR5N$R5N5R2+YR84W+846I54KLLKXR5N$R5N5R2+Z

++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

Using NativeActivity Compatibly

32

Dynamic libraries

ndash the third library must be loaded manually before the native activity library

ndash we can extend NativeActivity to do this

ndash with our JNI-based class we load in order

LTC+I1KY1L0KW88C0WU

L9B05+0WW+1I$R5N5R2+YR84W+846I54KLLK$R5N5R2+Z++++WRR5+Z++++++++gt2WR1K0I45B662-[W88C0W[7U++++++++gt2WR1K0I45B662-[WE85[7U++++KKK

Key Game Components

33

Lifecycle

Graphics Sound

Input

Assets

Activity LifecycleLifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Activity Lifecycle

Activity Starts

onCreate()

onStart()

onResume()

Activity is Running

onPause()

onStop()

onDestroy()

Activity is Shut Down

Another activity comes in front of the activity

The activity is no longer visible

Other applications need memory

Process is Killed

User navigates back to the activity

The activity comes to the foreground

The activity comes to the foreground

onRestart()

Lifecycle

Process LifecycleLifecycle

Android keeps application processes around for as long as possible

ndash Even when the activity is closed with V585W`-7 or the back key is pressed

The foreground activity process is considered the most important

ndash It can still be killed as a last resort

Visible activities are also given high priority

ndash Backgrounded activities are considered less important

ndash Processes with no active activities are killed first

Implications of the Process LifecycleLifecycle

Be careful with static initializers

ndash Your library cannot be unloaded while your process is active

bull Donrsquot assume that your static initializers will be run when your activity is created

Be careful with threads

ndash Threads are tied to the process not the activity

bull Your threads will continue to run at reduced priority even if your activity is backgrounded or destroyed

ndash Gameplay should stop during onPause

bull It might make sense to keep certain threads running - your activity may still be visible

ndash Make sure all native code is cleaned up during onDestroy

bull Users expect that your application will no longer be active when its activity is destroyed

The Basics

Key handling

ndash Your device most likely has capacitive buttons

bull Look for complete state transitions of I8m2I_8I8m2AL

bull Avoid overriding 45WLR`m2N8R

ndash Use I8m290R5L0I8m2I8Camp6WW

bull Keep your game behaving like an Android application

TouchMultitouch handling

ndash With I8I9`N8R

bull take advantage of built-in gesture processing

ndash use gt0GWR96RRI6 and GWR96RRI6

ndash Most devices now support multitouch

bull determine if your device can track distinct points

ndash `Wgt2WR1FR96-F$AltA(gtltXAJA(JgtJX)

37

Input

Other Input

Trackball handling

ndash With I86TB00N8R

bull Unhandled events turn into dpad events

Motion handling

ndash With I8gt8WI6`8C4

bull Must be registered with the gt8WI68C6

bull Disable unneeded sensors especially when paused

ndash Active sensors will quickly drain the battery

38

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

Androidify Your Game

39

Donrsquot break the ldquohard buttonsrdquo

ndash Back dismiss dialogs exit menus pause the game

ndash Menu pause launch options dialog

ndash Home pause (not quit)

Donrsquot break the volume buttons

ndash Donrsquot eat volume button messages

s WR=I091I8R6I0gtR61-$945I8C6Kgtlt$AgtJ7

Donrsquot let the ldquohard buttonsrdquo break your game

ndash Very easy to press accidentally on some devices

bull Pause and give user the option to exit when back is pressed

bull Save game state whenever possible onPauseonStop

Input

OpenGL

GLSurfaceView

ndash Creates the compatible context

bull Contexts are shared between native code and Dalvik

ndash Creates a rendering thread

ndash Releases the context during onPause

ndash Not the most efficient way to multitask withOpenGL but it avoids some driver issues

When context is lost

ndash Reload resources

bull Textures

bull Buffer objects

bull Shaders

ndash Names donrsquot persist

40

Graphics

Texture Formats

Android encourages innovation in hardware

ndash Chipset vendors use several kinds of proprietary texture compression formats

ndash OpenGL ES supports multiple compressed formats none mandatory

Solutions

ndash Uncompressed Textures

ndash Use ETC1 ndash broad support in 20

bull Optimized around photographic data

bull No Alpha

ndash Use Multi-APK (coming soon)

ndash Put textures on an asset server

bull Detect support at runtime

bull Download to each device

41

Graphics

Drawing for Performance

Draw order is important

ndash Has no impact on some platforms means everything on others

ndash Draw front to back to make best use of early rejects

Use VBOs

ndash Avoid unnecessary state changes

Textures

ndash Use power of 2 sized textures

bull It can be very slow

bull On some chipsets not all address modes work

42

Graphics

Writing Compatible Shaders

Query query

ndash Make sure to query for number of attributes varying and uniforms supported

bull Varies between devices

bull Not respecting will make your application crash

bull ldquoSupportedrdquo does not mean ldquoperforms wellrdquo

Conditions

ndash Avoid as much as possible

bull if necessary put them last in the shader

ndash Use mix() clamp() etc to create the same result

discard()

ndash Avoid discard()

bull if necessary it should be last

43

Graphics

Audio Solutions

Full track audio

s 45amp026

bull Plays multiple formats with codec support

bull Plays from filesystem or from network

bull Has high latency memory and CPU usage for quick sound effects

Sound effects and clips

s gtI984ampII0

bull Plays multiple formats with codec support

bull Preloads audio files to a pool

ndash Plays them with low latency

44

Sound

Audio Solutions

Application-generated audio

s $945I6T

bull Plays PCM audio only with minimal latency

bull Useful for applications that wish to perform sound processing or mixing

OpenSLES

ndash Combines capabilities of 45amp026 and $945I6T

ndash Available only in the NDK

ndash Requires Android 23 and higher

45

Sound

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

The JNI Solution

Get the APK file name

s I8RYRKCR$LL05R5I8J8VI-7KWI9656

Use the asset manager code to get an AssetFileDescriptor

s V4++I8RYRKCR$WWRW-7KIL8F4-[IIR`26I54KL8C[7U

Read the offset and length from the AssetFileDescriptor

s 0I8C+IVVWR++V4KCRgtR6RVVWR-7U0I8C+08CR`++V4KCR0648CR`-7UV4K0IW-7U

Open the APK file at the specified offset and read the specified length

46

Assets

Use a native Zip Utility

ndash Slightly less future-proof

ndash Potentially faster

bull Make sure to cache the Zip directory

bull Get the offset and length if the item isnrsquot compressed

Use native AssetManager

ndash Gingerbread and Beyond

Targeting tricky trying tasks

Troubleshooting Tips and Tricks

47

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

Troubleshooting Threading Dalvik and the NDK

Problem App crashes mysteriously

Solution Check your threading

ndash JNI contexts are per-thread

48

Activity

JNI Context

Main UI Loop Game Loop

Framework Class

One JNI Context Per Thread

Threading Options

49

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

JNI Context 2

Activity

JNI Context 1

Main UI loop

Game loop

Framework Class

OR

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

Troubleshooting Performance

Check for older hardware

ndash ARM7 CPUs (use cpu-features lib)

ndash No support for OpenGL 2

Fallbacks for older HW

ndash Use 16-bit texturest M5R1LFRI62KLR5I8WK58amp6V664I8V5C++M5R1LKI8V5CK$ltGMuuuu

ndash Use smaller render target scale up

bull Framework will do it for you with gt96V(I046KWRF5Y4gt5h-7

bull Pixels are expensive especially on tablets

50

If all else fails Market filters

ndash Instruction set

ndash ARMv5ARMv7

ndash GL version

ndash Platform release

ndash Use Device Availability

Tips Standing Out from the Crowd

Start Small

ndash Download assets as-needed

ndash Hook me early instead of making me wait

Use Android backuprestore service (save to the cloud)

ndash Keep my progress when I switch devices

Support multiple control schemes

ndash Trackball D-pad virtual stick

ndash Let me decide what works best

Support install-to-SD

ndash Android Market users will knock your ratings if you donrsquot

51

Tips Standing Out from the Crowd

Profiling

ndash In-game profiling to select optimal settings per-device

Social

ndash Hook into social networks

ndash Use OpenID

Build a live wallpaper

ndash Own the userrsquos home screen with stats avatars

Analytics

ndash Market and in-game

In-app payments

ndash Consider alternative monetization techniques

52

Troubleshooting Development Tools

NVIDIA Debug Manager for Eclipse

ndash Simplifies setup for native debugger under Eclipse

bull developernvidiacomtegranvidia-debug-manager-android-ndk

WinGDB

ndash Use Visual Studio to debug Android NDK applications

bull wwwwingdbcom

vs-android

ndash Native MSBuild files for Android toolchain

bull vs-androidgooglecodecom

53

Troubleshooting Performance Tools

NVIDIA PerfHUD ES

ndash developernvidiacomtegraperfhud-es

Adreno Profiler

ndash developerqualcommcomshowcaseadreno-profiler

POWERVR Insider Utilities

ndash Including PVRTrace and PVRTune

ndash wwwimgteccompowervrinsiderpowervr-utilitiesasp

54

developerandroidcomsdkndkGoogleGameDevAndroid

Feedback httpgooglNudVs

QampA

55

Page 58: Bringing C and C++ Games to Android
Page 59: Bringing C and C++ Games to Android
Page 60: Bringing C and C++ Games to Android
Page 61: Bringing C and C++ Games to Android
Page 62: Bringing C and C++ Games to Android
Page 63: Bringing C and C++ Games to Android
Page 64: Bringing C and C++ Games to Android
Page 65: Bringing C and C++ Games to Android
Page 66: Bringing C and C++ Games to Android
Page 67: Bringing C and C++ Games to Android
Page 68: Bringing C and C++ Games to Android
Page 69: Bringing C and C++ Games to Android
Page 70: Bringing C and C++ Games to Android
Page 71: Bringing C and C++ Games to Android
Page 72: Bringing C and C++ Games to Android
Page 73: Bringing C and C++ Games to Android
Page 74: Bringing C and C++ Games to Android
Page 75: Bringing C and C++ Games to Android
Page 76: Bringing C and C++ Games to Android
Page 77: Bringing C and C++ Games to Android
Page 78: Bringing C and C++ Games to Android
Page 79: Bringing C and C++ Games to Android
Page 80: Bringing C and C++ Games to Android
Page 81: Bringing C and C++ Games to Android
Page 82: Bringing C and C++ Games to Android
Page 83: Bringing C and C++ Games to Android
Page 84: Bringing C and C++ Games to Android
Page 85: Bringing C and C++ Games to Android
Page 86: Bringing C and C++ Games to Android
Page 87: Bringing C and C++ Games to Android
Page 88: Bringing C and C++ Games to Android
Page 89: Bringing C and C++ Games to Android
Page 90: Bringing C and C++ Games to Android
Page 91: Bringing C and C++ Games to Android
Page 92: Bringing C and C++ Games to Android
Page 93: Bringing C and C++ Games to Android
Page 94: Bringing C and C++ Games to Android
Page 95: Bringing C and C++ Games to Android
Page 96: Bringing C and C++ Games to Android
Page 97: Bringing C and C++ Games to Android
Page 98: Bringing C and C++ Games to Android
Page 99: Bringing C and C++ Games to Android
Page 100: Bringing C and C++ Games to Android
Page 101: Bringing C and C++ Games to Android
Page 102: Bringing C and C++ Games to Android
Page 103: Bringing C and C++ Games to Android
Page 104: Bringing C and C++ Games to Android
Page 105: Bringing C and C++ Games to Android
Page 106: Bringing C and C++ Games to Android
Page 107: Bringing C and C++ Games to Android