Android is one of the major players in the mobile phone market. Android is a mobile platform that is built on the top of Linux operating system. The native-code support on Android offers endless opportunities to application developers, not limited the functionality that is provided by Android framework. Pro Android C++ with the NDK is an advanced tutorial and professional reference for today's more sophisticated app developers now porting, developing or employing C++ and other native code to integrate into the Android platform to run sophisticated native apps and better performing apps in general. Using a game app case study, this book explores tools for troubleshooting, debugging, analyzing memory issues, unit testing, unit test code coverage, performance measurement, on native applications, as well as integrating the Android NDK toolchain into existing Autoconf, Makefile, CMake, or JAM based build systems. Pro Android C++ with the NDK also covers the following: ยท The Android platform, and getting up to speed with the Android NDK, and exploring the APIs that are provided in native space. An overview of Java Native Interface (JNI), and auto-generating JNI code through Simplified Wrapper and Interface Generator (SWIG). An introduction to Bionic API, native networking. native multithreading, and the C++ Standard Template Library (STL) support. Native graphics and sound using JNI Graphics, OpenGL ES, and OpenSL ES. Debugging and troubleshooting native applications using Logging, GNU Debugger (GDB), Eclipse Debugger, Valgrind, strace, and other tools. Profiling native code using GProf to identify performance bottlenecks, and NEON/SIMD optimization from an advanced perspective, with tips and recommendations.
Author(s): Onur Cinar
Publisher: Apress
Year: 2012
Language: English
Pages: 416
Pro Android C++ with the NDK
Contents at a Glance
Contents
About the Author
About the Technical
Reviewer
Preface
Chapter 1: Getting Started with C++ on Android
Microsoft Windows
Downloading and Installing the Java Development Kit on Windows
Downloading and Installing the Apache ANT on Windows
Downloading and Installing the Android SDK on Windows
Downloading and Installing the Cygwin on Windows
Downloading and Installing the Android NDK on Windows
Downloading and Installing the Eclipse on Windows
Apple Mac OS X
Installing Xcode on Mac
Validating the Java Development Kit on Mac
Validating the Apache ANT on Mac
Validating the GNU Make
Downloading and Installing the Android SDK on Mac
Downloading and Installing the Android NDK on Mac
Downloading and Installing the Eclipse on Mac
Ubuntu Linux
Checking the GNU C Library Version
Enabling the 32-Bit Support on 64-Bit Systems
Downloading and Installing the Java Development Kit on Linux
Downloading and Installing the Apache ANT on Linux
Downloading and Installing the GNU Make on Linux
Downloading and Installing the Android SDK on Linux
Downloading and Installing the Android NDK on Linux
Downloading and Installing the Eclipse on Linux
Downloading and Installing the ADT
Installing the Android Platform Packages
Configuring the Emulator
Summary
Chapter 2: Exploring the Android NDK
Components Provided with the Android NDK
Structure of the Android NDK
Starting with an Example
Specifying the Android NDK Location
Importing the Sample Project
Adding Native Support to Project
Running the Project
Building from the Command Line
Examining the Structure of an Android NDK Project
Build System
Android.mk
Building a Shared Library
Building Multiple Shared Libraries
Building Static Libraries
Sharing Common Modules using Shared Libraries
Sharing Modules between Multiple NDK Projects
Using Prebuilt Libraries
Building Standalone Executable
Other Build System Variables
Other Build System Function Macros
Defining New Variables
Conditional Operations
Application.mk
Using the NDK-Build Script
Troubleshooting Build System Problems
Summary
Chapter 3: Communicating with Native Code using JNI
What is JNI?
Starting with an Example
Declaration of Native Methods
Loading the Shared Libraries
Implementing the Native Methods
C/C++ Header Generator: javah
Running from Command Line
Running from Eclipse IDE
Method Declarations
JNIEnv Interface Pointer
Instance vs. Static Methods
Data Types
Primitive Types
Reference Types
Operations on Reference Types
String Operations
New String
Converting a Java String to C String
Releasing Strings
Array Operations
New Array
Accessing the Array Elements
Operating on a Copy
Operating on Direct Pointer
NIO Operations
New Direct Byte Buffer
Getting the Direct Byte Buffer
Accessing Fields
Getting the Field ID
Getting the Field
Calling Methods
Getting the Method ID
Calling the Method
Field and Method Descriptors
Java Class File Disassembler: javap
Running from Command Line
Running from Eclipse IDE
Exception Handling
Catching Exceptions
Throwing Exceptions
Local and Global References
Local References
Global References
New Global Reference
Deleting a Global Reference
Weak Global References
New Weak Global Reference
Validating a Weak Global Reference
Deleting a Weak Global Reference
Threading
Synchronization
Native Threads
Summary
Chapter 4: Auto-Generate JNI Code Using SWIG
What is SWIG?
Installation
Installing on Windows
Installing on Mac OS X
Installing on Ubuntu Linux
Experimenting with SWIG Through an Example
Interface File
Comments
Module Name
User-Defined Code
Type Definitions
Function Prototypes
Invoking SWIG from Command Line
Java Package for Proxy Classes
Invoking SWIG
Integrating SWIG into Android Build Process
Android Build System Fragment for SWIG
Integrating SWIG into Android.mk
Updating the Activity
Executing the Application
Exploring Generated Code
Wrapping C Code
Global Variables
Constants
Read-Only Variables
Enumerations
Anonymous
Type-Safe
Type-Unsafe
Java Enumerations
Structures
Pointers
Wrapping C++ Code
Pointers, References, and Values
Default Arguments
Overloaded Functions
Classes
Exception Handling
Memory Management
Calling Java from Native Code
Asynchronous Communication
Enabling Directors
Enabling RTTI
Overriding the Callback Method
Updating the HelloJni Activity
Summary
Chapter 5: Logging , Debugging, and Troubleshooting
Logging
Framework
Native Logging APIs
Log Message
Logging Functions
Controlled Logging
Log Wrapper
Adding Logging
Updating Android.mk
Log Tag
Log Level
Applying the Logging Configuration
Observing Log Messages Through Logcat
Console Logging
Debugging
Prerequisites
Debug Session Setup
Setting up the Example for Debugging
Starting the Debugger
Fix for Windows Users
Using Eclipse
The Command Line
Useful GDB Commands
Troubleshooting
Stack Trace Analysis
Extended Checking of JNI
Enabling CheckJNI
Memory Issues
Using Libc Debug Mode
Valgrind
Using the Prebuilt Binaries
Building from Source Code
Deploying Valgrind to Emulator
Valgrind Wrapper
Running Valgrind
Strace
Summary
Chapter 6: Bionic API Primer
Reviewing Standard Libraries
Yet Another C Library?
Binary Compatibility
What is Provided?
What is Missing?
Memory Management
Memory Allocation
Dynamic Memory Management for C
Allocating Dynamic Memory in C
Freeing Dynamic Memory in C
Changing Dynamic Memory Allocation in C
Dynamic Memory Management for C++
Allocating Dynamic Memory in C++
Freeing Dynamic Memory in C++
Changing Dynamic Memory Allocation in C++
Mixing the Memory Functions and the Keywords
Standard File I/O
Standard Streams
Using the Stream I/O
Opening Streams
Writing to Streams
Writing Block of Data to Streams
Writing Character Sequences to Streams
Writing a Single Character to Streams
Writing Formatted Data to Streams
Flushing the Buffer
Reading from Streams
Reading Block of Data from Streams
Reading Character Sequences from Streams
Reading a Single Character from Streams
Reading Formatted Data from Streams
Checking for End of File
Seeking Position
Checking Errors
Closing Streams
Interacting with Processes
Executing a Shell Command
Communicating with the Child Process
System Configuration
Getting a System Property Value by Name
Getting a System Property by Name
Users and Groups
Getting the Application User and Group IDs
Getting the Application User Name
Inter-Process Communication
Summary
Chapter 7: Native Threads
Creating the Threads Example Project
Creating the Android Project
Adding the Native Support
Declaring the String Resources
Creating a Simple User Interface
Implementing the Main Activity
Generating the C/C++ Header File
Implementing the Native Functions
Updating the Android.mk Build Script
Java Threads
Updating the Example Application to use Java Threads
Executing the Java Threads Example
Pros and Cons of using Java Threads for Native Code
POSIX Threads
Using POSIX Threads in Native Code
Creating Threads using pthread_create
Updating the Example Application to use POSIX Threads
Updating the Main Activity
Regenerating the C/C++ Header File for posixThreads Method
Updating the Native Code
Executing the POSIX Threads Example
Return Result from POSIX Threads
Updating the Native Code to Use pthread_join
Synchronizing POSIX Threads
Synchronizing POSIX Threads using Mutexes
Initializing Mutexes
Locking Mutexes
Unlocking Mutexes
Destroying Mutexes
Updating the Example Application to Use a Mutex
Synchronizing POSIX Threads Using Semaphores
Initializing Semaphores
Locking Semaphores
Unlocking Semaphores
Destroying Semaphores
Priority and Scheduling Strategy for POSIX Threads
POSIX Thread Scheduling Strategy
POSIX Thread Priority
Summary
Chapter 8: POSIX Socket API: Connection-Oriented Communication
Echo Socket Example Application
Echo Android Application Project
Abstract Echo Activity
Echo Application String Resources
Native Echo Module
Connection-Oriented Communication through TCP Sockets
Echo Server Activity Layout
Echo Server Activity
Implementing the Native TCP Server
Creating a Socket: socket
Binding the Socket to an Address: bind
Network Byte Ordering
Listen for Incoming Connections: listen
Accepting Incoming Connections: accept
Receiving Data from the Socket: recv
Sending Data to the Socket: send
Native TCP Server Method
Echo Client Activity Layout
Echo Client Activity
Implementing the Native TCP Client
Connect to Address: connect
Native TCP Client Method
Updating the Android Manifest
Running the TCP Sockets Example
Configuring the Echo TCP Server
Interconnecting Emulators for TCP
Configuring the Echo TCP Client
Summary
Chapter 9: POSIX Socket API: Connectionless Communication
Adding Native UDP Server Method to Echo Server Activity
Implementing the Native UDP Server
New UDP Socket: socket
Receive Datagram from Socket: recvfrom
Send Datagram to Socket: sendto
Native UDP Server Method
Adding Native UDP Client Method to Echo Client Activity
Implementing the Native UDP Client
Native UDP Client Method
Running the UDP Sockets Example
Interconnecting the Emulators for UDP
Starting the Echo UDP Client
Summary
Chapter 10: POSIX Socket API: Local Communication
Echo Local Activity Layout
Echo Local Activity
Implementing the Native Local Socket Server
New Local Socket: socket
Bind Local Socket to Name: bind
Accept on Local Socket: accept
Native Local Socket Server
Adding Local Echo Activity to Manifest
Running the Local Sockets Example
Asynchronous I/O
Summary
Chapter 11: C++ Support
Supported C++ Runtimes
GAbi++ C++ Runtime
STLport C++ Runtime
GNU STL C++ Runtime
Specifying the C++ Runtime
Static vs. Shared Runtimes
C++ Exception Support
C++ RTTI Support
C++ Standard Library Primer
Containers
Sequence
Associative Container
Sorted Associative Container
Hashed Associative Container
Adaptors
String
Iterators
Algorithms
Thread Safety of C++ Runtime
C++ Runtime Debug Mode
GNU STL Debug Mode
Using Individual GNU STL Debugging Containers
Enabling GNU STL Debug Mode
STLport Debug Mode
Redirecting Debug Mode Messages to Android Logs
Summary
Chapter 12: Native Graphics API
Availability of Native Graphics API
Creating an AVI Video Player
Make AVILib a NDK Import Module
Create the AVI Player Android Application
Create the AVI Player Main Activity
Creating the Abstract Player Activity
Rendering using JNI Graphics API
Enabling the JNI Graphics API
Using the JNI Graphics API
Retrieving Information about a Bitmap Object
Accessing the Native Pixel Buffer
Releasing the Native Pixel Buffer
Updating AVI Player with Bitmap Renderer
Running the AVI Player with Bitmap Renderer
Rendering Using OpenGL ES
Using the OpenGL ES API
Enabling OpenGL ES 1.x API
Enabling OpenGL ES 2.0 API
Updating AVI Player with OpenGL ES Renderer
Rendering Using Native Window API
Enabling the Native Window API
Using the Native Window API
Retrieving Native Window from a Surface Object
Acquiring a Reference on a Native Window Instance
Releasing the Native Window Reference
Retrieving Native Window Information
Setting the Native Window Buffer Geometry
Accessing the Native Window Buffer
Releasing the Native Window Buffer
Updating AVI Player with Native Window Renderer
EGL Graphics Library
Summary
Chapter 13: Native Sound API
Using the OpenSL ES API
Compatibility with the OpenSL ES Standard
Audio Permissions
Creating the WAVE Audio Player
Make WAVELib a NDK Import Module
Create the WAVE Player Android Application
Creating the WAVE Player Main Activity
Implementing WAVE Audio Playback
Running the WAVE Audio Player
Summary
Chapter 14: Profiling and NEON Optimization
GNU Profiler for Measuring Performance
Installing the Android NDK Profiler
Enabling the Android NDK Profiler
Analyzing gmon.out using GNU Profiler
Optimization using ARM NEON Intrinsics
Overview of ARM NEON Technology
Adding a Brightness Filter to AVI Player
Enabling the Android NDK Profiler for AVI Player
Profiling the AVI Player
Optimizing the Brightness Filter using NEON Intrinsics
Automatic Vectorization
Enabling Automatic Vectorization
Troubleshooting Automatic Vectorization
Summary
Index