This document contains all the necessary Android configuration files for the NativeBridge app.
NativeBridge/
├── android/
│ ├── app/
│ │ ├── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── nativebridge/
│ │ │ │ └── io/
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── MainApplication.kt
│ │ │ ├── res/
│ │ │ │ ├── values/
│ │ │ │ │ └── strings.xml
│ │ │ │ └── xml/
│ │ │ │ └── network_security_config.xml
│ │ │ └── AndroidManifest.xml
│ │ └── build.gradle
│ ├── gradle.properties
│ └── build.gradle
Location: android/app/src/main/java/com/nativebridge/io/MainActivity.kt
package com.nativebridge.io
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
class MainActivity : ReactActivity() {
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
override fun getMainComponentName(): String = "NativeBridge"
/**
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}Key Points:
- Package name:
com.nativebridge.io - Main component name:
NativeBridge(must match app name in package.json) - Uses React Native 0.74.7 New Architecture delegates
Location: android/app/src/main/java/com/nativebridge/io/MainApplication.kt
package com.nativebridge.io
import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.soloader.SoLoader
class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here
}
override fun getJSMainModuleName(): String = "index"
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
override val reactHost: ReactHost
get() = getDefaultReactHost(applicationContext, reactNativeHost)
override fun onCreate() {
super.onCreate()
SoLoader.init(this, false)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()
}
}
}Key Points:
- Package name:
com.nativebridge.io - Supports New Architecture (React Native 0.74.7)
- Auto-links all React Native packages
- Hermes enabled by default
Location: android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Biometric Permissions -->
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<!-- Camera Permission (for QR scanning) -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- Storage Permissions -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Network Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Location Permissions (for permission testing) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Contacts Permission (for permission testing) -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- Vibration Permission -->
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>Key Permissions:
USE_BIOMETRICandUSE_FINGERPRINT: Required for biometric authenticationCAMERA: For QR code scanningREAD/WRITE_EXTERNAL_STORAGE: For file operationsINTERNETandACCESS_NETWORK_STATE: For network operationsACCESS_FINE_LOCATION: For location permission testingREAD_CONTACTS: For contacts permission testingVIBRATE: For vibration feature
Key Application Settings:
usesCleartextTraffic="true": Allows HTTP connections (for testing)networkSecurityConfig: References custom network security configscreenOrientation="portrait": Locks app to portrait modeandroid:exported="true": Required for launcher activity (Android 12+)
Location: android/app/build.gradle
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
react {
/* Folders */
root = file("../")
reactNativeDir = file("../node_modules/react-native")
codegenDir = file("../node_modules/@react-native/codegen")
cliFile = file("../node_modules/react-native/cli.js")
/* Variants */
debuggableVariants = ["liteDebug", "prodDebug"]
/* Bundling */
nodeExecutableAndArgs = ["node"]
bundleCommand = "ram-bundle"
bundleConfig = file(../rn-cli.config.js)
bundleAssetName = "MyApplication.android.bundle"
entryFile = file("../js/MyApplication.android.js")
extraPackagerArgs = []
/* Hermes Commands */
hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
hermesFlags = ["-O", "-output-source-map"]
}
/**
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
*/
def enableProguardInReleaseBuilds = false
/**
* The preferred build flavor of JavaScriptCore (JSC)
*/
def jscFlavor = 'org.webkit:android-jsc:+'
android {
ndkVersion rootProject.ext.ndkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion
namespace "com.nativebridge.io"
defaultConfig {
applicationId "com.nativebridge.io"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0.0"
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
}
dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("com.facebook.react:flipper-integration")
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
}Key Configuration:
namespace:com.nativebridge.ioapplicationId:com.nativebridge.io(must be unique on device)versionCode: 1 (increment for each release)versionName: "1.0.0"- Hermes engine enabled by default
- Debug signing config included for testing
Location: android/app/src/main/res/values/strings.xml
<resources>
<string name="app_name">NativeBridge</string>
</resources>Purpose: Defines the app name shown in launcher and system UI.
Location: android/app/src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- Allow cleartext traffic for all domains (development/testing only) -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
<!-- For production, you should specify specific domains instead -->
<!--
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">example.com</domain>
</domain-config>
-->
</network-security-config>Purpose:
- Allows HTTP connections for testing
- For production, restrict to specific domains only
- Trusts both system and user certificates
Security Note: In production apps, you should only allow HTTPS and specify explicit domains.
Location: android/gradle.properties
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.182.0
# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using
# ./gradlew <task> -PreactNativeArchitectures=x86_64
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# Use this property to enable support to the new architecture.
# This will allow you to use TurboModules and the Fabric render in
# your application. You should enable this flag either if you want
# to write custom TurboModules/Fabric components OR use libraries that
# are providing them.
newArchEnabled=false
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=trueKey Settings:
android.useAndroidX=true: Uses AndroidX librariesnewArchEnabled=false: Disable New Architecture (can enable later)hermesEnabled=true: Use Hermes JavaScript enginereactNativeArchitectures: Build for all architectures (arm, x86)
Location: android/build.gradle
buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 23
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "26.1.10909125"
kotlinVersion = "1.9.22"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.1.4")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
allprojects {
repositories {
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
google()
mavenCentral()
maven { url 'https://www.jitpack.io' }
}
}Key Versions:
minSdkVersion = 23: Android 6.0+ (required for biometric support)compileSdkVersion = 34: Android 14targetSdkVersion = 34: Android 14kotlinVersion = "1.9.22": Latest Kotlin version- Android Gradle Plugin: 8.1.4
Repositories:
- Google Maven (for AndroidX)
- Maven Central
- JitPack (for some React Native libraries)
- Local React Native repository from node_modules
Location: index.js (project root)
/**
* @format
*/
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);Purpose: Entry point for React Native app. Registers the App component.
Location: app.json (project root)
{
"name": "NativeBridge",
"displayName": "NativeBridge"
}Purpose: Defines the app name for React Native.
When creating NativeBridge from NativeBridgeApp, update these values:
| File | Old Value | New Value |
|---|---|---|
| MainActivity.kt | package com.nativebridgeapp |
package com.nativebridge.io |
| MainActivity.kt | getMainComponentName() = "NativeBridgeApp" |
getMainComponentName() = "NativeBridge" |
| MainApplication.kt | package com.nativebridgeapp |
package com.nativebridge.io |
| AndroidManifest.xml | package="com.nativebridgeapp" |
Package attribute removed (uses namespace) |
| build.gradle (app) | namespace "com.nativebridgeapp" |
namespace "com.nativebridge.io" |
| build.gradle (app) | applicationId "com.nativebridgeapp" |
applicationId "com.nativebridge.io" |
| strings.xml | <string name="app_name">NativeBridgeApp</string> |
<string name="app_name">NativeBridge</string> |
| app.json | "name": "NativeBridgeApp" |
"name": "NativeBridge" |
| package.json | "name": "NativeBridgeApp" |
"name": "NativeBridge" |
After setup, verify:
- Package name is
com.nativebridge.ioin all files - App name is "NativeBridge" in strings.xml and app.json
- All biometric permissions are in AndroidManifest.xml
- MainActivity.kt and MainApplication.kt are in correct directory structure
- Gradle build completes without errors
- App installs and launches successfully
- Biometric authentication prompt appears on launch
Error: Package name mismatch
- Ensure all files use
com.nativebridge.ioconsistently - Check that Java/Kotlin files are in correct directory:
com/nativebridge/io/
Error: Main component not found
- Verify
getMainComponentName()returns "NativeBridge" - Check app.json has correct name
- Ensure App.tsx exports default component
Error: Biometric permission denied
- Check AndroidManifest.xml has
USE_BIOMETRICandUSE_FINGERPRINT - Verify minSdkVersion is at least 23 (Android 6.0)
- Ensure device has biometric sensor and fingerprint enrolled
Error: Gradle build failed
- Clean gradle:
./gradlew clean - Delete
.gradlefolder in android directory - Verify Java 17 is being used:
java -version - Check build.gradle versions match React Native 0.74.7 requirements