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.storyboardfor 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'
}
}
}
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.
9. Setting Up Deep Link Schemes
| 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 |
Example: Configuring Deep Link in AndroidManifest.xml
<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>
Example: Handling Deep Links in iOS (Info.plist)
<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.