Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Android NDK Game Development Cookbook
Android NDK Game Development Cookbook

Android NDK Game Development Cookbook: For C++ developers, this is the book that can swiftly propel you into the potentially profitable world of Android games. The 70+ step-by-step recipes using Android NDK will give you the wide-ranging knowledge you need.

Arrow left icon
Profile Icon Sergey Kosarevsky Profile Icon Viktor Latypov
Arrow right icon
$19.99 per month
Full star icon Full star icon Full star icon Full star icon Empty star icon 4 (5 Ratings)
Paperback Nov 2013 320 pages 1st Edition
eBook
€28.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at $19.99p/m
Arrow left icon
Profile Icon Sergey Kosarevsky Profile Icon Viktor Latypov
Arrow right icon
$19.99 per month
Full star icon Full star icon Full star icon Full star icon Empty star icon 4 (5 Ratings)
Paperback Nov 2013 320 pages 1st Edition
eBook
€28.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at $19.99p/m
eBook
€28.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with a Packt Subscription?

Free for first 7 days. €18.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing
Table of content icon View table of contents Preview book icon Preview Book

Android NDK Game Development Cookbook

Chapter 1. Establishing a Build Environment

 

Some LinkedIn profiles say developing with a particular IDE is a skill.

No! Development without any IDE is the skill!

 
 --Sergey Kosarevsky

In this chapter, we will cover the following recipes:

  • Installing Android development tools on Windows
  • Installing Android development tools on Linux
  • Creating an application template manually
  • Adding native C++ code to your application
  • Switching NDK toolchains
  • Supporting multiple CPU architectures
  • Basic rendering with OpenGL ES
  • Going cross platform
  • Unifying the cross-platform code
  • Linking and source code organization
  • Signing release Android applications

Introduction

This chapter explains how to install and configure Android NDK on Microsoft Windows or Ubuntu/Debian Linux, and how to build and run your first application on an Android-based device. We will learn how to set-up different compilers and toolchains that come with Android NDK. In addition, we show how to setup the GCC toolchain for Windows to build your projects. The rest of the chapter is devoted to cross-platform development using C++.

Installing Android development tools on Windows

To start developing games for Android you will need some essential tools to be installed on your system.

Getting ready

Here is the list of all the prerequisites you will need to start developing games for Android:

Former versions of SDK/NDK for Windows required a Cygwin environment, a Linux-like environment for Windows, to be installed. Up-to-date versions of these tools can run natively on Windows without any intermediate layer. We will focus on the Cygwin-less environment and will do all of the development without IDE. You heard it right, we will just use the command line. All the examples in this book were written and debugged on a Windows PC.

To compile native Windows applications presented in this book, you will need a decent C++ compiler, such as the MinGW package with a GCC toolchain. Using Microsoft Visual Studio is also possible.

Note

Minimalist GNU for Windows (MinGW) is a minimalist development environment for Windows applications using a port of GNU Compiler Collection (GCC).

How to do it...

  1. Android SDK and NDK should be installed into folders that do not contain any whitespaces in their names.

    Note

    This requirement comes from the limitations of scripts in Android SDK. There is a nice discussion on StackOverflow which explains some reasons behind these limitations at http://stackoverflow.com/q/6603194/1065190.

  2. Other tools can be installed to their default locations. We used the following paths in our Windows 7 system:

Tools

Path

Android SDK

D:\android-sdk-windows

Android NDK

D:\ndk

Apache Ant

D:\ant

Java Development Kit

C:\Program Files\Java\jdk1.6.0_33

All tools have pretty decent GUI installers (see the following image, that shows the Android SDK Manager from SDK R21) so you don't have to use the command line.

How to do it...

For the Windows environment, you need the MinGW GCC toolchain. The easy to install all-in-one package can be found at http://www.equation.com, in the Programming Tools section, Fortran, C, C++ subsection. Alternatively, you can download the official installer from http://www.mingw.org. We will use the one from www.equation.com

There's more...

You need to set some environment variables to let the tools know where the files are located. The JAVA_HOME variable should point to the Java Development Kit folder. The NDK_HOME variable should point to the Android NDK installation folder, and ANDROID_HOME should point to the Android SDK folder (note the double backslash). We used the following environment variable values:

JAVA_HOME=D:\Java\jdk1.6.0_23

NDK_HOME=D:\ndk

ANDROID_HOME=D:\\android-sdk-windows

The final configuration looks similar to the one shown in the following screenshot, which shows the Windows Environment Variables dialog box:

There's more...

After MinGW has been successfully installed, you should also add the bin folder from its installation folder to the PATH environment variable. For example, if MinGW is installed to C:\MinGW, then PATH should contain the C:\MinGW\bin folder.

Installing Android development tools on Linux

Installation of the basic tools on Linux is as easy as it was with their Windows counterpart. In this recipe, we will see how to install the basic Android development tools on *nix systems.

Getting ready

We assume you already have an Ubuntu/Debian system with the apt package manager. Refer to http://wiki.debian.org/Apt for details.

How to do it...

