Changed formula from (major*100000 + minor*1000 + patch) to the correct (major*10000 + minor*100 + patch) to match UpdateManager.smali implementation. Updated all examples: - 14.5.0 = 140500 (0x224D4) not 145000 - Corrected hex values throughout documentation This bug would have prevented OTA updates from working correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
11 KiB
🔧 RR3 OTA Integration Guide
Step-by-step guide to integrate the OTA update system into any RR3 APK
📋 Prerequisites
Tools Needed
- apktool - For decompiling/recompiling APKs
- Java JDK 8+ - For compiling Java to class files
- dx tool (Android SDK) - For converting class to dex
- baksmali/smali - For dex to smali conversion
- zipalign - For optimizing APK
- apksigner - For signing APK
- Text editor - For editing files
Install Tools
# apktool
wget https://github.com/iBotPeaches/Apktool/releases/latest/download/apktool.jar
# Android SDK (includes dx, zipalign, apksigner)
# Download from: https://developer.android.com/studio
# baksmali/smali
wget https://github.com/JesusFreke/smali/releases/latest/download/baksmali.jar
wget https://github.com/JesusFreke/smali/releases/latest/download/smali.jar
🎯 Integration Steps
Step 1: Decompile Your APK
# Decompile RR3 APK
apktool d your-rr3.apk -o rr3-decompiled
cd rr3-decompiled
Output structure:
rr3-decompiled/
├── AndroidManifest.xml
├── smali/
├── assets/
├── res/
└── ...
Step 2: Add UpdateManager
Option A: Use Precompiled Smali (Easier)
# Create directory
mkdir -p smali/com/community
# Copy UpdateManager.smali
cp /path/to/rr3-ota/UpdateManager.smali smali/com/community/
Option B: Compile from Java (More Control)
# Compile Java to class
javac -source 1.8 -target 1.8 \
-cp android.jar:org.json.jar \
UpdateManager.java
# Convert class to dex
dx --dex --output=UpdateManager.dex UpdateManager.class
# Convert dex to smali
baksmali d UpdateManager.dex -o smali-output
# Copy to APK
mkdir -p smali/com/community
cp smali-output/com/community/UpdateManager.smali smali/com/community/
Important: Update Version Constants
Edit smali/com/community/UpdateManager.smali:
Find these lines:
.field private static final CURRENT_VERSION:Ljava/lang/String; = "15.0.0-community-alpha"
.field private static final CURRENT_VERSION_CODE:I = 0x249f0
Change to your version:
.field private static final CURRENT_VERSION:Ljava/lang/String; = "14.5.0" # Your version
.field private static final CURRENT_VERSION_CODE:I = 0x224D4 # 140500 in hex
Calculate version code:
versionCode = (major * 10000) + (minor * 100) + patch
Examples:
14.5.0 → 140500 → 0x224D4 (hex)
15.0.0 → 150000 → 0x249F0 (hex)
# Convert to hex: printf '%x\n' 140500
Update Manifest URL
Find this line:
.field private static final UPDATE_API_URL:Ljava/lang/String; = "https://raw.githubusercontent.com/project-real-resurrection-3/rr3-releases/main/versions.json"
Change to your manifest URL:
.field private static final UPDATE_API_URL:Ljava/lang/String; = "https://raw.githubusercontent.com/YOUR-ORG/YOUR-REPO/main/versions.json"
Step 3: Add HTML UI
# Copy update checker HTML
cp /path/to/rr3-ota/community_update_checker.html assets/
Verify placement:
assets/
└── community_update_checker.html
Step 4: Add Permissions
Edit AndroidManifest.xml:
<manifest>
<!-- Add these permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- Rest of manifest -->
</manifest>
Step 5: Integrate into Your UI
You need to add a button/menu item that triggers the update checker.
Example: Add to Main Menu WebView
Find your main menu HTML file (usually in assets/):
# Search for HTML files
find assets/ -name "*.html" | grep -i menu
Add update button:
<!-- Add to your menu -->
<button onclick="checkForUpdates()" class="menu-button">
🔄 Check for Updates
</button>
<script>
function checkForUpdates() {
window.location.href = 'file:///android_asset/community_update_checker.html';
}
</script>
Add WebView Bridge
Find the Activity that creates your WebView (in smali/):
Common locations:
smali/com/ea/games/*/MainActivity.smalismali/com/ea/games/*/WebViewActivity.smali
Find where WebView is created:
# Look for this pattern
new-instance v0, Landroid/webkit/WebView;
invoke-direct {v0, p0}, Landroid/webkit/WebView;-><init>(Landroid/content/Context;)V
Add JavaScript interface after WebView creation:
# Create UpdateManager instance
new-instance v1, Lcom/community/UpdateManager;
move-object v2, p0 # context
invoke-direct {v1, v2}, Lcom/community/UpdateManager;-><init>(Landroid/content/Context;)V
# Add as JavaScript interface
const-string v2, "UpdateManager"
invoke-virtual {v0, v1, v2}, Landroid/webkit/WebView;->addJavascriptInterface(Ljava/lang/Object;Ljava/lang/String;)V
Step 6: Recompile APK
# Build APK
apktool b rr3-decompiled -o rr3-modified-unsigned.apk
# Zipalign
zipalign -p -f -v 4 rr3-modified-unsigned.apk rr3-modified-aligned.apk
# Sign APK (create keystore if needed)
# Create keystore (first time only):
keytool -genkey -v -keystore rr3.keystore -alias rr3-key -keyalg RSA -keysize 2048 -validity 10000
# Sign
apksigner sign --ks rr3.keystore --ks-key-alias rr3-key \
--out rr3-modified-signed.apk \
rr3-modified-aligned.apk
# Verify signature
apksigner verify rr3-modified-signed.apk
Final APK: rr3-modified-signed.apk
Step 7: Test Installation
# Install on device
adb install rr3-modified-signed.apk
# Or manually:
# 1. Transfer APK to device
# 2. Enable "Install from Unknown Sources"
# 3. Tap APK to install
🧪 Testing the Integration
Test 1: WebView Bridge
Open your app and run in Android Studio logcat:
adb logcat | grep UpdateManager
Expected: Should see UpdateManager logs when app starts.
Test 2: UI Button
- Open your modified menu
- Click "Check for Updates" button
- Should navigate to update checker page
If it doesn't work:
- Check
assets/community_update_checker.htmlexists - Verify path:
file:///android_asset/community_update_checker.html
Test 3: Update Check
- Click "Check for Updates" in the UI
- Watch logcat:
adb logcat | grep UpdateManager
Expected logs:
I/UpdateManager: Checking for updates from manifest...
I/UpdateManager: No update available
Or if update exists:
I/UpdateManager: Update available: 15.1.0
Test 4: Download
- Create a test release on GitHub
- Update your
versions.jsonmanifest - Check for updates in app
- Click "Download Update"
- Verify download starts
🐛 Troubleshooting
Issue: "Class not found: UpdateManager"
Cause: UpdateManager.smali not in correct location
Fix:
# Verify file exists
ls -la smali/com/community/UpdateManager.smali
# Should be:
# smali/com/community/UpdateManager.smali
# NOT: smali/UpdateManager.smali
Issue: "JavaScript interface not found"
Cause: WebView bridge not added or incorrect
Fix:
- Verify you added the JavaScript interface code
- Check the interface name matches:
"UpdateManager" - Make sure it's added BEFORE WebView loads content
Issue: "Update check returns error"
Cause: Manifest URL incorrect or not accessible
Fix:
# Test manifest URL manually
curl https://raw.githubusercontent.com/YOUR-ORG/YOUR-REPO/main/versions.json
# Should return JSON, not 404
Issue: "Version code mismatch"
Cause: Incorrect version code calculation
Fix:
# Calculate version code
echo "scale=0; (14*10000) + (5*100) + 0" | bc
# Result: 140500
# Convert to hex
printf '%x\n' 140500
# Result: 224d4
# Update in smali:
.field private static final CURRENT_VERSION_CODE:I = 0x23ab8
Issue: "APK won't install"
Cause: Signature mismatch or corrupted APK
Fix:
# Verify APK
apksigner verify rr3-modified-signed.apk
# If invalid, rebuild and re-sign
apktool b rr3-decompiled -o new.apk
zipalign -p 4 new.apk aligned.apk
apksigner sign --ks rr3.keystore aligned.apk
📱 Platform-Specific Notes
Android 11+ (API 30+)
File access changes: Need to use scoped storage
In UpdateManager.smali, update download destination:
// Old (doesn't work on Android 11+):
Environment.DIRECTORY_DOWNLOADS
// New (works on all versions):
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
Android 8+ (API 26+)
Install unknown apps permission required
Add to AndroidManifest.xml:
<application>
<activity android:name=".MainActivity">
<!-- Add this -->
<meta-data
android:name="android.app.install_package"
android:value="true" />
</activity>
</application>
🔐 Security Checklist
Before releasing:
- Version constants updated
- Manifest URL points to your repository
- APK signed with your keystore (not debug key!)
- Permissions added to AndroidManifest.xml
- SHA-256 checksums in manifest (optional but recommended)
- HTTPS used for all URLs
- Tested on multiple Android versions
📊 Version Manifest Setup
After integration, you need a manifest:
1. Create GitHub Repository
# Create releases repository
gh repo create YOUR-ORG/rr3-releases --public
2. Create versions.json
{
"schema_version": 1,
"last_updated": "2026-02-24T00:00:00Z",
"channels": {
"stable": {
"description": "Stable releases",
"latest": "14.5.0"
}
},
"versions": [
{
"version": "14.5.0",
"version_code": 140500,
"channel": "stable",
"release_date": "2026-02-24",
"min_android": 21,
"target_android": 33,
"download_url": "https://github.com/YOUR-ORG/rr3-releases/releases/download/v14.5.0/RR3-v14.5.0.apk",
"file_size": 230000000,
"sha256": "your-sha256-here",
"changelog": "## What's New\n- Your changelog here",
"upgrade_from": []
}
]
}
3. Upload to GitHub
git add versions.json
git commit -m "Add version manifest"
git push
4. Verify Accessibility
curl https://raw.githubusercontent.com/YOUR-ORG/rr3-releases/main/versions.json
🎉 You're Done!
Your RR3 APK now has a fully functional OTA update system!
Next steps:
- Release your first version on GitHub
- Update versions.json when new versions are ready
- Users will automatically see updates
📞 Need Help?
- 📖 Full documentation: README.md
- 🐛 Report issues: GitHub Issues
- 💬 Community: Discord (link TBA)
- 📧 Contact: @ssfdre38
Happy integrating! 🔄🏁