Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Android Project Setup

This guide covers setting up an Android Blinc project — toolchain, build commands, and the platform-specific files (AndroidManifest.xml, Gradle config, debugging).

For the cross-platform Blinc API (native bridge, camera, deep linking, lifecycle, etc.), see the Mobile Development overview.

Prerequisites

1. Android SDK & NDK

# macOS
brew install --cask android-studio

export ANDROID_HOME=$HOME/Library/Android/sdk
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/26.1.10909125
export PATH=$PATH:$ANDROID_HOME/platform-tools

2. Rust Targets

rustup target add aarch64-linux-android
rustup target add armv7-linux-androideabi
rustup target add x86_64-linux-android
cargo install cargo-ndk

Building

# Debug — single arch
cargo ndk -t arm64-v8a build

# Release — multi-arch
cargo ndk -t arm64-v8a -t armeabi-v7a build --release

# Or via Gradle (from platforms/android/)
./gradlew assembleDebug

The APK lands in app/build/outputs/apk/debug/app-debug.apk.

Project Configuration

Cargo.toml

[lib]
name = "my_app"
crate-type = ["cdylib", "staticlib"]

[target.'cfg(target_os = "android")'.dependencies]
blinc_app = { version = "0.5", features = ["android"] }
blinc_platform_android = "0.5"
android-activity = { version = "0.6", features = ["native-activity"] }
log = "0.4"
android_logger = "0.14"

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-feature android:glEsVersion="0x00030000" android:required="true" />

    <!-- Permissions for native bridge features -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:label="My App"
        android:theme="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"
        android:hardwareAccelerated="true">

        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:exported="true"
            android:launchMode="singleTask">

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

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

            <!-- Deep link: myapp://path/to/route -->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="myapp" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Debugging

# View Rust logs
adb logcat | grep -E "(blinc|BlincApp)"

# Filter for native bridge calls
adb logcat | grep BlincNativeBridge

Common Issues

“Library not found” — ensure the native library is built and copied to app/src/main/jniLibs/<arch>/:

cargo ndk -t arm64-v8a build
cp target/aarch64-linux-android/debug/libmy_app.so \
   platforms/android/app/src/main/jniLibs/arm64-v8a/

“Vulkan not supported” — check device capability:

adb shell getprop ro.hardware.vulkan

API 24+ devices generally support Vulkan, but some emulators may not.

“Native call failed” — verify the namespace+name matches between Kotlin and Rust handlers. Check logcat for BlincNativeBridge: handler not found for X.Y.

Touch events not working — verify the render context is created successfully and android.app.lib_name in the manifest matches your library name.

Performance

[profile.release]
lto = "fat"
opt-level = "z"      # optimize for size on mobile
panic = "abort"
strip = true
codegen-units = 1
  • Test on real devices — emulators have different GPU characteristics
  • Profile with Android Studio Profiler for CPU/GPU/memory
  • Bundle assets via assets/AndroidAssetLoader auto-resolves them through the platform AssetLoader trait

Next Steps