Carry out the following steps to install the required basic tools:

  1. Make sure you are using the latest version of the packages for your OS by running the following command:
    >sudo apt-get update
    
  2. Install OpenJDK 6+:
    >sudo apt-get install openjdk-6-jdk
    
  3. Install the Apache Ant build automation tool:
    >sudo apt-get install ant
    
  4. Download the official Android SDK from http://developer.android.com. There is a bigger package next to it, with the ADT plugin for the Eclipse IDE. However, since we do all of our development from the command line, we won't need it. Run the following command:
    >wget http://dl.google.com/android/android-sdk_r22.2.1-linux.tgz
    
  5. Unpack the downloaded .tgz file (the actual version might vary, 22.2.1 is the latest version as of October 2013):
    >tar -xvf android-sdk_r22.2.1-linux.tgz
    
  6. Use ~/<sdk>/tools/android to install the latest Platform Tools and all of the SDKs—just like in the Windows case.

    Failure to do so will result in an error while trying to use the Ant tool when building any application for the Android.

  7. Get the official Android NDK from http://developer.android.com:
    >wget http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2
    
  8. Unpack the downloaded NDK .tgz file:
    >tar -xvf android-ndk-r9b-linux-x86_64.tar.bz2
    
  9. Set the NDK_ROOT environment variable to your Android NDK directory (for example, ~/android-ndk-r9b in our case):
    >NDK_ROOT=/path/to/ndk
    

    It is useful to put this line and the JAVA_HOME definition to /etc/profile or /etc/environment, if these settings are applicable to all the users of the system.

  10. In case you are running a 64-bit system, you must ensure that you have the 32-bit Java runtime installed also.
  11. Run the following command to install the libraries. Failure to do so may lead to errors with adb and aapt tools:
    >sudo apt-get install ia32-libs
    

There's more...

There is a nice one-liner script that helps you automatically detect the OpenJDK home directory. It essentially resolves the link /usr/bin/javac to the full path and returns the directory part of the path.

  JAVA_HOME=$(readlink -f /usr/bin/javac | sed "s:bin/javac::")

Creating an application template manually

First of all, we are going to create a basic template for our applications. Every Android application that is to be built via Android SDK, should contain a predefined directory structure and the configuration .xml files. This can be done using Android SDK tools and IDEs. In this recipe, we will learn how to do it manually. We will use these files later on as the very starting point for all our examples.

Getting ready

Let us set up the directory structure of our project (see the following screenshot):

Getting ready

This is a typical structure for any Android project. We will create all the required files manually rather than using Android tools.

How to do it...

Place the Java Activity code into the App1\src\com\packtpub\ndkcookbook\app1\App1Activity.java file, which should look as follows:

package com.packtpub.ndkcookbook.app1;
import android.app.Activity;
public class App1Activity extends Activity
{
};

The localizable application name should go to App1\res\values\strings.xml. The string parameter app_name is used in the AndroidManifest.xml file to specify the user-readable name of our application, as seen in the following code:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">App1</string>
</resources>

Now we need to write more scripts for Apache Ant and the Android SDK build system. They are necessary to build the .apk package of your application.

  1. The following is the App1/project.properties file:
    target=android-15
    sdk.dir=d:/android-sdk-windows
  2. We need two more files for Ant. The following is App1/AndroidManifest.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.packtpub.ndkcookbook.app1"
      android:versionCode="1"
      android:versionName="1.0.0">
      <supports-screens
         android:smallScreens="false"
         android:normalScreens="true"
         android:largeScreens="true"
         android:xlargeScreens="true"
         android:anyDensity="true" />
      <uses-sdk android:minSdkVersion="8" />
      <uses-sdk android:targetSdkVersion="18" />

    Our examples require at least OpenGL ES 2. Let Android know about it:

      <uses-feature android:glEsVersion="0x00020000"/>
      <application android:label="@string/app_name"
                   android:icon="@drawable/icon"
                   android:installLocation="preferExternal"
                   android:largeHeap="true"
                   android:debuggable="false">
      <activity android:name="com.packtpub.ndkcookbook.app1.App1Activity"
    android:launchMode="singleTask"

    Create a full-screen application in a landscape screen orientation:

                      android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
                      android:screenOrientation="landscape"
                      android:configChanges="orientation|keyboardHidden"
                      android:label="@string/app_name">
        <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
       </activity>
     </application>
    </manifest>

    The second file is App1/build.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="App1" default="help">
        <property file="ant.properties" />
        <loadproperties srcFile="project.properties" />
        <import file="${sdk.dir}/tools/ant/build.xml" />
    </project>

How it works...

With all the listed files in place, we can now build the project and install it on an Android device by carrying out the following steps:

  1. From the App1 folder run:
    >ant debug
    
  2. The tail of the output from the previous command should look like:
    BUILD SUCCESSFUL
    Total time: 12 seconds
    
  3. And the built debug .apk package is in bin/App1-debug.apk.
  4. To install the app, run:
    >adb install App1-debug.apk
    

    Note

    Don't forget to connect your device through a USB and turn USB Debugging on in Android settings before running this command.

  5. You should see the output from adb, similar to the following commands:
    * daemon not running. starting it now on port 5037 *
    * daemon started successfully *
    1256 KB/s (8795 bytes in 0.006s)
            pkg: /data/local/tmp/App1-debug.apk
    Success
    

The application can now be started from your Android launcher (named App1). You will see just a black screen. You can exit the application using the BACK button.

There's more...

Don't forget to put the application icon into App1\res\drawable\icon.png. Refer to the book's code bundle if you want to build the app quickly, or put your own icon there. 72 x 72 32-bit will do just fine. You can find the official Android icons guidelines at http://developer.android.com/design/style/iconography.html.

The official documentation on the AndroidManifest.xml file can be found at http://developer.android.com/guide/topics/manifest/manifest-intro.html.

Furthermore, you can update your applications without uninstalling the previous version using the adb -r command-line switch in the following way:

>adb install -r App1-debug.apk

Otherwise, before installing a new version of your application you will have to uninstall the existing one using the following command:

>adb uninstall <package-name>

See also…

  • Signing release Android applications

Adding native C++ code to your application

Let us expand our minimalistic Java template, which was discussed in the previous recipe, so we can create a placeholder for our native C++ code.

Getting ready

We need to copy all the files from our App1 project to save time while creating the initial project files. This recipe will focus on the changes to be made to the App1 project in order to add the C++ code to it.

How to do it...

