mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-21 16:32:39 +00:00
tell people where to go for an updated game
This commit is contained in:
6 files changed
+134
-8
No files matched your search
@@ -3,6 +3,7 @@ package com.geode.launcher
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.DocumentsContract
|
||||
@@ -12,10 +13,13 @@ import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.AbsoluteRoundedCornerShape
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
@@ -34,6 +38,7 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -44,8 +49,10 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -594,6 +601,82 @@ fun ErrorInfoActions(extraDetails: String?, modifier: Modifier = Modifier) {
|
||||
}
|
||||
}
|
||||
|
||||
fun onDownloadGame(context: Context) {
|
||||
val appUrl = "https://play.google.com/store/apps/details?id=${Constants.PACKAGE_NAME}"
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
data = Uri.parse(appUrl)
|
||||
setPackage("com.android.vending")
|
||||
}
|
||||
context.startActivity(intent)
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
Toast.makeText(context, R.string.no_activity_found, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun GooglePlayBadge(modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.google_play_badge),
|
||||
contentDescription = stringResource(R.string.launcher_download_game),
|
||||
modifier = modifier
|
||||
.width(196.dp)
|
||||
.clip(AbsoluteRoundedCornerShape(4.dp))
|
||||
.clickable { onDownloadGame(context) }
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DownloadRecommendation(needsUniversal: Boolean, modifier: Modifier = Modifier) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val context = LocalContext.current
|
||||
val version = BuildConfig.VERSION_NAME
|
||||
|
||||
val showDownload = remember {
|
||||
!GamePackageUtils.isGameInstalled(context.packageManager) ||
|
||||
!GamePackageUtils.identifyGameLegitimacy(context.packageManager)
|
||||
}
|
||||
|
||||
val downloadBase = "https://github.com/geode-sdk/android-launcher/releases/download/$version"
|
||||
val legacyDownloadUrl = "$downloadBase/geode-launcher-v$version-android32.apk"
|
||||
val universalDownloadUrl = "$downloadBase/geode-launcher-v$version.apk"
|
||||
|
||||
val downloadUrl = if (needsUniversal)
|
||||
universalDownloadUrl else legacyDownloadUrl
|
||||
|
||||
val downloadText = if (needsUniversal)
|
||||
stringResource(R.string.launcher_download_universal)
|
||||
else
|
||||
stringResource(R.string.launcher_download_32bit)
|
||||
|
||||
Column(
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(
|
||||
12.dp, alignment = Alignment.CenterVertically
|
||||
)
|
||||
) {
|
||||
ClickableText(
|
||||
text = AnnotatedString(downloadText),
|
||||
onClick = {
|
||||
uriHandler.openUri(downloadUrl)
|
||||
},
|
||||
|
||||
style = TextStyle.Default.copy(
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
textDecoration = TextDecoration.Underline
|
||||
),
|
||||
)
|
||||
|
||||
if (showDownload) {
|
||||
GooglePlayBadge(
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ErrorInfoSheet(failureInfo: LoadFailureInfo, onDismiss: () -> Unit) {
|
||||
@@ -611,13 +694,21 @@ fun ErrorInfoSheet(failureInfo: LoadFailureInfo, onDismiss: () -> Unit) {
|
||||
|
||||
ErrorInfoBody(failureInfo.title)
|
||||
|
||||
if (failureInfo.description != null) {
|
||||
if (failureInfo.description != null && !failureInfo.title.isAbiFailure()) {
|
||||
ErrorInfoDescription(
|
||||
failureInfo.description,
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
if (failureInfo.title.isAbiFailure()) {
|
||||
DownloadRecommendation(
|
||||
needsUniversal = failureInfo.title == LaunchUtils.LauncherError.LINKER_NEEDS_64BIT,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp, bottom = 16.dp)
|
||||
)
|
||||
} else {
|
||||
ErrorInfoActions(
|
||||
extraDetails = failureInfo.extendedMessage ?: failureInfo.description,
|
||||
modifier = Modifier
|
||||
@@ -628,6 +719,7 @@ fun ErrorInfoSheet(failureInfo: LoadFailureInfo, onDismiss: () -> Unit) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onLaunch(context: Context, safeMode: Boolean = false) {
|
||||
if (safeMode) {
|
||||
@@ -782,8 +874,17 @@ fun PlayButton(
|
||||
fun LaunchBlockedLabel(text: String) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val showDownload = remember {
|
||||
!GamePackageUtils.isGameInstalled(context.packageManager) ||
|
||||
!GamePackageUtils.identifyGameLegitimacy(context.packageManager)
|
||||
}
|
||||
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(text, modifier = Modifier.padding(12.dp))
|
||||
Text(text, textAlign = TextAlign.Center, modifier = Modifier.padding(12.dp))
|
||||
|
||||
if (showDownload) {
|
||||
GooglePlayBadge()
|
||||
} else {
|
||||
OutlinedButton(onClick = { onSettings(context) }) {
|
||||
Icon(Icons.Filled.Settings, contentDescription = null)
|
||||
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
|
||||
@@ -791,6 +892,7 @@ fun LaunchBlockedLabel(text: String) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MainScreen(
|
||||
@@ -868,7 +970,11 @@ fun MainScreen(
|
||||
}
|
||||
|
||||
if (gdVersion < Constants.SUPPORTED_VERSION_CODE) {
|
||||
LaunchBlockedLabel(stringResource(R.string.game_outdated))
|
||||
val versionName = remember {
|
||||
GamePackageUtils.getUnifiedVersionName(context.packageManager)
|
||||
}
|
||||
|
||||
LaunchBlockedLabel(stringResource(R.string.game_outdated, versionName))
|
||||
} else {
|
||||
val stopLaunch = releaseViewModel.isInUpdate || hasError
|
||||
PlayButton(
|
||||
|
||||
@@ -36,6 +36,19 @@ object GamePackageUtils {
|
||||
return game.versionName
|
||||
}
|
||||
|
||||
private val gameVersionMap = mapOf(
|
||||
37L to "2.200",
|
||||
38L to "2.205"
|
||||
)
|
||||
|
||||
/**
|
||||
* Gets the version name that more closely aligns to the Windows/macOS releases
|
||||
*/
|
||||
fun getUnifiedVersionName(packageManager: PackageManager): String {
|
||||
val versionCode = getGameVersionCode(packageManager)
|
||||
return gameVersionMap[versionCode] ?: getGameVersionString(packageManager)
|
||||
}
|
||||
|
||||
fun detectAbiMismatch(context: Context, packageInfo: PackageInfo, loadException: Error): Boolean {
|
||||
val abi = LaunchUtils.applicationArchitecture
|
||||
val isExtracted =
|
||||
|
||||
@@ -359,8 +359,7 @@ object GeodeUtils {
|
||||
fun getGameVersion(): String {
|
||||
// these versions should be aligned to windows releases, not what android says
|
||||
activity.get()?.run {
|
||||
val versionCode = GamePackageUtils.getGameVersionCode(packageManager)
|
||||
return gameVersionMap[versionCode] ?: GamePackageUtils.getGameVersionString(packageManager)
|
||||
return GamePackageUtils.getUnifiedVersionName(packageManager)
|
||||
}
|
||||
|
||||
return ""
|
||||
|
||||
@@ -97,7 +97,11 @@ object LaunchUtils {
|
||||
LINKER_NEEDS_32BIT,
|
||||
LINKER_FAILED,
|
||||
GENERIC,
|
||||
CRASHED
|
||||
CRASHED;
|
||||
|
||||
fun isAbiFailure(): Boolean {
|
||||
return this == LINKER_NEEDS_32BIT || this == LINKER_NEEDS_64BIT
|
||||
}
|
||||
}
|
||||
|
||||
const val LAUNCHER_KEY_RETURN_ERROR = "return_error"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -11,10 +11,14 @@
|
||||
<string name="launcher_logo_alt">geode logo</string>
|
||||
<string name="launcher_launch_icon_alt">play icon</string>
|
||||
<string name="launcher_download_icon_alt">download icon</string>
|
||||
<string name="launcher_purchase_reminder">If you enjoy the game, please consider purchasing it for a smoother launcher experience.</string>
|
||||
<string name="launcher_download_game">Download Game</string>
|
||||
<string name="launcher_download_32bit">Download the 32-bit version of launcher.</string>
|
||||
<string name="launcher_download_universal">Download the non 32-bit version of launcher.</string>
|
||||
<string name="launcher_settings_icon_alt">settings icon</string>
|
||||
<string name="launcher_retry_icon_alt">retry icon</string>
|
||||
<string name="geode_download_title">Geode is not installed.</string>
|
||||
<string name="game_outdated">A Geometry Dash update is required.</string>
|
||||
<string name="game_outdated">A Geometry Dash update is required.\nYou currently have version %1$s.</string>
|
||||
<string name="geode_download_description">Geode is downloading. Please wait.</string>
|
||||
<plurals name="automatically_load_countdown">
|
||||
<item quantity="one">Automatically launching game in %1$d second.</item>
|
||||
@@ -65,7 +69,7 @@
|
||||
<string name="load_failed_generic_error_description">Uncaught error during game load. Try to:</string>
|
||||
<string name="load_failed_crashed">Geode crashed</string>
|
||||
<string name="load_failed_crashed_description">A crash was reported during the last session. Try to:</string>
|
||||
<string name="load_failed_recommendation_reinstall">Reinstall Geometry Dash from the Play Store.</string>
|
||||
<string name="load_failed_recommendation_reinstall">Reinstall Geometry Dash.</string>
|
||||
<string name="load_failed_recommendation_switch_32bit_abi">Install the 32-bit version of the launcher.</string>
|
||||
<string name="load_failed_recommendation_switch_64bit_abi">Install the non 32-bit version of the launcher.</string>
|
||||
<string name="load_failed_recommendation_update">Verify that the latest versions of the launcher and Geometry Dash are installed.</string>
|
||||
|
||||
Reference in new issue
Block a user