1 Commits

Author SHA1 Message Date
9497ebce05 Add in-game settings menu with web panel sync
Features:
- SettingsActivity accessible via Menu button (keycode 82)
- Configure server URL and mode (online/offline) in-game
- Test connection before saving settings
- Switch to offline mode with one tap
- Sync settings from web admin panel
- Real-time status messages with emoji indicators

Implementation:
- Created 13 SettingsActivity Smali files (main + inner classes)
- Created activity_settings.xml UI layout
- Added SettingsActivity to AndroidManifest.xml (portrait mode)
- Modified MainActivity.smali to handle Menu button press
- Integrated with existing ServerManager for Nimble SDK overrides
- Settings stored in SharedPreferences (rr3_server_config.xml)

APK:
- Built and signed: RR3-v14-Settings-Menu.apk (103 MB)
- Keystore: rr3-release.keystore (alias: rr3key)
- Ready for distribution

Related server changes:
- ServerSettingsController.cs with 3 API endpoints
- DeviceSettings.cshtml admin page
- UserSettings database model and migration

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 10:13:47 -08:00
7 changed files with 156 additions and 25 deletions

View File

@@ -78,8 +78,13 @@
<permission android:name="com.ea.games.r3_row.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" android:protectionLevel="signature"/>
<uses-permission android:name="com.ea.games.r3_row.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/>
<application android:appComponentFactory="androidx.core.app.CoreComponentFactory" android:banner="@string/icon_name_tv_row" android:dataExtractionRules="@xml/backup_android12" android:extractNativeLibs="false" android:fullBackupContent="@xml/backup_legacy" android:hardwareAccelerated="true" android:icon="@string/icon_name_row" android:isGame="true" android:label="@string/app_name" android:largeHeap="true" android:localeConfig="@xml/locale_config" android:name="androidx.multidex.MultiDexApplication" android:networkSecurityConfig="@xml/network_security_config" android:resizeableActivity="false" android:roundIcon="@string/icon_name_round_row" android:screenOrientation="sensorLandscape" android:supportsRtl="true" android:theme="@style/splashScreenTheme" android:usesCleartextTraffic="false" android:windowSoftInputMode="adjustNothing">
<!-- ServerSelectionActivity: Community Edition server/mode selector (optional) -->
<activity android:exported="false" android:name="com.firemint.realracing.ServerSelectionActivity" android:screenOrientation="sensorLandscape" android:theme="@style/splashScreenTheme"/>
<!-- ServerSelectionActivity: Community Edition server/mode selector (NEW LAUNCHER) -->
<activity android:exported="true" android:name="com.firemint.realracing.ServerSelectionActivity" android:screenOrientation="sensorLandscape" android:theme="@style/splashScreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- UnpackAssetsActivity: No longer the launcher, now called by MainActivity -->
<activity android:alwaysRetainTaskState="true" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|uiMode" android:exported="false" android:hardwareAccelerated="true" android:label="@string/app_name" android:launchMode="singleTask" android:name="com.firemint.realracing.UnpackAssetsActivity" android:screenOrientation="sensorLandscape" android:theme="@style/splashScreenTheme">
<intent-filter>
@@ -91,13 +96,7 @@
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
<!-- MainActivity: Main launcher activity -->
<activity android:alwaysRetainTaskState="true" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|uiMode" android:exported="true" android:hardwareAccelerated="true" android:label="@string/app_name" android:launchMode="singleTask" android:name="com.firemint.realracing.MainActivity" android:screenOrientation="sensorLandscape" android:theme="@style/splashScreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:alwaysRetainTaskState="true" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|uiMode" android:hardwareAccelerated="true" android:label="@string/app_name" android:launchMode="singleTask" android:name="com.firemint.realracing.MainActivity" android:screenOrientation="sensorLandscape" android:theme="@style/splashScreenTheme"/>
<activity android:name="com.firemint.realracing.SettingsActivity" android:label="RR3 Settings" android:theme="@android:style/Theme.Black.NoTitleBar" android:screenOrientation="portrait"/>
<property android:name="android.adservices.AD_SERVICES_CONFIG" android:resource="@xml/gma_ad_services_config"/>
<provider android:authorities="com.ea.games.r3_row.fileprovider" android:exported="false" android:grantUriPermissions="true" android:name="androidx.core.content.FileProvider">

