Skip to main content

Building and Configuring Apps

1. Configuring package.json

Property Values Description
name "my-react-native-app" App name, used in stores and as the bundle ID
version "1.0.0" Version following semantic versioning
main "index.js" Entry point for the app
scripts { "start": "expo start --dev-client" } Command aliases for development and build tasks
dependencies { "react": "^18.2.0", "react-native": "^0.73.0" } Runtime dependencies required for app execution
devDependencies { "@types/react": "^18.2.0", "typescript": "^5.0.0" } Development tools and type definitions
expo { "sdkVersion": "50.0.0" } Expo-specific configuration (if using Expo)

Example: package.json configuration

{
  "name": "my-react-native-app",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "expo start --dev-client",
    "android": "expo run:android",
    "ios": "expo run:ios"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-native": "^0.73.0",
    "expo": "~50.0.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.0",
    "typescript": "^5.0.0"
  }
}
Note: When using Expo, the expo field is required to specify the SDK version.

2. Setting App Name and Bundle ID

Field Platform Configuration Description
name Android app.json App display name shown on device home screen
name iOS Info.plist App display name shown on device home screen
package Android app.json Unique identifier for Android app (reverse domain notation)
bundleIdentifier iOS Info.plist Unique identifier for iOS app (reverse domain notation)

Example: Configuring app name and bundle ID in app.json

{
  "name": "MyReactNativeApp",
  "displayName": "MyReactNativeApp",
  "android": {
    "package": "com.mycompany.myreactnativeapp"
  },
  "ios": {
    "bundleIdentifier": "com.mycompany.myreactnativeapp"
  }
}

3. Configuring App Icons

Platform Icon File Size Notes
iOS AppIcon.appiconset 1024x1024px Contains multiple sizes for different devices and resolutions
Android res/mipmap-*/ic_launcher.png 192x192px (mdpi), 384x384px (hdpi), 576x576px (xhdpi) Must be in multiple densities for various screen sizes

Example: iOS App Icon Setup

mkdir -p ios/MyApp/Assets.xcassets/AppIcon.appiconset
cp icon-1024.png ios/MyApp/Assets.xcassets/AppIcon.appiconset/icon-1024.png

Example: Android App Icon Setup

mkdir -p android/app/src/main/res/mipmap-mdpi
mkdir -p android/app/src/main/res/mipmap-hdpi
mkdir -p android/app/src/main/res/mipmap-xhdpi

cp icon-192.png android/app/src/main/res/mipmap-mdpi/ic_launcher.png
cp icon-384.png android/app/src/main/res/mipmap-hdpi/ic_launcher.png
cp icon-576.png android/app/src/main/res/mipmap-xhd/%ic_launcher.png
Note: Ensure all icon files are properly named and placed in the correct directories as per platform requirements.

4. Setting Up Splash Screens

Example: Basic splash screen setup with react-native-splash-screen

import SplashScreen from 'react-native-splash-screen';

const App = () => {
  useEffect(() => {
    SplashScreen.hide();
  }, []);

  return (
    <View style={{ flex: 1 }}>
      <Text>Hello World</Text>
    </View>
  );
};
Property Description Default
splashScreen Image resource for splash screen None
hideDelay Time in ms to hide splash screen 0
Note: On iOS, splash screen is managed via Info.plist and LaunchScreen.storyboard.
Warning: On Android, ensure splash screen image is placed in android/app/src/main/res/drawable.

Setup Steps

  • Install react-native-splash-screen
  • Add splash image to native project resources
  • Configure LaunchScreen.storyboard for iOS
  • Call SplashScreen.hide() after app initialization

5. Configuring Build Variants

Variant Description Configuration Usage
debug Builds app with debugging enabled buildType = "debug" Used for development and testing
release Builds app optimized for production buildType = "release" Used for app store deployment

Example: Setting Build Type in Gradle

