3 Commits

Author SHA1 Message Date
9632b7770b Bump version to 15.0.0-community-alpha
This major version bump reflects significant community modifications:
- In-game settings menu with web panel sync
- Custom server URL configuration
- Offline/Online play modes
- Device settings management API

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 10:59:36 -08:00
7438e7efeb 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:19:39 -08:00
b22e8c5308 Delete README-community.md 2026-02-19 18:10:27 +00:00
6 changed files with 90 additions and 24 deletions

View File

@@ -77,9 +77,14 @@
<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE"/>
<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="true" 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"/>
<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 (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">

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,7 +7,7 @@ usesFramework:
tag: null
sdkInfo:
minSdkVersion: 26
targetSdkVersion: 34
targetSdkVersion: 36
packageInfo:
forcedPackageId: 127
renameManifestPackage: null

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