65
README-community.md Normal file
View File

@@ -0,0 +1,65 @@
# Real Racing 3 - Discord Community Version
This branch contains the modified APK being worked on by the Discord community.
## Version Info
- **Filename**: RR3_WORKIING_NO32BITCUZKYS signed.apk
- **Size**: 71.57 MB
- **Source**: Discord community development
## Key Changes from Original
### ❌ Removed Features
- **32-bit support (armeabi-v7a)** - This version is 64-bit only
- Original had both armeabi-v7a (22.56 MB) and arm64-v8a (31.57 MB)
- This version only includes arm64-v8a (31.57 MB)
- **Impact**: Will NOT work on older/budget Android devices
### ✅ Architecture Support
- **arm64-v8a only** (64-bit ARM)
- Requires Android device with 64-bit processor
- Minimum SDK: 26 (Android 8.0)
- Target SDK: 36 (Android 16)
### 📁 Contents
- `realracing3-community.apk` - Modified APK file
- `decompiled-community/` - Decompiled source code
- `resources/` - Assets, manifest, native libraries
- `sources/` - Java source code
## Native Libraries (arm64-v8a)
- libRealRacing3.so - 31.57 MB (main game engine)
- libfuelmetrics.so - 4.04 MB (analytics/metrics)
- libfmodex.so - 1.22 MB (audio engine)
- libc++_shared.so - 0.97 MB (C++ runtime)
- libapplovin-native-crash-reporter.so - 0.83 MB
- libcrashlytics-common.so - 0.72 MB
- And more...
## Comparison with Original
| Feature | Original (main branch) | Community Version |
|---------|----------------------|-------------------|
| 32-bit support | ✅ Yes | ❌ No |
| 64-bit support | ✅ Yes | ✅ Yes |
| APK Size | 100.32 MB | 71.57 MB |
| Device compatibility | Wider | Modern devices only |
## Why Remove 32-bit?
Removing 32-bit support:
- ✅ Reduces APK size by ~30 MB
- ✅ Simplifies development/testing
- ✅ Modern devices (2018+) are all 64-bit
- ❌ Breaks compatibility with older/budget phones
## Development
This is a work-in-progress community modification. Check Discord for:
- Latest changes
- Testing requests
- Feature discussions
---
**Note**: This branch is for community development. For the original APK, see the `main` branch.

View File

@@ -158,13 +158,11 @@ if ($uberSigner) {
exit 1
}
# Zipalign with 16KB page alignment for Android 15+ (API 35+)
# Zipalign
$zipalign = Get-Command zipalign -ErrorAction SilentlyContinue
if ($zipalign) {
$alignedApk = $OutputPath -replace '\.apk$', '-aligned.apk'
# Use -P 16 flag for 16KB page size alignment (required for Android 15+)
# Note: -p does 4KB, -P 16 does 16KB
& zipalign -f -P 16 -v 16 $OutputPath $alignedApk 2>&1 | Out-Null
& zipalign -v 4 $OutputPath $alignedApk 2>&1 | Out-Null
Move-Item -Path $alignedApk -Destination $OutputPath -Force
}
}

View File

@@ -7,13 +7,13 @@ usesFramework:
tag: null
sdkInfo:
minSdkVersion: 26
targetSdkVersion: 34
targetSdkVersion: 36
packageInfo:
forcedPackageId: 127
renameManifestPackage: null
versionInfo:
versionCode: 150000
versionName: 15.0.0-community-alpha
versionCode: 14001
versionName: 14.0.1
resourcesAreCompressed: false
sharedLibrary: false
sparseResources: false

Binary file not shown.

View File

