Advanced React Native integration, platform-specific configuration, and troubleshooting (Beta)
iOS Development Requirements
Android Development Requirements
Development Environment
Advanced Podfile Configuration
ios/Podfile
:# Platform and deployment target
platform :ios, '13.4'
# Enable modular headers for compatibility
pod 'SPTPersistentCache', :modular_headers => true
pod 'DVAssetLoaderDelegate', :modular_headers => true
# Video caching support
$RNVideoUseVideoCaching = true
# Performance optimizations
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
# Flipper integration (for debugging)
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
# Post install hooks
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.4'
config.build_settings['CODE_SIGN_IDENTITY'] = ''
end
end
end
Extended Permissions Configuration
ios/{YourAppName}/Info.plist
:<!-- Camera and Media Permissions -->
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to capture photos and videos for posts and stories.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record audio for video posts and voice messages.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access to select and share photos and videos.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs permission to save photos and videos to your photo library.</string>
<!-- Location Permissions (if using location features) -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app uses location to tag posts and find nearby communities.</string>
<!-- Background Processing -->
<key>UIBackgroundModes</key>
<array>
<string>background-fetch</string>
<string>background-processing</string>
</array>
<!-- File Sharing -->
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
Background Downloads Handler
ios/{YourAppName}/AppDelegate.mm
:#import <RNFSManager.h>
#import <React/RCTBundleURLProvider.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Your existing initialization code
return YES;
}
// Background URL session handling
- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)(void))completionHandler
{
[RNFSManager setCompletionHandlerForIdentifier:identifier
completionHandler:completionHandler];
}
// Push notification handling
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
// Handle push notifications
completionHandler(UIBackgroundFetchResultNewData);
}
@end
Advanced Build Configuration
android/build.gradle
with comprehensive settings:buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 24
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "25.1.8937393"
kotlinVersion = "1.7.0"
// Dependency versions
supportLibVersion = "28.0.0"
playServicesVersion = "17.0.0"
androidXCoreVersion = "1.9.0"
// Performance settings
enableHermes = true
enableSeparateBuildPerCPUArchitecture = false
universalApk = false
}
dependencies {
classpath("com.android.tools.build:gradle:8.1.0")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
App-Level Build Configuration
android/app/build.gradle
:android {
namespace "com.yourapp"
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.yourapp"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
multiDexEnabled true
// Performance optimizations
ndk {
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
release {
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// Packaging options
packagingOptions {
pickFirst '**/libc++_shared.so'
pickFirst '**/libjsc.so'
}
}
Comprehensive Permissions
android/app/src/main/AndroidManifest.xml
:<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Camera and Media Permissions -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<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 (if using location features) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Notification Permissions -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- File Access -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- Camera hardware features -->
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<application
android:name=".MainApplication"
android:allowBackup="false"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<!-- Your activities and services -->
</application>
</manifest>
import React from 'react';
import {
AmityUiKitSocial,
AmityUiKitProvider,
AmityUiKitChat,
} from 'amity-react-native-social-ui-kit';
const advancedConfig = {
// Theme configuration
preferred_theme: "auto", // "light", "dark", "auto"
theme: {
light: {
primary_color: "#1054DE",
secondary_color: "#292B32",
base_color: "#000000",
base_shade1_color: "#636878",
base_shade2_color: "#898e9e",
base_shade3_color: "#a5a9b5",
base_shade4_color: "#ebecef",
alert_color: "#FA4D30",
background_color: "#FFFFFF",
background_shade1_color: "#f6f7f8"
},
dark: {
primary_color: "#1054DE",
secondary_color: "#292B32",
base_color: "#ebecef",
base_shade1_color: "#a5a9b5",
base_shade2_color: "#6e7487",
base_shade3_color: "#40434e",
base_shade4_color: "#292b32",
alert_color: "#FA4D30",
background_color: "#191919",
background_shade1_color: "#40434e"
}
},
// Performance settings
maxCacheSize: 100, // MB
enableOfflineMode: true,
enablePushNotifications: true,
// Feature flags
features: {
enableStories: true,
enableLiveStreaming: true,
enablePolls: true,
enableReactions: true
}
};
export default function App() {
return (
<AmityUiKitProvider
apiKey="YOUR_API_KEY"
apiRegion="YOUR_API_REGION"
userId="USER_ID"
displayName="USER_DISPLAY_NAME"
apiEndpoint="https://api.{API_REGION}.amity.co"
configs={advancedConfig}
// Event handlers
onConnectionStateChange={(state) => console.log('Connection:', state)}
onError={(error) => console.error('UIKit Error:', error)}
>
<MainApp />
</AmityUiKitProvider>
);
}
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createStackNavigator } from '@react-navigation/stack';
import Icon from 'react-native-vector-icons/Ionicons';
import {
AmityUiKitSocial,
AmityUiKitChat,
AmityUserProfilePage,
} from 'amity-react-native-social-ui-kit';
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
function SocialStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="SocialFeed"
component={AmityUiKitSocial}
options={{ title: 'Social Feed' }}
/>
</Stack.Navigator>
);
}
function ChatStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="ChatList"
component={AmityUiKitChat}
options={{ title: 'Messages' }}
/>
</Stack.Navigator>
);
}
function ProfileStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Profile"
component={AmityUserProfilePage}
options={{ title: 'Profile' }}
/>
</Stack.Navigator>
);
}
export default function MainApp() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Social') {
iconName = focused ? 'home' : 'home-outline';
} else if (route.name === 'Chat') {
iconName = focused ? 'chatbubbles' : 'chatbubbles-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person' : 'person-outline';
}
return <Icon name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: '#1054DE',
tabBarInactiveTintColor: 'gray',
})}
>
<Tab.Screen name="Social" component={SocialStack} />
<Tab.Screen name="Chat" component={ChatStack} />
<Tab.Screen name="Profile" component={ProfileStack} />
</Tab.Navigator>
</NavigationContainer>
);
}
import React, { useState, useEffect } from 'react';
import { useColorScheme } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
const ThemeProvider = ({ children }) => {
const systemColorScheme = useColorScheme();
const [userThemePreference, setUserThemePreference] = useState('auto');
const [currentTheme, setCurrentTheme] = useState('light');
useEffect(() => {
loadThemePreference();
}, []);
useEffect(() => {
updateCurrentTheme();
}, [userThemePreference, systemColorScheme]);
const loadThemePreference = async () => {
try {
const savedTheme = await AsyncStorage.getItem('theme_preference');
if (savedTheme) {
setUserThemePreference(savedTheme);
}
} catch (error) {
console.error('Failed to load theme preference:', error);
}
};
const updateCurrentTheme = () => {
if (userThemePreference === 'auto') {
setCurrentTheme(systemColorScheme || 'light');
} else {
setCurrentTheme(userThemePreference);
}
};
const saveThemePreference = async (theme) => {
try {
await AsyncStorage.setItem('theme_preference', theme);
setUserThemePreference(theme);
} catch (error) {
console.error('Failed to save theme preference:', error);
}
};
const themeConfig = {
preferred_theme: currentTheme,
// ... your theme configuration
};
return (
<AmityUiKitProvider
// ... other props
configs={themeConfig}
>
{children}
</AmityUiKitProvider>
);
};
iOS Firebase Setup
GoogleService-Info.plist
to your iOS projectios/Podfile
:pod 'Firebase/Core'
pod 'Firebase/Messaging'
ios/{YourApp}/AppDelegate.mm
:#import <Firebase.h>
#import <UserNotifications/UserNotifications.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure];
// Request notification permissions
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
}
}];
return YES;
}
@end
Android Firebase Setup
google-services.json
to android/app/
android/build.gradle
:dependencies {
classpath 'com.google.gms:google-services:4.3.15'
}
android/app/build.gradle
:apply plugin: 'com.google.gms.google-services'
dependencies {
implementation 'com.google.firebase:firebase-messaging:23.1.2'
}
React Native Integration
npm install @react-native-async-storage/async-storage
npm install react-native-push-notification
npm install @react-native-firebase/app
npm install @react-native-firebase/messaging
import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';
export const initializePushNotifications = async () => {
// Request permission (iOS)
if (Platform.OS === 'ios') {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (!enabled) {
console.log('Push notification permission denied');
return;
}
}
// Get FCM token
const fcmToken = await messaging().getToken();
console.log('FCM Token:', fcmToken);
// Register token with Amity
// This would be handled by the UIKit internally
// Handle foreground messages
messaging().onMessage(async remoteMessage => {
console.log('Foreground notification:', remoteMessage);
});
// Handle background messages
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Background notification:', remoteMessage);
});
};
import { useEffect, useRef, useCallback } from 'react';
import { AppState, AppStateStatus } from 'react-native';
export const useMemoryOptimization = () => {
const appState = useRef(AppState.currentState);
const handleAppStateChange = useCallback((nextAppState: AppStateStatus) => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === 'active'
) {
// App has come to foreground - refresh data if needed
console.log('App foregrounded - refreshing data');
} else if (nextAppState.match(/inactive|background/)) {
// App going to background - cleanup if needed
console.log('App backgrounded - cleaning up');
}
appState.current = nextAppState;
}, []);
useEffect(() => {
const subscription = AppState.addEventListener('change', handleAppStateChange);
return () => subscription?.remove();
}, [handleAppStateChange]);
};
// Use in your main component
function App() {
useMemoryOptimization();
return (
<AmityUiKitProvider
// ... other props
// Enable memory optimization
enableMemoryOptimization={true}
// Limit concurrent operations
maxConcurrentOperations={3}
// Enable image caching
enableImageCaching={true}
maxImageCacheSize={50} // MB
>
{/* Your app content */}
</AmityUiKitProvider>
);
}
import NetInfo from '@react-native-community/netinfo';
import { useState, useEffect } from 'react';
export const useNetworkOptimization = () => {
const [networkInfo, setNetworkInfo] = useState(null);
useEffect(() => {
const unsubscribe = NetInfo.addEventListener(state => {
setNetworkInfo(state);
// Adjust quality based on connection
if (state.type === 'cellular' && state.details?.cellularGeneration === '2g') {
// Reduce quality for 2G connections
console.log('Low bandwidth detected - reducing quality');
}
});
return unsubscribe;
}, []);
return networkInfo;
};
// Network-aware configuration
const getNetworkAwareConfig = (networkInfo) => {
const baseConfig = {
// Default configuration
};
if (networkInfo?.type === 'cellular') {
// Optimize for cellular connections
return {
...baseConfig,
imageQuality: 'medium',
videoQuality: 'low',
enablePreloading: false,
maxConcurrentDownloads: 2
};
}
return {
...baseConfig,
imageQuality: 'high',
videoQuality: 'high',
enablePreloading: true,
maxConcurrentDownloads: 5
};
};
Build and Compilation Issues
cd ios
rm -rf Pods Podfile.lock
pod deintegrate
pod setup
pod install --repo-update
# Clean build folder
rm -rf ~/Library/Developer/Xcode/DerivedData
# Reset simulator
xcrun simctl shutdown all
xcrun simctl erase all
cd android
./gradlew clean
rm -rf .gradle
cd ..
npx react-native run-android
# Update Android SDK
sdkmanager --update
# Check NDK version
sdkmanager --list | grep ndk
// In android/app/build.gradle
configurations.all {
resolutionStrategy {
force 'androidx.core:core:1.9.0'
}
}
Runtime and Performance Issues
// Use React DevTools Profiler
// Monitor component re-renders
// Implement proper cleanup
useEffect(() => {
const subscription = someSubscription();
return () => subscription.unsubscribe();
}, []);
// Use FlatList for large datasets
<FlatList
data={posts}
renderItem={({ item }) => <PostComponent post={item} />}
keyExtractor={(item) => item.id}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={10}
/>
// Enable fast image for better performance
import FastImage from 'react-native-fast-image';
const optimizedImageConfig = {
enableFastImage: true,
imageCache: 'web', // or 'memory'
imageCacheSize: 50 // MB
};
Platform-Specific Issues
import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions';
const checkCameraPermission = async () => {
const result = await check(PERMISSIONS.IOS.CAMERA);
if (result === RESULTS.DENIED) {
const requestResult = await request(PERMISSIONS.IOS.CAMERA);
return requestResult === RESULTS.GRANTED;
}
return result === RESULTS.GRANTED;
};
import { PermissionsAndroid } from 'react-native';
const requestAndroidPermissions = async () => {
const granted = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.CAMERA,
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
]);
return Object.values(granted).every(
permission => permission === PermissionsAndroid.RESULTS.GRANTED
);
};
import { BackHandler } from 'react-native';
useEffect(() => {
const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
// Handle back button press
return true; // Prevent default behavior
});
return () => backHandler.remove();
}, []);
Network and API Issues
// Validate API configuration
const validateAPIConfig = {
apiKey: 'YOUR_API_KEY',
apiRegion: 'us', // must match your console region
apiEndpoint: 'https://api.us.amity.co' // must match region
};
const networkConfig = {
timeout: 30000, // 30 seconds
retryAttempts: 3,
retryDelay: 1000, // 1 second
enableOfflineMode: true
};
// For development only - not for production
const devConfig = {
allowSelfSignedSSL: true, // Development only
trustAllCertificates: false // Keep false for security
};