android {
    buildTypes {
        debug {
            debuggable true
        }
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

Example: Setting Build Type in Xcode

export CONFIGURATION_BUILD_DIR="build/Release-iphoneos"
Note: Release builds should always enable ProGuard or R8 for code shrinking and obfuscation.

6. Using Environment-specific Configurations

Example: Environment Configuration Setup

// config/env.js
const envConfig = {
  development: {
    apiUrl: 'http://localhost:3000',
    debug: true
  },
  production: {
    apiUrl: 'https://api.myapp.com',
    debug: false
  }
};

export default envConfig[process.env.NODE_ENV || 'development'];
Configuration Value Description
apiUrl http://localhost:3000 Base URL for API calls in development
apiUrl https://api.myapp.com Base URL for API calls in production
debug true Enables debug logging in development
debug false Disables debug logging in production
Note: The NODE_ENV variable is typically set during the build process or by your CI/CD pipeline.

Example: Using Config in App

import config from './config/env';

function fetchData() {
  return fetch(`\${config.apiUrl}/data`);
}

7. Managing App Versioning

Property Value Description
version "1.0.0" App version string in semantic versioning format (MAJOR.MINOR.PATCH)
buildNumber "1" Build number for app store submission (iOS: CFBundleVersion, Android: versionCode)

Example: Configuring version in package.json

{
  "name": "MyReactNativeApp",
  "version": "2.1.0",
  "buildNumber": "5"
}

Example: Setting version in app.json (Expo)

{
  "expo": {
    "name": "MyApp",
    "version": "3.0.1",
    "android": {
      "versionCode": 10
    },
    "ios": {
      "buildNumber": "10"
    }
  }
}
Note: For iOS, buildNumber maps to CFBundleVersion. For Android, it maps to versionCode.
Warning: Increment buildNumber for every app store submission to ensure proper version tracking.
Platform Version Property Notes
iOS CFBundleVersion Used by App Store. Must be an integer.
Android versionCode Used by Google Play. Must be an integer.
React Native version Used for semantic versioning in code and documentation.

8. Configuring Permissions

Permission Description Android Manifest iOS Info.plist
ACCESS_FINE_LOCATION Allows access to precise location data <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <key>NSLocationWhenInUseUsageDescription</key><string>Location access for feature X</string>
CAMERA Allows access to camera for capturing photos or videos <uses-permission android:name="android.permission.CAMERA" /> <key>NSCameraUsageDescription</key><string>Camera access for feature X</string>
RECORD_AUDIO Allows recording audio <uses-permission android:name="android.permission.RECORD_AUDIO" /> <key>NSMicrophoneUsageDescription</key><string>Audio recording for feature X</string>
READ_CONTACTS Allows reading contact data <uses-permission android:name="android.permission.READ_CONTACTS" /> <key>NSContactsUsageDescription</key><string>Contact access for feature X</string>
WRITE_EXTERNAL_STORAGE Allows writing to external storage (e.g. SD card) <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> Not required on iOS

Example: Requesting Camera Permission

import { PermissionsAndroid, Platform } from 'react-native';

const requestCameraPermission = async () => {
  if (Platform.OS === 'android') {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.CAMERA,
        {
          title: 'Camera Permission',
          message: 'App needs camera access to scan QR codes.',
          buttonNeutral: 'Ask Me Later',
          buttonNegative: 'Cancel',
          buttonPositive: 'OK'
        }
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        console.log('Camera permission granted');
      } else {
        console.log('Camera permission denied');
      }
    } catch (err) {
      console.warn(err);
    }
  }
};
Note: On iOS, you must also add the appropriate NSCameraUsageDescription key to your app's Info.plist.
Warning: Always request permissions at runtime on Android 6.0+ (API level 23) and above, as they are not automatically granted.
Property Description Example
scheme URI scheme used to open the app myapp://
host Host part of the deep link notifications
path Path to navigate to within the app /message/123
<intent-filter>
  <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" android:host="notifications" />
</intent-filter>
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLName</key>
    <string>Deep Link Scheme</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myapp</string>
    </array>
  </dict>
</array>
Note: Ensure that your deep link schemes are unique to avoid conflicts with other apps.
Warning: On Android, make sure to define the intent filter in AndroidManifest.xml correctly to handle deep links.

10. Configuring App Signing

Property Description Value
android.signingConfigs.release.storeFile Path to the keystore file ../my-release-key.keystore
android.signingConfigs.release.storePassword Password to access the keystore myStorePassword
android.signingConfigs.release.keyAlias Alias of the key in the keystore myKeyAlias
android.signingConfigs.release.keyPassword Password for the key myKeyPassword

Example: Android signing configuration in gradle.properties

MYAPP_RELEASE_STORE_FILE=../my-release-key.keystore
MYAPP_RELEASE_STORE_PASSWORD=myStorePassword
MYAPP_RELEASE_KEY_ALIAS=myKeyAlias
MYAPP_RELEASE_KEY_PASSWORD=myKeyPassword

Example: Android signing config in build.gradle

signingConfigs {
    release {
        storeFile file(System.getenv("MYAPP_RELEASE_STORE_FILE"))
        storePassword System.getenv("MYAPP_RELEASE_STORE_PASSWORD")
        keyAlias System.getenv("MYAPP_RELEASE_KEY_ALIAS")
        keyPassword System.getenv("MYAPP_RELEASE_KEY_PASSWORD")
    }
}
Note: Store your keystore and passwords securely. Losing them will prevent you from publishing updates to the app.

Was this article helpful?