Carry out the following steps to create a placeholder for our C++ code:

  1. Add the jni/Wrappers.cpp file with the following code:
    #include <stdlib.h>
    #include <jni.h>
    #include <android/log.h>
    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "App2", __VA_ARGS__))
    
    extern "C"
    {
      JNIEXPORT void JNICALL
    Java_com_packtpub_ndkcookbook_app2_App2Activity_onCreateNative( JNIEnv* env, jobject obj )
        {
          LOGI( "Hello World!" );
        }
    }
  2. We need to change our Activity class from the previous recipe to make use of the native code we just added in the preceding section, through the following code:
    package com.packtpub.ndkcookbook.app2;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class App2Activity extends Activity
    {
        static
        {

    Here we load the native library named libApp2.so. Note the omitted lib prefix and .so extension:

          System.loadLibrary( "App2" );
        }
        @Override protected void onCreate( Bundle icicle )
        {
          super.onCreate( icicle );
          onCreateNative();
        }
        public static native void onCreateNative();
    };
  3. Tell the NDK build system how to treat the .cpp file. Create the jni/Android.mk file. The Android.mk file is used by the Android NDK build system to find out how to treat the source code of your project:
    TARGET_PLATFORM := android-7
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_ARM_MODE := arm
    LOCAL_MODULE     := App2
    LOCAL_SRC_FILES += Wrappers.cpp
    LOCAL_ARM_MODE := arm
    COMMON_CFLAGS := -Werror -DANDROID -DDISABLE_IMPORTGL \
    -isystem $(SYSROOT)/usr/include/
    ifeq ($(TARGET_ARCH),x86)
    	LOCAL_CFLAGS   := $(COMMON_CFLAGS)
      else
    	LOCAL_CFLAGS   := -mfpu=vfp -mfloat-abi=softfp \
      -fno-short-enums $(COMMON_CFLAGS)
    endif
    LOCAL_LDLIBS     := -llog -lGLESv2 -Wl,-s
    LOCAL_CPPFLAGS += -std=gnu++0x
    include $(BUILD_SHARED_LIBRARY)

    Note the ifeq ($(TARGET_ARCH),x86) section. Here we specify architecture-specific compiler flags for floating point support on ARMv7. This will give you hardware floating-point support on the ARM architecture and a warnings-free log on the x86 Android target architecture..

  4. Paste the following code into the jni/Application.mk file:
    APP_OPTIM := release
    APP_PLATFORM := android-7
    APP_STL := gnustl_static
    APP_CPPFLAGS += -frtti 
    APP_CPPFLAGS += -fexceptions
    APP_CPPFLAGS += -DANDROID
    APP_ABI := armeabi-v7a
    APP_MODULES := App2
    NDK_TOOLCHAIN_VERSION := clang

How it works...

  1. First of all, we need to compile the native code. From the root of your App2 project, run the following command:
    >ndk-build
    
  2. You should see the following output:
    Compile++ arm: App2 <= Wrappers.cpp
    SharedLibrary: libApp2.so
    Install      : libApp2.so => libs/armeabi-v7a/libApp2.so
    
  3. Now proceed to the .apk creation as in the previous recipe by running the following command:
    >ant debug
    
  4. Your libApp2.so native shared library will be packed into the App2-debug.apk package. Install and run it. It will output a Hello World! string into the device log.

There's more...

You can use the adb command to view the device log. A nice clean formatted log with timestamps can be created using the following command:

>adb logcat -v time > 1.txt

The actual output from your device will look similar to the following command:

05-22 13:00:13.861 I/App2    ( 2310): Hello World!

Switching NDK toolchains

A toolchain is a set of tools that are used to build your project. A toolchain usually consists of a compiler, an assembler, and a linker. Android NDK comes with different toolchains—GCC and Clang—of different versions. It has a convenient and simple way to switch between them.

Getting ready

Look through the list of the available toolchains before proceeding. You can find all the available toolchains in the $(NDK_ROOT)/toolchains/ folder.

How to do it...

The parameter NDK_TOOLCHAIN_VERSION in Application.mk corresponds to one of the available toolchains. In NDK r9b, you can switch between three GCC versions—4.6, and 4.7, which are marked as deprecated and will be removed from the next NDK releases, and 4.8. And two Clang versions—Clang3.2, which is also marked as deprecated, and Clang3.3. The default toolchain in the NDK r9b is still GCC 4.6.

Starting from the NDK r8e, you can just specify clang as the value of NDK_TOOLCHAIN_VERSION. This option will select the most recent version of the available Clang toolchain.

There's more...

The toolchains are discovered by the $(NDK_ROOT)/build/core/init.mk script, so you can define your own toolchain in a folder named <ABI>-<ToolchainName> and use it in Application.mk.

Supporting multiple CPU architectures

Android NDK supports different CPU architectures such as ARMv5TE and ARMv7-based devices, x86, and MIPS (big-endian architecture). We can create fat binaries that can run on any of the supported platforms.

Getting ready

Find out the architecture of your Android-based device. You can do it using the adb command as follows:

>adb shell cat /proc/cpuinfo

How to do it...

The following are the two approaches to pick an appropriate set of CPU architectures:

  1. By default, the NDK will generate the code for ARMv5TE-based CPUs. Use the parameter APP_ABI in Application.mk to select a different architecture, for example (use only one line from the following list):
    APP_ABI := armeabi-v7a
    APP_ABI := x86
    APP_ABI := mips
  2. We can specify multiple architectures to create a fat binary that will run on any of them through the following command:
    APP_ABI := armeabi armeabi-v7a x86 mips

There's more...

The main pitfall of the fat binaries is the resulting .apk size, as separate native code versions are compiled for each of the specified architectures. If your application heavily uses third-party libraries, the package size can become an issue. Plan your deliverables wisely.

Basic rendering with OpenGL ES

