Configuring Android Studio for Native (C/C++) Development with Java Support

All, Game & Software Engineering, Game Development
Configuring Android Studio for Native (C/C++) Development with Java Support

After setting up the Android development environment then it is time to start development of your game, UFO Tap Attack. Within a few minutes working with this tutorial you will become a master of setting up Android Studio for native (C/C++) development with Java support.

You might be able to put together a game that is not native, without this material. However, at great cost to process efficiency and portability of your game to other platforms such as Apple’s iPhone and iPad.

 Starting an Android Project

To begin, launch Android Studio. If this is the first time launching Android Studio then a dialog box will appear, titled “Welcome to Android Studio”. Within the dialog box select the option “Select a new Android Studio project”. The selection will start a wizard for configuring a new project.

The first step in the wizard is configuring the application’s name and ownership. Please, fill in the dialog. The dialog should look similar to the following. Be sure the app’s name is UFOTapAttack and check the check-box “Include C++ Support”.

New UFO Tap Attack Project

The next step of the wizard calls for the selection of the minimum Application Programming Interface (API) that your source-code will  interface with. For UFO Tap Attack please select API 19.

The selection will capture (currently) 73.9% of the devices that are active with Google Play Store.  You really don’t want to capture more than 80% of the active devices, because you will also want to use a more up to date API in your software development.

Minimum API selection

After configuring the set of targeted Android devices then the next step is configuring the desired Android Activity. An activity is the interface between the user or a third-party app/game/library and your app/game. For example, we will use the Java activity class NativeActivity to interface the native C++ code of UFO Tap Attack to Android’s API Java library. Another typical example of an activity is the activity class that takes care of creating a window that will be an interface between the user and your app/game.

As seen in the image below, please select a blank Activity within the wizard.

Add an activity

 Following the creation of your game’s activity, the wizard’s next step is to configure the activity. For UFO Tap Attack, you can leave the name of the activity as MainActivity. Also, if checked, then please uncheck the check-boxes “Generate Layout File” and “Backwards Compatibility (AppCompat)”, as seen below.

Naming UFO Tap Attack's activity

To finish up the wizard, the last step is selecting the level of C++ support, as seen below. UFO Tap Attack will use some C++ 11 features, so please select from the combo-box C++ standard C++11.

Choosing the C++ standards for UFO Tap Attack

Configuring the NDK

After completing the wizard, the interactive development environment (IDE) will appear. At the bottom of the IDE, you should see the following message within the Messages tab.

NDK not configured. Download it with SDK manager.

To fix the error message and to configure the NDK, start by going to the file-menu and select Tools – Android – SDK Manager. As a result, a dialog box will appear, titled Default Settings. Within the tree-menu on the left of the dialog, please select Appearance & Behavior – System Setting – Android SDK and then select within the SDK Tools tab CMake, LLDB and NDK to install, as seen below.

NDK Support

CMake is the compiler used by Android Studio to compile the C/C++ source-code into the binary (machine) code and LLDB or low- level debugger is the debugger used to debug the C/C++ source-code. The NDK or the native development kit is the C/C++ libraries and Java source-code that your game will use for native development. The NDK bridges the communications of the binaries (built from UFO Tap Attack), the Java intermediate-code and the Android OS during run-time of the game.

After installing the tools, you will need to restart Android Studio.

Writing your first bit of Source-Code

To begin, within the project explorer please select (if not already selected) Android from the combo-box, above the explorer window. Then within the explorer window expand the tree to app/java/com.yourcompany.ufotapattack. Afterwards, double-click on the file MainActivity to open the file within the editor.

Selecting Main Activity

Replace the contents of MainActivity with the source-code outlined below.

package com.raginggazebo.ufotapattack;
import android.app.NativeActivity;
import android.os.Bundle;

////////////////////////////////////////////////////////////////////////////////
// The class outlines the UFO Tap Attack native activity.  2016/11/23 DK
public class MainActivity extends NativeActivity
{
  /////////////////////////////////////////////////////////////////////////////
  // The activity's on create.  2016/11/23 DK
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

  } // End of public void onCreate(Bundle savedInstanceState)

} // End of public class MainActivity extends NativeActivity

MainActivity is your Java interface to your C++ source-code. It will handle function calls such as opening an internet browser window. The activity derives from (extends from) NativeActivity which derives from Android’s base activity, Activity. MainActivity is also the place where you will interface with other java libraries such as AdMob and Appodeal.

The next step, is to remove file native-lib.cpp from the folder app/cpp.  Please, perform a right mouse click on the file followed by selecting from the drop-down menu Delete, as seen below.

Deleting Nativelib.cpp

After removing the file then replace it with Main.cpp, as seen below.

Creating Main.cpp

Main.cpp will appear within the editor, with the following warning. Also, note the file did not appear within the explorer, but the warning will disappear and the file will appear under the cpp folder when you add the file to CMakeLists.txt, which you will do later within this post.

Replace the Main.cpp contents with the following source-code, outlined below.

// Main.cpp

#include <android_native_app_glue.h>
#include <android/log.h>