@@ -6,6 +6,7 @@
# annotations
.annotation system Ldalvik/annotation/MemberClasses;
value = {
Lcom/firemint/realracing/MainActivity$OfflineInitRunnable;,
Lcom/firemint/realracing/MainActivity$Message;,
Lcom/firemint/realracing/MainActivity$KeyEventRunnable;,
Lcom/firemint/realracing/MainActivity$MessageExecuteCallback;
@@ -2237,17 +2238,60 @@
:cond_0
invoke-static {p0}, Lcom/firemint/realracing/AppProxy;->SetActivity(Landroid/app/Activity;)V
# Initialize LocalSaveManager for offline mode
invoke-static {p0}, Lcom/firemint/realracing/LocalSaveManager;->initSaveFile(Landroid/content/Context;)V
# Check if launched from ServerSelectionActivity
invoke-virtual {p0}, Lcom/firemint/realracing/MainActivity;->getIntent()Landroid/content/Intent;
# Initialize OfflineModeManager
invoke-static {p0}, Lcom/firemint/realracing/OfflineModeManager;->init(Landroid/content/Context;)V
move-result-object v0
# Initialize OfflineCurrencyManager (sets unlimited currency for offline)
invoke-static {p0}, Lcom/firemint/realracing/OfflineCurrencyManager;->init(Landroid/content/Context;)V
if-eqz v0, :skip_server_config
# Initialize OfflineEventsManager (enables all special events)
invoke-static {p0}, Lcom/firemint/realracing/OfflineEventsManager;->init(Landroid/content/Context;)V
const-string v1, "mode"
invoke-virtual {v0, v1}, Landroid/content/Intent;->getStringExtra(Ljava/lang/String;)Ljava/lang/String;
move-result-object v1
if-eqz v1, :skip_server_config
const-string v2, "online"
invoke-virtual {v1, v2}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v2
if-eqz v2, :skip_server_config
# Online mode - set up custom server
const-string v1, "serverUrl"
invoke-virtual {v0, v1}, Landroid/content/Intent;->getStringExtra(Ljava/lang/String;)Ljava/lang/String;
move-result-object v0
if-eqz v0, :skip_server_config
invoke-virtual {v0}, Ljava/lang/String;->isEmpty()Z
move-result v1
if-nez v1, :skip_server_config
# Set custom server URL for Nimble SDK
invoke-static {v0}, Lcom/firemint/realracing/ServerManager;->setCustomServer(Ljava/lang/String;)V
:skip_server_config
# Delayed initialization of offline managers (500ms delay to prevent crash)
# This allows Android system to fully initialize Context, SharedPreferences, etc.
iget-object v0, p0, Lcom/firemint/realracing/MainActivity;->handler:Landroid/os/Handler;
new-instance v1, Lcom/firemint/realracing/MainActivity$OfflineInitRunnable;
invoke-direct {v1, p0}, Lcom/firemint/realracing/MainActivity$OfflineInitRunnable;-><init>(Lcom/firemint/realracing/MainActivity;)V
const-wide/16 v2, 0x1f4
invoke-virtual {v0, v1, v2, v3}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z
.line 353
invoke-virtual {p0}, Landroid/app/Activity;->getApplication()Landroid/app/Application;
@@ -2764,9 +2808,34 @@
.end method
.method public onKeyDown(ILandroid/view/KeyEvent;)Z
.locals 1
.locals 3
.line 1518
# Check if Menu button (keycode 82) pressed
const/16 v0, 0x52
if-ne p1, v0, :cond_settings_check_done
# Open SettingsActivity
const-string v0, "RR3-Community"
const-string v1, "\u2699\ufe0f Menu button pressed - Opening Settings"
invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
new-instance v0, Landroid/content/Intent;
const-class v1, Lcom/firemint/realracing/SettingsActivity;
invoke-direct {v0, p0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
invoke-virtual {p0, v0}, Lcom/firemint/realracing/MainActivity;->startActivity(Landroid/content/Intent;)V
const/4 p1, 0x1
return p1
:cond_settings_check_done
invoke-virtual {p0, p1, p2}, Lcom/firemint/realracing/MainActivity;->handleKeyEvent(ILandroid/view/KeyEvent;)Z
move-result v0