Let us add some graphics to our sample Android application App2. Here, we show how to create an off-screen bitmap, and then copy it to the screen using the OpenGL ES Version 2 or 3 available on your Android device.

Note

Refer to the App3 sample in the book's downloadable code bundle for the full source code.

Getting ready

We assume that the reader is somewhat familiar with OpenGL and the GL Shading Language (GLSL). Refer to http://www.opengl.org/documentation for the desktop OpenGL, and http://www.khronos.org/opengles for the mobile OpenGL ES documentation.

How to do it…

  1. We need to write a simple vertex and fragment GLSL shader that will render our framebuffer on the screen using OpenGL ES. Let's put them directly into jni/Wrappers.cpp as strings. The following code shows the vertex shader:
    static const char g_vShaderStr[] =
       "#version 100\n"
       "precision highp float;\n"
       "attribute vec3 vPosition;\n"
       "attribute vec3 vCoords;\n"
       "varying vec2 Coords;\n"
       "void main()\n"
       "{\n"
       "   Coords = vCoords.xy;\n"
       "   gl_Position = vec4( vPosition, 1.0 );\n"
       "}\n";
  2. The fragment shader is as follows:
    static const char g_fShaderStr[] =
       "#version 100\n"
       "precision highp float;\n"
       "varying vec2 Coords;\n"
       "uniform sampler2D Texture0;\n"
       "void main()\n"
       "{\n"
       "   gl_FragColor = texture2D( Texture0, Coords );\n"
       "}\n";
  3. We will also need the following helper function to load our shaders into OpenGL ES:
    static GLuint LoadShader( GLenum type, const char* shaderSrc )
    {
       GLuint shader = glCreateShader( type );
       glShaderSource ( shader, 1, &shaderSrc, NULL );
       glCompileShader ( shader );
       GLint compiled;
       glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
       GLsizei MaxLength = 0;
       glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &MaxLength );
       char* InfoLog = new char[MaxLength];
       glGetShaderInfoLog( shader, MaxLength, &MaxLength, InfoLog );
       LOGI( "Shader info log: %s\n", InfoLog );
       return shader;
    }

How it works…

We will not go into all the details about the OpenGL ES programming here, and will instead focus on a minimal application (App3) that should initialize the GLView in Java; create fragment and vertex programs, create and fill the vertex array consisting of two triangles that form a single quadrilateral, and then render them with a texture, which is updated from g_FrameBuffer contents. This is it—just draw the offscreen framebuffer. The following is the code to draw the full-screen quad textured with the offscreen buffer content:

  const GLfloat vVertices[] = { -1.0f, -1.0f, 0.0f,
                                -1.0f,  1.0f, 0.0f,
                                 1.0f, -1.0f, 0.0f,
                                -1.0f,  1.0f, 0.0f,
                                1.0f, -1.0f, 0.0f,
                                1.0f,  1.0f, 0.0f
                              };

  const GLfloat vCoords[]   = {  0.0f,  0.0f, 0.0f,
                                 0.0f,  1.0f, 0.0f,
                                 1.0f,  0.0f, 0.0f,
                                 0.0f,  1.0f, 0.0f,
                                 1.0f,  0.0f, 0.0f,
                                 1.0f,  1.0f, 0.0f
                              };
  glUseProgram ( g_ProgramObject );

These attribute variables are declared in a vertex shader. See the value of g_vShaderStr[] in the preceding code.

  GLint Loc1 = glGetAttribLocation(g_ProgramObject,"vPosition");
  GLint Loc2 = glGetAttribLocation(g_ProgramObject,"vCoords");

  glBindBuffer( GL_ARRAY_BUFFER, 0 );
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
  glVertexAttribPointer(
    Loc1, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
  glVertexAttribPointer(
    Loc2, 3, GL_FLOAT, GL_FALSE, 0, vCoords   );
  glEnableVertexAttribArray( Loc1 );
  glEnableVertexAttribArray( Loc2 );

  glDisable( GL_DEPTH_TEST );
  glDrawArrays( GL_TRIANGLES, 0, 6 );
  glUseProgram( 0 );
  glDisableVertexAttribArray( Loc1 );
  glDisableVertexAttribArray( Loc2 );

We also need a few JNI callbacks. The first one handles the surface size changes, as seen in the following code:

  JNIEXPORT void JNICALLJava_com_packtpub_ndkcookbook_app3_App3Activity_SetSurfaceSize(JNIEnv* env, jclass clazz, int Width, int Height )
  {
    LOGI( "SurfaceSize: %i x %i", Width, Height );
    g_Width  = Width;
    g_Height = Height;
    GLDebug_LoadStaticProgramObject();
    glGenTextures( 1, &g_Texture );
    glBindTexture( GL_TEXTURE_2D, g_Texture );

Disable mip-mapping through the following code:

    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,ImageWidth, ImageHeight, 0, GL_RGBA,GL_UNSIGNED_BYTE, g_FrameBuffer );
  }

The second callback does the actual frame rendering:

  JNIEXPORT void JNICALL Java_com_packtpub_ndkcookbook_app3_App3Activity_DrawFrame( JNIEnv* env, jobject obj )
  {

Invoke our frame rendering callback through the following code:

    OnDrawFrame();

    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, g_Texture );
    glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,ImageWidth, ImageHeight, GL_RGBA,GL_UNSIGNED_BYTE, g_FrameBuffer );
    GLDebug_RenderTriangle();
  }

Going cross platform

The main idea is the possibility of cross-platform development in What You See (on a PC) is What You Get (on a device), when most of the application logic can be developed in a familiar desktop environment like Windows, and it can be built for Android using the NDK whenever necessary.

Getting ready