////////////////////////////////////////////////////////////////////////////////
// The main entry into the game.  2016/06/30 DK
void android_main(
  android_app *pstDroidAPI) // The pointer's allocated memory helps manage the
                            // interface between the Android OS and this game
{
  // The function call prevents the linker from
  // stripping out the native glue library
  app_dummy();

  for(uint8_t ui = 0; ui < 100; ++ui)
  {
    // The function prints to log cat the index of the for loop
    __android_log_print(
      ANDROID_LOG_INFO,
      "UFO Tap Attack",
      " -- CUFOTapAttack::android_main(), ui == %d \n",
      ui);

  } // End of for(uint8_t ui = 0; ui < 100; ++ui)

} // End of void android_main()

The above source-code is straight forward. The main entry into the game is void android_main(android_app *pstDroidAPI) and is like void main() or int main() from our traditional C/C++ entry points. However, void android_main(android_app *pstDroidAPI) is not called directly from the OS, but instead is called from NativeActivity.

The function app_dummy() is declared in android_native_app_glue.h. The empty function prevents the linker from stripping out important constants, enumerations and other items from the Android defined source-code.

The function __android_log_print() is like printf(), but instead of printing to the console, the messages are printed to a logging system called LogCat.

Configuring the Game’s Properties and Build Process

To begin, please open the file AndroidManifest.xml, located in the folder app/manifests, within the project’s explorer; and copy the following XML code.

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.raginggazebo.ufotapattack" >

  <application
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.NoTitleBar.Fullscreen">

    <activity
      android:name=".MainActivity"
      android:screenOrientation="portrait">

      <meta-data
        android:name="android.app.lib_name"
        android:value="native-lib" />

      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>
</manifest>

The Android manifest outlines the game’s properties such as how the OS will call the game; how the user will see the display of the game and how it will interact with the Android OS. The above manifest outlines that your game does not require the adb to backup its data.  The manifest also outlines that the game will display in portrait mode and has a native library called native-lib.

The next step is the modification of the file CMakeLists.txt located in the folder External Build Files. Please replace the contents of the file, with outlined text, below.

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             app-glue

             # Sets the library as a shared library.
             STATIC

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/Main.cpp )

# Specifies a path to native header files.
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
                    ${ANDROID_NDK}/sources/android/native_app_glue/ )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( native-lib
                       app-glue
                       android
                       ${log-lib} )

The file commands the compiler to build the NDK’s app-glue source-code into a static library and your game’s source code into a shared library. The file also commands the linker to link into your game the app-glue static library (that was just compiled) and the Android library, as well as the log-lib library.

The app-glue source-code is part of the NDK and is used to “glue” the C/C++ and the Android Java source-code. While the log-lib library is used for debugging your game by logging items to LogCat (Android Studio’s logging system).

The last step (if it is not already listed in the file) is to enable the standard C++11 libraries for our game by opening the Module’s gradle, located in Gradle Scripts/gradle.build (Module: app) and adding to cppFlags the flag “-std=c++11” located in the gradle block android/defaultConfig/externalNativeBuild/cmake.

After the modifying the flag, click on the Sync Now option (if there), at the top right hand corner of your editor window.

Sync Now

Please note, after syncing the project your project explorer should look similar to the following, revealing the C/C++ libraries.

Project Window updated

Modifying the Launcher Icons

This step isn’t necessary for the operation of the game. However, if desired you can modify the launcher icons in the folder $Project_Folder/app/src/main/res. The launcher icons are in the folders labeled mipmap-*, within the res folder, as seen below. Each mipmap folder contains one icon for each size of device your game will support.

mipmap folder location

For your convince, the following zip files contain the launcher icons that were developed for UFO Tap Attack.

mipmap.zip

Compiling and Running the Game

To build the project either go to the file-menu and select Build – Make Project or by pressing the keys Ctrl+F9. To bring up the window to see the progress of your build, click on the button Gradle Console in the lower right-hand corner of the IDE.

Gradle Console

Next, please start an Android Virtual Device (AVD) to test your game, by simply clicking the green “play” button at the top-center of the IDE or by pressing the keys Shift+F10. After doing so, the following dialog should appear. Within the dialog click the Create New Virtual Device button, to start configuring the emulator.

No AVD

The first step in the wizard is selecting the Android device that you wish to test your game with. Please select the Nexus S, as seen below.

Android virtual device configuration

The next step within the wizard is selecting the AVD’s system image. Please select the tab Other Images, so that you have access to the Android KitKat OS and then please select that.

Choosing system image

The final step of the wizard is the configuration and the naming of the AVD. Within in this dialog, please leave the default settings, as seen below.

Naming and configuring the AVD

After you have completed setting up the wizard, you will see in the Select Deployment Target dialog the AVD that was just created by the wizard. Hence, all you have to do is simply click the OK button.

Select deployment method

After clicking the OK button, the emulator will start. It may take a while to boot (go make a sand-which) and you may even get a warning message detailing that it is faster to choose a different emulator. However, the emulator that you just built is the minimum targeted device that your game will run on and the device we should test the game with, at least to begin with.

To see the result of the game open the app’s message box (LogCat) at the bottom left of the IDE.

Print out

Congratulations!! You have mastered the configuration and setup of a native C/C++ Android application/game! You now have a talent that will help you stick out among the Android app/game development community.

Please visit our next post in this tutorial series, How to build UFO Tap Attack’s framework.

Thank you for reading our material and I hope you have enjoyed it. Please keep us funded by either donating with PayPal or through our Patreon site.

If you have any questions and/or comments, please leave them below.

The post’s source-code.

Please, keep your comments family friendly and respectful of each other and the author.