Overview
Android provides several native APIs that are specific to the Android platform. These APIs allow you to interact with Android system services, manage app resources, and integrate with the Android runtime.
All Android-specific APIs require linking against their respective libraries. Add them to your build configuration (CMake or ndk-build).
Native Activity
Native Activity allows you to create Android apps entirely in native code without writing Java/Kotlin code.
Key features
Static helper library that simplifies NativeActivity lifecycle management. Recommended for all NativeActivity applications.
API reference
Main application structure containing activity state, window, input queue, and callbacks.
Pointer to the ANativeActivity instance representing the Android activity.
Native window for rendering. NULL when no window is available.
Input event queue for processing touch, key, and motion events.
Code example: Basic NativeActivity
#include <android_native_app_glue.h>
#include <android/log.h>
#define LOG_TAG "NativeActivity"
static void handle_cmd ( struct android_app * app , int32_t cmd ) {
switch (cmd) {
case APP_CMD_INIT_WINDOW:
// Window is being shown, initialize rendering
if (app -> window != NULL ) {
__android_log_print (ANDROID_LOG_INFO, LOG_TAG,
"Window initialized" );
// Initialize graphics here
}
break ;
case APP_CMD_TERM_WINDOW:
// Window is being hidden or closed
__android_log_print (ANDROID_LOG_INFO, LOG_TAG,
"Window terminated" );
// Cleanup graphics here
break ;
case APP_CMD_GAINED_FOCUS:
// App gained focus, resume rendering
break ;
case APP_CMD_LOST_FOCUS:
// App lost focus, pause rendering
break ;
}
}
static int32_t handle_input ( struct android_app * app , AInputEvent * event ) {
if ( AInputEvent_getType (event) == AINPUT_EVENT_TYPE_MOTION) {
float x = AMotionEvent_getX (event, 0 );
float y = AMotionEvent_getY (event, 0 );
__android_log_print (ANDROID_LOG_INFO, LOG_TAG,
"Touch at %.2f , %.2f " , x, y);
return 1 ; // Event handled
}
return 0 ; // Event not handled
}
void android_main ( struct android_app * app ) {
app -> onAppCmd = handle_cmd;
app -> onInputEvent = handle_input;
__android_log_print (ANDROID_LOG_INFO, LOG_TAG, "App started" );
// Main loop
while ( 1 ) {
int events;
struct android_poll_source * source;
// Poll for events
while ( ALooper_pollAll ( 0 , NULL , & events, ( void ** ) & source) >= 0 ) {
if (source != NULL ) {
source -> process (app, source);
}
if ( app -> destroyRequested != 0 ) {
__android_log_print (ANDROID_LOG_INFO, LOG_TAG, "App destroyed" );
return ;
}
}
// Render frame here
}
}
CMake configuration
# Link against native_app_glue and android libraries
target_link_libraries ( ${CMAKE_PROJECT_NAME}
android
native_app_glue
log
)
Asset Manager
The Asset Manager API allows you to access files packaged in your app’s APK.
API reference
Manager object for accessing assets. Obtained from ANativeActivity.
Represents an open asset file. Use for reading asset contents.
Code example: Reading assets
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/log.h>
#define LOG_TAG "AssetManager"
void load_asset (AAssetManager * mgr , const char * filename ) {
// Open the asset
AAsset * asset = AAssetManager_open (mgr, filename, AASSET_MODE_BUFFER);
if (asset == NULL ) {
__android_log_print (ANDROID_LOG_ERROR, LOG_TAG,
"Failed to open asset: %s " , filename);
return ;
}
// Get asset size
off_t size = AAsset_getLength (asset);
__android_log_print (ANDROID_LOG_INFO, LOG_TAG,
"Asset %s size: %ld bytes" , filename, size);
// Read asset into buffer
char * buffer = ( char * ) malloc (size + 1 );
int bytes_read = AAsset_read (asset, buffer, size);
buffer [size] = ' \0 ' ; // Null terminate if text
if (bytes_read > 0 ) {
__android_log_print (ANDROID_LOG_INFO, LOG_TAG,
"Read %d bytes from %s " , bytes_read, filename);
// Use the buffer...
}
// Cleanup
free (buffer);
AAsset_close (asset);
}
// In NativeActivity context
void load_assets_from_activity ( struct android_app * app ) {
AAssetManager * mgr = app -> activity -> assetManager ;
load_asset (mgr, "config.json" );
load_asset (mgr, "textures/sprite.png" );
}
Asset access modes
Mode Description Use Case AASSET_MODE_UNKNOWNNo specific access mode Default AASSET_MODE_RANDOMRandom access Seeking within file AASSET_MODE_STREAMINGSequential access Reading file once AASSET_MODE_BUFFEREntire file in memory Fast access, small files
Logging
The Android logging API provides native logging that integrates with logcat.
API reference
Formatted logging function similar to printf. Most commonly used logging function.
Simple logging function for unformatted messages.
Log levels
Verbose logging. Typically compiled out in release builds.
Debug logging. Use for development and debugging.
Informational messages. Use for normal operation messages.
Warning messages. Use for potential issues.
Error messages. Use for error conditions.
Fatal error messages. Use for critical failures.
Code example: Logging utilities
#include <android/log.h>
#define LOG_TAG "MyApp"
// Convenience macros
#define LOGV (...) __android_log_print (ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__ )
#define LOGD (...) __android_log_print (ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__ )
#define LOGI (...) __android_log_print (ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__ )
#define LOGW (...) __android_log_print (ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__ )
#define LOGE (...) __android_log_print (ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__ )
void example_logging () {
int user_id = 1234 ;
const char * username = "john_doe" ;
LOGI ( "User logged in: %s (ID: %d )" , username, user_id);
LOGW ( "Memory usage: %.2f%% " , 85.5 );
LOGE ( "Failed to connect to server: %s " , "Connection timeout" );
}
// Assert-style logging
#define ASSERT_LOG ( condition , ...) \
if ( ! (condition)) { \
LOGE ( __VA_ARGS__ ); \
abort (); \
}
void example_assert () {
void * ptr = malloc ( 1024 );
ASSERT_LOG (ptr != NULL , "Memory allocation failed" );
// Use ptr...
free (ptr);
}
CMake configuration
# Link against log library
target_link_libraries ( ${CMAKE_PROJECT_NAME}
log
)
Storage Access Framework
Access files through Android’s Storage Access Framework (SAF) using file descriptors.
Direct file system access is restricted on Android 10 (API 29) and higher. Use SAF or app-specific directories.
Code example: Working with file descriptors
#include <android/asset_manager.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
// File descriptor obtained from Java layer via SAF
void read_from_fd ( int fd ) {
struct stat stat_buf;
if ( fstat (fd, & stat_buf) == 0 ) {
off_t size = stat_buf . st_size ;
char * buffer = ( char * ) malloc (size);
ssize_t bytes_read = read (fd, buffer, size);
if (bytes_read > 0 ) {
// Process the data
}
free (buffer);
}
close (fd);
}
Configuration and System Info
Access device configuration and system information.
Code example: Device configuration
#include <android/configuration.h>
#include <android/native_activity.h>
void get_device_info (ANativeActivity * activity ) {
AConfiguration * config = AConfiguration_new ();
AConfiguration_fromAssetManager (config, activity -> assetManager );
// Get screen density
int32_t density = AConfiguration_getDensity (config);
LOGI ( "Screen density: %d dpi" , density);
// Get screen size
int32_t screen_size = AConfiguration_getScreenSize (config);
const char * size_name [] = {
"small" , "normal" , "large" , "xlarge"
};
LOGI ( "Screen size: %s " , size_name [screen_size - 1 ]);
// Get orientation
int32_t orientation = AConfiguration_getOrientation (config);
LOGI ( "Orientation: %s " ,
orientation == ACONFIGURATION_ORIENTATION_PORT ? "portrait" : "landscape" );
// Get language
char lang [ 3 ] = { 0 };
AConfiguration_getLanguage (config, lang);
LOGI ( "Language: %s " , lang);
AConfiguration_delete (config);
}
Additional Android-specific APIs
Access and share hardware graphics buffers for efficient rendering. Available from API 26+. Used for Vulkan, OpenGL ES interop, and camera integration.
Synchronize rendering with display refresh rate. Available from API 24+. Essential for smooth animations and game loops.
Add native trace events visible in Android Studio Profiler. Available from API 23+. Critical for performance profiling.
Manipulate Android Bitmap objects from native code. Available from API 8+. Useful for image processing.
Library reference
Android-specific libraries to link in your build configuration:
Library Purpose Header androidNative Activity, Configuration, etc. <android/*.h>logLogging to logcat <android/log.h>native_app_glueNativeActivity helper (static) <android_native_app_glue.h>jnigraphicsBitmap access <android/bitmap.h>
Next steps
Bionic status Check POSIX compliance and available C library functions
Platform APIs Learn about platform API availability and compatibility
Graphics guide OpenGL ES and Vulkan rendering
Audio guide High-performance audio with AAudio