To perform what we just discussed, we have to implement some sort of abstraction on top of the NDK, POSIX, and Windows API. Such an abstraction should feature at least the following:

  • Ability to render buffer contents on the screen: Our framework should provide the functions to build the contents of an off-screen framebuffer (a 2D array of pixels) to the screen (for Windows we refer to the window as "the screen").
  • Event handling: The framework must be able to process the multi-touch input and virtual/physical key presses (some Android devices, such as the Toshiba AC 100, or the Ouya console, and other gaming devices, have physical buttons), timing events, and asynchronous operation completions.
  • Filesystem, networking, and audio playback: The abstraction layers for these entities need a ton of work to be done by you, so the implementations are presented in Chapter 3, Networking, Chapter 4, Organizing a Virtual Filesystem, and Chapter 5, Cross-platform Audio Streaming.

How to do it...

  1. Let us proceed to write a minimal application for the Windows environment, since we already have the application for Android (for example, App1). A minimalistic Windows GUI application is the one that creates a single window and starts the event loop (see the following example in Win_Min1/main.c):
    #include <windows.h>
    
    LRESULT CALLBACK MyFunc(HWND h, UINT msg, WPARAM w, LPARAM p)
    {
      if(msg == WM_DESTROY) { PostQuitMessage(0); }
      return DefWindowProc(h, msg, w, p);
    }
    
    char WinName[] = "MyWin";
  2. The entry point is different from Android. However, its purpose remains the same— to initialize surface rendering and invoke callbacks:
    int main()
    {
      OnStart();
    
      const char WinName[] = "MyWin";
    
      WNDCLASS wcl;
      memset( &wcl, 0, sizeof( WNDCLASS ) );
      wcl.lpszClassName = WinName;
      wcl.lpfnWndProc = MyFunc;
      wcl.hCursor = LoadCursor( NULL, IDC_ARROW );
    
      if ( !RegisterClass( &wcl ) ) { return 0; }
    
      RECT Rect;
    
      Rect.left = 0;
      Rect.top = 0;
  3. The size of the window client area is predefined as ImageWidth and ImageHeight constants. However, the WinAPI function CreateWindowA() accepts not the size of the client area, but the size of the window, which includes caption, borders, and other decorations. We need to adjust the window rectangle to set the client area to the desired size through the following code:
      Rect.right  = ImageWidth;
      Rect.bottom = ImageHeight;
    
      DWORD dwStyle = WS_OVERLAPPEDWINDOW;
    
      AdjustWindowRect( &Rect, dwStyle, false );
    
      int WinWidth  = Rect.right  - Rect.left;
      int WinHeight = Rect.bottom - Rect.top;
    
      HWND hWnd = CreateWindowA( WinName, "App3", dwStyle,100, 100, WinWidth, WinHeight,0, NULL, NULL, NULL );
      ShowWindow( hWnd, SW_SHOW );
    
      HDC dc = GetDC( hWnd );
  4. Create the offscreen device context and the bitmap, which holds our offscreen framebuffer through the following code:
      hMemDC = CreateCompatibleDC( dc );
      hTmpBmp = CreateCompatibleBitmap( dc,ImageWidth, ImageHeight );
      memset( &BitmapInfo.bmiHeader, 0,sizeof( BITMAPINFOHEADER ) );
      BitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
      BitmapInfo.bmiHeader.biWidth = ImageWidth;
      BitmapInfo.bmiHeader.biHeight = ImageHeight;
      BitmapInfo.bmiHeader.biPlanes = 1;
      BitmapInfo.bmiHeader.biBitCount = 32;
      BitmapInfo.bmiHeader.biSizeImage = ImageWidth*ImageHeight*4;
      UpdateWindow( hWnd );
  5. After the application's window is created, we have to run a typical message loop:
      MSG msg;
      while ( GetMessage( &msg, NULL, 0, 0 ) )
      {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
      }
      …
    }
  6. This program only handles the window destruction event and does not render anything. Compilation of this program is done with a single command as follows:
    >gcc -o main.exe main.c -lgdi32

How it works…

To render a framebuffer on the screen, we need to create a so-called device context with an associated bitmap, and add the WM_PAINT event handler to the window function.

To handle the keyboard and mouse events, we add the WM_KEYUP and WM_MOUSEMOVE cases to the switch statement in the previous program. Actual event handling is performed in the externally provided routines OnKeyUp() and OnMouseMove(), which contain our game logic.

The following is the complete source code of the program (some omitted parts, similar to the previous example, are omitted). The functions OnMouseMove(), OnMouseDown(), and OnMouseUp() accept two integer arguments that store the current coordinates of the mouse pointer. The functions OnKeyUp() and OnKeyDown() accept a single argument—the pressed (or released) key code:

#include <windows.h>

HDC hMemDC;
HBITMAP hTmpBmp;
BITMAPINFO BmpInfo;

In the following code, we store our global RGBA framebuffer:

unsigned char* g_FrameBuffer;

