This guide will help you test the native OTA bundle update functionality on an Android emulator.
- Android Studio installed with Android SDK
- Android Emulator set up (API 21+ recommended)
- React Native development environment configured
- Backend server running (for serving bundles)
npx react-native init TestOTAApp
cd TestOTAApp# If using local path
npm install ../react-native-ota-sdk
# Or if published
npm install react-native-ota-sdkThe module should auto-link, but verify:
cd android
./gradlew clean
cd ..Ensure the package is registered:
import com.otaupdater.react.OTAPackage;
// In getPackages() method:
packages.add(new OTAPackage());Ensure permissions are set:
<uses-permission android:name="android.permission.INTERNET" />Create App.js:
import React, { useEffect, useState } from 'react';
import { View, Text, Button, ScrollView, StyleSheet } from 'react-native';
import { OTAUpdater } from 'react-native-ota-sdk';
import NativeBundleManager from 'react-native-ota-sdk/src/NativeBundleManager';
export default function App() {
const [logs, setLogs] = useState([]);
const [isAvailable, setIsAvailable] = useState(false);
useEffect(() => {
// Check if native module is available
setIsAvailable(NativeBundleManager.isAvailable);
addLog('Native module available: ' + NativeBundleManager.isAvailable);
}, []);
const addLog = (message) => {
const timestamp = new Date().toLocaleTimeString();
setLogs(prev => [...prev, `[${timestamp}] ${message}`]);
console.log(message);
};
const testDownload = async () => {
try {
addLog('Starting bundle download test...');
// Replace with your actual bundle URL
const bundleUrl = 'http://10.0.2.2:3001/api/bundles/test.bundle';
const versionName = '1.0.1';
const result = await NativeBundleManager.downloadBundle(bundleUrl, versionName);
addLog('Download successful: ' + JSON.stringify(result));
} catch (error) {
addLog('Download error: ' + error.message);
}
};
const testGetCurrent = async () => {
try {
const bundle = await NativeBundleManager.getCurrentBundle();
addLog('Current bundle: ' + JSON.stringify(bundle));
} catch (error) {
addLog('Get current error: ' + error.message);
}
};
const testGetConfig = async () => {
try {
const config = await NativeBundleManager.getConfiguration();
addLog('Configuration: ' + JSON.stringify(config));
} catch (error) {
addLog('Config error: ' + error.message);
}
};
const testClearBundles = async () => {
try {
await NativeBundleManager.clearBundles();
addLog('Bundles cleared successfully');
} catch (error) {
addLog('Clear error: ' + error.message);
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>OTA Native Module Test</Text>
<Text style={styles.status}>
Native Module: {isAvailable ? '✅ Available' : '❌ Not Available'}
</Text>
<View style={styles.buttonContainer}>
<Button title="Test Download" onPress={testDownload} />
<Button title="Get Current Bundle" onPress={testGetCurrent} />
<Button title="Get Configuration" onPress={testGetConfig} />
<Button title="Clear Bundles" onPress={testClearBundles} />
</View>
<ScrollView style={styles.logContainer}>
{logs.map((log, index) => (
<Text key={index} style={styles.log}>{log}</Text>
))}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
paddingTop: 60,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
},
status: {
fontSize: 16,
marginBottom: 20,
},
buttonContainer: {
gap: 10,
marginBottom: 20,
},
logContainer: {
flex: 1,
backgroundColor: '#f0f0f0',
padding: 10,
borderRadius: 5,
},
log: {
fontSize: 12,
fontFamily: 'monospace',
marginBottom: 5,
},
});Ensure your backend is running and accessible from the emulator:
cd backend
npm startImportant: Use 10.0.2.2 instead of localhost in the emulator to access your host machine.
Create test-server.js:
const express = require('express');
const app = express();
const path = require('path');
app.use(express.static('test-bundles'));
// Serve a test bundle
app.get('/api/bundles/test.bundle', (req, res) => {
res.sendFile(path.join(__dirname, 'test-bundles', 'test.bundle'));
});
app.listen(3001, () => {
console.log('Test server running on http://localhost:3001');
});Create a simple test bundle file test-bundles/test.bundle:
// Simple test bundle
console.log('Test bundle loaded!');# List available emulators
emulator -list-avds
# Start an emulator
emulator -avd <emulator-name># Clean build
cd android
./gradlew clean
cd ..
# Run on emulator
npx react-native run-android- Open the app
- Check if "Native Module: ✅ Available" is shown
- If not available, check logs:
adb logcat | grep OTAUpdater
- Click "Test Download" button
- Watch logs for download progress
- Check logs:
adb logcat | grep OTAUpdater
Expected logs:
[OTAUpdater] Starting bundle download...
[OTAUpdater] Download progress: X%
[OTAUpdater] Download successful
- After downloading, click "Get Current Bundle"
- Should show bundle metadata
- Click "Get Configuration"
- Should show app version and bundle file name
- Click "Clear Bundles"
- Then try "Get Current Bundle" - should return null
Create test-bundles/test-v2.bundle:
console.log('Test bundle V2 loaded! This is an update!');- Download bundle V1
- Install bundle V1
- Load bundle V1 (app should reload)
- Download bundle V2
- Install bundle V2
- Load bundle V2 (app should reload with new content)
adb logcat | grep -E "(OTAUpdater|ReactNative)"adb logcat -s ReactNative:V OTAUpdater:*adb logcat -cawait NativeBundleManager.downloadBundle('http://invalid-url.com/bundle.bundle', '1.0.0');
// Should show error in logs- Turn off WiFi/data on emulator
- Try downloading bundle
- Should handle error gracefully
await NativeBundleManager.loadBundle('/invalid/path/bundle.bundle');
// Should show errorError: OTANative module is not available
Solutions:
- Rebuild the app:
cd android && ./gradlew clean && cd .. && npx react-native run-android - Check
MainApplication.javahasnew OTAPackage() - Verify module exists:
ls android/app/src/main/java/com/otaupdater/react/
Error: package com.otaupdater.react does not exist
Solutions:
- Clean build:
cd android && ./gradlew clean - Invalidate caches in Android Studio
- Rebuild:
npx react-native run-android
Error: Bundle downloads but doesn't load
Solutions:
- Check bundle path is correct
- Verify bundle file name matches
index.android.bundle - Check logs for specific error:
adb logcat | grep BundleLoader
Error: Cannot connect to server
Solutions:
- Use
10.0.2.2instead oflocalhostfor emulator - Check firewall settings
- Verify server is running:
curl http://10.0.2.2:3001/api/bundles/test.bundle
- Build a production bundle:
npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output test.bundle- Upload to your backend
- Download via native module
- Test loading
Monitor download progress events:
import { DeviceEventEmitter } from 'react-native';
DeviceEventEmitter.addListener('OTADownloadProgress', (progress) => {
console.log('Progress:', progress.receivedBytes, '/', progress.totalBytes);
});- Download version 1.0.0
- Install and load
- Download version 1.0.1
- Install and load
- Verify version 1.0.1 is current
- Test rollback (if implemented)
- Native module is detected
- Bundle download works
- Download progress events fire
- Bundle installation works
- Bundle loading works (app reloads)
- Current bundle info is correct
- Configuration is correct
- Clear bundles works
- Error handling works
- Logs are informative
Once basic testing passes:
- Test with your actual backend API
- Test with production bundles
- Test update flow end-to-end
- Test error recovery
- Test on physical device