We do all OS-independent frame rendering in this callback. We draw a simple XOR pattern (http://lodev.org/cgtutor/xortexture.html) into the framebuffer as follows:

void DrawFrame()
{
  int x, y;
  for (y = 0 ; y < ImageHeight ; y++)
  {
    for (x = 0 ; x < ImageWidth ; x++)
    {
      int Ofs = y * ImageWidth + x;
      int c = (x ^ y) & 0xFF;
      int RGB = (c<<16) | (c<<8) | (c<<0) | 0xFF000000;
      ( ( unsigned int* )g_FrameBuffer )[ Ofs ] =	RGB;
    }
  }
}

The following code shows the WinAPI window function:

LRESULT CALLBACK MyFunc(HWND h, UINT msg, WPARAM w, LPARAM p)
{
  PAINTSTRUCT ps;
  switch(msg)
  {
  case WM_DESTROY:
    PostQuitMessage(0);
break;
  case WM_KEYUP:
    OnKeyUp(w);
break;
  case WM_KEYDOWN:
    OnKeyDown(w);
break;
  case WM_LBUTTONDOWN:
    SetCapture(h);
    OnMouseDown(x, y);
break;
  case WM_MOUSEMOVE:
    OnMouseMove(x, y);
break;
  case WM_LBUTTONUP:
    OnMouseUp(x, y);
    ReleaseCapture();
break;
  case WM_PAINT:
    dc = BeginPaint(h, &ps);
    DrawFrame();         

Transfer the g_FrameBuffer to the bitmap through the following code:

    SetDIBits(hMemDC, hTmpBmp, 0, Height,g_FrameBuffer, &BmpInfo, DIB_RGB_COLORS);
    SelectObject(hMemDC, hTmpBmp);

And copy it to the window surface through the following code:

    BitBlt(dc, 0, 0, Width, Height, hMemDC, 0, 0, SRCCOPY);
    EndPaint(h, &ps);
break;
  }
  return DefWindowProc(h, msg, w, p);
}

Since our project contains a make file the compilation can be done via a single command:

>make all

Running this program should produce the result as shown in the following screenshot, which shows the Win_Min2 example running on Windows:

How it works…

There's more…

The main difference between the Android and Windows implementation of a main loop can be summarized in the following way. In Windows, we are in control of the main loop. We literally declare a loop, which pulls messages from the system, handles input, updates the game state, and render s the frame (marked green in the following figure). Each stage invokes an appropriate callback from our portable game (denoted with blue color in the following figure). On the contrary, the Android part works entirely differently. The main loop is moved away from the native code and lives inside the Java Activity and GLSurfaceView classes. It invokes the JNI callbacks that we implement in our wrapper native library (shown in red). The native wrapper invokes our portable game callbacks. Let's summarize it in the following way:

There's more…

The rest of the book is centered on this kind of architecture and the game functionality will be implemented inside these portable On...() callbacks.

There is yet another important note. Responding to timer events to create animation can be done on Windows with the SetTimer() call and the WM_TIMER message handler. We get to that in Chapter 2, Porting Common Libraries, when we speak about rigid body physics simulations. However, it is much better to organize a fixed time-step main loop, which is explained later in the book.

See also

  • Chapter 6, Unifying OpenGL ES 3 and OpenGL 3
  • The recipe Implementing the main loop in Chapter 8, Writing a Match-3 Game

Unifying the cross-platform code

Right now, we have two different versions of a simple program (Win_Min2 and App3). Let us see how to unify the common parts of the code.

Getting ready

In Android, the application initialization phase is different, and since we use a mixed Java plus C++ approach, the entry points will be different. In C++, we are tied to, int main() or DWORD WinMain() functions; whereas in Android it is up to us to choose which JNI function we may call from our Java starter code. Event handling and rendering the initialization code are also quite different, too. To do so, we mark sections of the code with pre-processor definitions and put the different OS code into different files—Wrappers_Android.h and Wrappers_Windows.h.

How to do it...

We use the standard macros to detect the OS for which the program is being compiled: Windows-targeted compilers provide the _WIN32 symbol definition, and the __linux__ macro is defined on any Linux-based OS, including Android. However, the __linux__ defination is not enough, since some of the APIs are missing in Android. The macro ANDROID is a non-standard macro and we pass the -DANDROID switch to our compiler to identify the Android target in our C++ code. To make this for every source file, we modify the CFLAGS variable in the Android.mk file.

Finally, when we write the low-level code, the detection looks like the following code:

#if defined(_WIN32)
// windows-specific code
#elif defined(ANDROID)
// android-specific code
#endif

For example, to make an entry point look the same for both the Android and Windows versions, we write the following code:

#if defined(_WIN32)
#  define APP_ENTRY_POINT()  int main()
#elif defined(ANDROID)
#  define APP_ENTRY_POINT() int App_Init()
#endif

Later we will replace the int main() definition with the APP_ENTRY_POINT() macro.

There's more...

To detect more operating systems, compilers, and CPU architectures, it is useful to check out a list of predefined macros at http://predef.sourceforge.net.

Linking and source code organization

In the previous recipes, we learned how to create basic wrappers that allow us to run our application on Android and Windows. However, we used an ad-hoc approach since the amount of source code was low and fit into a single file. We have to organize our project source files in a way suitable for building the code for larger projects in Windows and Android.

Getting ready

Recall the folder structure of the App3 project. We have the src and jni folders inside our App2 folder. The jni/Android.mk, jni/Application.mk, and build.xml files specify the Android build process. To enable the Windows executable creation, we add a file named Makefile, which references the main.cpp file.

How to do it...

The following is the content of Makefile:

CC = gcc
all:
  $(CC) -o main.exe main.cpp -lgdi32 -lstdc++

The idea is that when we add more and more OS-independent logic, the code resides in .cpp files, which do not reference any OS-specific headers or libraries. For the first few chapters, this simple framework that delegates frame rendering and event handling to portable OS-independent functions (OnDrawFrame(), OnKeyUp() and so on) is enough.

How it works...

All of our examples from the subsequent chapters are buildable for Windows from the command line using a single make all command. Android native code is buildable with a single ndk-build command. We will use this convention throughout the rest of the book.

Signing release Android applications

Now we can create a cross-platform application, debug it on a PC, and deploy it to Android devices. We cannot, however, upload it on Google Play because it is not (yet) signed properly with the release key.

Getting ready

A detailed explanation of the signing procedure on Android is given in the developer manual at http://developer.android.com/tools/publishing/app-signing.html. We will focus on the signing from the command line and automating the entire process via batch files.

How to do it...

First of all, we need to rebuild the project and create a release version of the .apk package. Let's do it with our App2 project:

>ndk-build -B
>ant release

You should see a lot of text output from Ant, which ends with something like the following command:

-release-nosign:
[echo] No key.store and key.alias properties found in build.properties.
[echo] Please sign App2\bin\App2-release-unsigned.apk manually
[echo] and run zipalign from the Android SDK tools.

Let us generate a self-signed release key using keytool from the JDK through the following command:

>keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

Fill out all the fields necessary for the key, as in the following command:

Enter keystore password:
Re-enter new password:
What is your first and last name?
  [Unknown]:  Sergey Kosarevsky
What is the name of your organizational unit?
  [Unknown]:  SD
What is the name of your organization?
  [Unknown]:  Linderdaum
What is the name of your City or Locality?
  [Unknown]:  St.Petersburg
What is the name of your State or Province?
  [Unknown]:  Kolpino
What is the two-letter country code for this unit?
  [Unknown]:  RU
Is CN=Sergey Kosarevsky, OU=SD, O=Linderdaum, L=St.Petersburg, ST=Kolpino, C=RU correct?
  [no]:  yes

Generating 2048 bit RSA key pair and self-signed certificate (SHA1withRSA) with a validity of 10000 days
        for: CN=Sergey Kosarevsky, OU=SD, O=Linderdaum, L=St.Petersburg, ST=Kolpino, C=RU
Enter key password for <alias_name>
        (RETURN if same as keystore password):
[Storing my-release-key.keystore]

Now we are ready to proceed with the actual application signing. Use the jarsigner tool from the JDK through the following code:

>jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore bin\App2-release-unsigned.apk alias_name

This command is interactive, and it will require the user to enter the keystore password and the key password. However, we can provide passwords in a batch file in the following way:

>jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore -storepass 123456 –keypass 123456 bin\App2-release-unsigned.apk alias_name

Passwords should match what you entered while creating your release key and keystore.

There is one more step left before we can safely publish our .apk package on Google Play. Android applications can access uncompressed content within .apk using mmap() calls. Yet, mmap() may imply some alignment restrictions on the underlying data. We need to align all uncompressed data within .apk on 4-byte boundaries. Android SDK has the zipalign tool to do it, as seen in the following command:

>zipalign -v 4 bin\App2-release-unsigned.apk App2-release.apk

Now our .apk is ready to be published.

See also

Left arrow icon Right arrow icon

Key benefits

  • Tips and tricks for developing and debugging mobile games on your desktop
  • Enhance your applications by writing multithreaded code for audio playback, network access, and asynchronous resource loading
  • Enhance your game development skills by using modern OpenGL ES and develop applications without using an IDE
  • Features two ready-to-run Android games

Description

Android NDK is used for multimedia applications which require direct access to a system's resources. Android NDK is also the key for portability, which in turn provides a reasonably comfortable development and debugging process using familiar tools such as GCC and Clang toolchains. If your wish to build Android games using this amazing framework, then this book is a must-have.This book provides you with a number of clear step-by-step recipes which will help you to start developing mobile games with Android NDK and boost your productivity debugging them on your computer. This book will also provide you with new ways of working as well as some useful tips and tricks that will demonstrably increase your development speed and efficiency.This book will take you through a number of easy-to-follow recipes that will help you to take advantage of the Android NDK as well as some popular C++ libraries. It presents Android application development in C++ and shows you how to create a complete gaming application. You will learn how to write portable multithreaded C++ code, use HTTP networking, play audio files, use OpenGL ES, to render high-quality text, and how to recognize user gestures on multi-touch devices. If you want to leverage your C++ skills in mobile development and add performance to your Android applications, then this is the book for you.

Who is this book for?

If you are a C++ developer who wants to jump into the world of Android game development and who wants to use the power of existing C++ libraries in your existing Android Java applications, then this book is for you. You need to have basic knowledge of C or C++ including pointer manipulation, multithreading, and object-oriented programming concepts as well as some experience developing applications without using an IDE.

What you will learn

  • Port popular C++ libraries to Android
  • Write portable multithreaded code
  • Play audio with OpenAL
  • Implement gesture recognition
  • Render text with FreeType
  • Use OpenGL ES to port and abstract APIs from the game code to develop games on a desktop PC
  • Debug mobile applications on your desktop
  • Access Flickr and Picasa web services from C++
  • Extract resources from APK archives
  • Develop Android applications without an IDE

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Nov 25, 2013
Length: 320 pages
Edition : 1st
Language : English
ISBN-13 : 9781782167785
Languages :

What do you get with a Packt Subscription?

Free for first 7 days. €18.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing

Product Details

Publication date : Nov 25, 2013
Length: 320 pages
Edition : 1st
Language : English
ISBN-13 : 9781782167785
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 120.97
Android Security Cookbook
€36.99
Android NDK Game Development Cookbook
€41.99
Android Native Development Kit Cookbook
€41.99
Total 120.97 Stars icon

Table of Contents

10 Chapters
1. Establishing a Build Environment Chevron down icon Chevron up icon
2. Porting Common Libraries Chevron down icon Chevron up icon
3. Networking Chevron down icon Chevron up icon
4. Organizing a Virtual Filesystem Chevron down icon Chevron up icon
5. Cross-platform Audio Streaming Chevron down icon Chevron up icon
6. Unifying OpenGL ES 3 and OpenGL 3 Chevron down icon Chevron up icon
7. Cross-platform UI and Input Systems Chevron down icon Chevron up icon
8. Writing a Match-3 Game Chevron down icon Chevron up icon
9. Writing a Picture Puzzle Game Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
(5 Ratings)
5 star 60%
4 star 20%
3 star 0%
2 star 0%
1 star 20%
User Jan 04, 2014
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This is my first book on Android Native Development Kit. I hope you will find it useful and write great games for Android.
Amazon Verified review Amazon
C. Moeller May 01, 2014
Full star icon Full star icon Full star icon Full star icon Full star icon 5
If you’d like to try making games on Android using C++, or want to use a C++ library with your current game, this book would be very helpful for you. The last two chapters especially bring it all together, creating two simpler games, just to demonstrate all the basic techniques needed to make any game (A tetris type game, and a picture puzzle that fetches pictures from the internet, and creates a cool little 3d carousel to display them).This book would be most helpful to someone who either has a C++ background, and wants to create Android games, while trying to avoid Java, or for a current Android Java programmer, who needs or wants higher performance for cpu intensive tasks. The target audience isn’t someone new to programming.Don’t expect it to teach you C++, or in depth game programming, but it will teach you how to create a game using C++ on Android (and on desktop, which is much more time efficient to debug on, and can really help you get your games out faster). From there you could extrapolate, and use the techniques to create any kind of game you like.
Amazon Verified review Amazon
Johnny Aug 23, 2014
Full star icon Full star icon Full star icon Full star icon Full star icon 5
good service
Amazon Verified review Amazon
Ralf Apr 25, 2014
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
The book is as the title suggests a cookbook for developing games using the Android NDK.While I have only skimmed through the chapters, my initial impression is that it covers thebasic building blocks of game development: toolchain setup, compilation of existing libraries,audio, video, user interaction, and sums it up in two chapters where the authors discuss 2basic games.One criticism I have is that personally I found the Windows-specific code to be off-topic,perhaps it would have been more suitable for an appendix chapter.While the book does not seem to go into as much depth as the "Android NDK Beginner's Guide"it does seem like a nice way to jump into NDK game development. The authors certainlyhave a lot of experience to share with someone new to game development of Android.
Amazon Verified review Amazon
xuechjbj Dec 31, 2013
Full star icon Empty star icon Empty star icon Empty star icon Empty star icon 1
accumulating some libraries which want to integate into android. useless.can i refund it? it is first book i regretted.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is included in a Packt subscription? Chevron down icon Chevron up icon

A subscription provides you with full access to view all Packt and licnesed content online, this includes exclusive access to Early Access titles. Depending on the tier chosen you can also earn credits and discounts to use for owning content

How can I cancel my subscription? Chevron down icon Chevron up icon

To cancel your subscription with us simply go to the account page - found in the top right of the page or at https://subscription.packtpub.com/my-account/subscription - From here you will see the ‘cancel subscription’ button in the grey box with your subscription information in.

What are credits? Chevron down icon Chevron up icon

Credits can be earned from reading 40 section of any title within the payment cycle - a month starting from the day of subscription payment. You also earn a Credit every month if you subscribe to our annual or 18 month plans. Credits can be used to buy books DRM free, the same way that you would pay for a book. Your credits can be found in the subscription homepage - subscription.packtpub.com - clicking on ‘the my’ library dropdown and selecting ‘credits’.

What happens if an Early Access Course is cancelled? Chevron down icon Chevron up icon

Projects are rarely cancelled, but sometimes it's unavoidable. If an Early Access course is cancelled or excessively delayed, you can exchange your purchase for another course. For further details, please contact us here.

Where can I send feedback about an Early Access title? Chevron down icon Chevron up icon

If you have any feedback about the product you're reading, or Early Access in general, then please fill out a contact form here and we'll make sure the feedback gets to the right team. 

Can I download the code files for Early Access titles? Chevron down icon Chevron up icon

We try to ensure that all books in Early Access have code available to use, download, and fork on GitHub. This helps us be more agile in the development of the book, and helps keep the often changing code base of new versions and new technologies as up to date as possible. Unfortunately, however, there will be rare cases when it is not possible for us to have downloadable code samples available until publication.

When we publish the book, the code files will also be available to download from the Packt website.

How accurate is the publication date? Chevron down icon Chevron up icon

The publication date is as accurate as we can be at any point in the project. Unfortunately, delays can happen. Often those delays are out of our control, such as changes to the technology code base or delays in the tech release. We do our best to give you an accurate estimate of the publication date at any given time, and as more chapters are delivered, the more accurate the delivery date will become.

How will I know when new chapters are ready? Chevron down icon Chevron up icon

We'll let you know every time there has been an update to a course that you've bought in Early Access. You'll get an email to let you know there has been a new chapter, or a change to a previous chapter. The new chapters are automatically added to your account, so you can also check back there any time you're ready and download or read them online.

I am a Packt subscriber, do I get Early Access? Chevron down icon Chevron up icon

Yes, all Early Access content is fully available through your subscription. You will need to have a paid for or active trial subscription in order to access all titles.

How is Early Access delivered? Chevron down icon Chevron up icon

Early Access is currently only available as a PDF or through our online reader. As we make changes or add new chapters, the files in your Packt account will be updated so you can download them again or view them online immediately.

How do I buy Early Access content? Chevron down icon Chevron up icon

Early Access is a way of us getting our content to you quicker, but the method of buying the Early Access course is still the same. Just find the course you want to buy, go through the check-out steps, and you’ll get a confirmation email from us with information and a link to the relevant Early Access courses.

What is Early Access? Chevron down icon Chevron up icon

Keeping up to date with the latest technology is difficult; new versions, new frameworks, new techniques. This feature gives you a head-start to our content, as it's being created. With Early Access you'll receive each chapter as it's written, and get regular updates throughout the product's development, as well as the final course as soon as it's ready.We created Early Access as a means of giving you the information you need, as soon as it's available. As we go through the process of developing a course, 99% of it can be ready but we can't publish until that last 1% falls in to place. Early Access helps to unlock the potential of our content early, to help you start your learning when you need it most. You not only get access to every chapter as it's delivered, edited, and updated, but you'll also get the finalized, DRM-free product to download in any format you want when it's published. As a member of Packt, you'll also be eligible for our exclusive offers, including a free course every day, and discounts on new and popular titles.