8000 Lower minimum api to 28 by LossyDragon · Pull Request #262 · oxters168/Pluvia · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Lower minimum api to 28 #262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions app/build.gradle.kts
8000
Original file line numberDiff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ android {
defaultConfig {
applicationId = "com.OxGames.Pluvia"

minSdk = 29
targetSdk = 34
minSdk = 28
//noinspection ExpiredTargetSdkVersion
targetSdk = 28

versionCode = 7
versionName = "1.3.2"
Expand Down Expand Up @@ -167,13 +168,13 @@ dependencies {
}
}
implementation(libs.spongycastle)
implementation(libs.zstd.jni) { artifact { type = "aar" } }

// Split Modules
implementation(libs.bundles.google)

// Winlator
implementation(libs.bundles.winlator)
implementation(libs.zstd.jni) { artifact { type = "aar" } }

// Jetpack Compose
implementation(platform(libs.androidx.compose.bom))
Expand Down
13 changes: 9 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!--
- android:requestLegacyExternalStorage="true" allows us to access the devices user storage with API 28.
- android:usesCleartextTraffic="true" allows us to talk to HTTP only CDNs from Steam.
- android:windowSoftInputMode must always be in the activity block. This solves IME resizing issues.
-->

<application
android:name=".PluviaApp"
Expand All @@ -20,14 +28,11 @@
android:icon="${icon}"
android:isGame="true"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="${roundIcon}"
android:supportsRtl="true"
android:theme="@style/Theme.Pluvia"
android:usesCleartextTraffic="true">
<!--
android:windowSoftInputMode must always be in the activity block.
IME padding with composables like 'Scaffold' will have terrible resizing consequences, if in the activity tag.
-->
<activity
android:name=".MainActivity"
android:exported="true"
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/com/OxGames/Pluvia/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,25 @@ class MainActivity : ComponentActivity() {
}

private val onSetSystemUi: (AndroidEvent.SetSystemUIVisibility) -> Unit = {
Timber.i("onSetSystemUi: ${it.visible}")
AppUtils.hideSystemUI(this, !it.visible)
}

private val onSetAllowedOrientation: (AndroidEvent.SetAllowedOrientation) -> Unit = {
// Log.d("MainActivity", "Requested allowed orientations of $it")
Timber.i("onSetAllowedOrientation called: $it")
availableOrientations = it.orientations
setOrientationTo(currentOrientationChangeValue, availableOrientations)
}

private val onStartOrientator: (AndroidEvent.StartOrientator) -> Unit = {
Timber.i("onStartOrientator called")
// TODO: When rotating the device on login screen:
// StrictMode policy violation: android.os.strictmode.LeakedClosableViolation: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
startOrientator()
}

private val onEndProcess: (AndroidEvent.EndProcess) -> Unit = {
Timber.i("onEndProcess called")
finishAndRemoveTask()
}

Expand All @@ -87,6 +90,7 @@ class MainActivity : ComponentActivity() {
val permissionLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
) { isGranted ->
Timber.i("Notification permission was granted: $isGranted")
hasNotificationPermission = isGranted
}

Expand Down Expand Up @@ -139,7 +143,7 @@ class MainActivity : ComponentActivity() {
PluviaApp.events.off<AndroidEvent.SetAllowedOrientation, Unit>(onSetAllowedOrientation)
PluviaApp.events.off<AndroidEvent.EndProcess, Unit>(onEndProcess)

Timber.d(
Timber.i(
"onDestroy - Index: %d, Connected: %b, Logged-In: %b, Changing-Config: %b",
index,
SteamService.isConnected,
Expand Down
38 changes: 21 additions & 17 deletions app/src/main/java/com/OxGames/Pluvia/PrefManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.OxGames.Pluvia.enums.AppFilter
import com.OxGames.Pluvia.enums.AppTheme
import com.OxGames.Pluvia.enums.HomeDestination
import com.OxGames.Pluvia.enums.Orientation
import com.OxGames.Pluvia.service.SteamService
import com.OxGames.Pluvia.utils.application.Crypto
import com.materialkolor.PaletteStyle
import com.winlator.box86_64.Box86_64Preset
Expand Down Expand Up @@ -89,20 +88,39 @@ object PrefManager {
getPref(stringPreferencesKey(key), defaultValue)

@Suppress("SameParameterValue")
private fun <T> getPref(key: Preferences.Key<T>, defaultValue: T): T = runBlocking {
dataStore.data.first()[key] ?: defaultValue
private fun <T> getPref(key: Preferences.Key<T>, defaultValue: T): T = runBlocking(Dispatchers.IO) {
val result = dataStore.data.first()[key] ?: defaultValue

val blacklist = listOf(
CLIENT_ID.name, USER_NAME.name, ACCESS_TOKEN_ENC.name, REFRESH_TOKEN_ENC.name,
"access_token", "refresh_token", "password", // Legacy keys
)
if (key.name !in blacklist) {
Timber.i("Getting preference: ${key.name} with value: $result")
}

result
}

@Suppress("SameParameterValue")
private fun <T> setPref(key: Preferences.Key<T>, value: T) {
scope.launch {
dataStore.edit { pref -> pref[key] = value }

val blacklist = listOf(
CLIENT_ID.name, USER_NAME.name, ACCESS_TOKEN_ENC.name, REFRESH_TOKEN_ENC.name,
"access_token", "refresh_token", "password", // Legacy keys
)
if (key.name !in blacklist) {
Timber.i("Setting preference: ${key.name} with value: $value")
}
}
}

private fun <T> removePref(key: Preferences.Key<T>) {
scope.launch {
dataStore.edit { pref -> pref.remove(key) }
Timber.i("Removing preference: ${key.name}")
}
}

Expand Down Expand Up @@ -286,20 +304,6 @@ object PrefManager {
// endregion

// region Login Info
private val APP_INSTALL_PATH = stringPreferencesKey("app_install_path")
var appInstallPath: String
get() = getPref(APP_INSTALL_PATH, SteamService.defaultAppInstallPath)
set(value) {
setPref(APP_INSTALL_PATH, value)
}

private val APP_STAGING_PATH = stringPreferencesKey("app_staging_path")
var appStagingPath: String
get() = getPref(APP_STAGING_PATH, SteamService.defaultAppStagingPath)
set(value) {
setPref(APP_STAGING_PATH, value)
}

// Special: Because null value.
private val CLIENT_ID = longPreferencesKey("client_id")
var clientId: Long?
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/com/OxGames/Pluvia/events/AndroidEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ interface AndroidEvent<T> : Event<T> {
data class SetAllowedOrientation(val orientations: EnumSet<Orientation>) : AndroidEvent<Unit>
data class SetSystemUIVisibility(val visible: Boolean) : AndroidEvent<Unit>
data object ActivityDestroyed : AndroidEvent<Unit>

@Deprecated("BackPressed doesn't seem to have a use case")
data object BackPressed : AndroidEvent<Unit>

data object EndProcess : AndroidEvent<Unit>
data object GuestProgramTerminated : AndroidEvent<Unit>
data object StartOrientator : AndroidEvent<Unit>
Expand Down
91 changes: 35 additions & 56 deletions app/src/main/java/com/OxGames/Pluvia/service/SteamService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.OxGames.Pluvia.service
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Environment
import android.os.IBinder
import androidx.room.withTransaction
import com.OxGames.Pluvia.BuildConfig
Expand Down Expand Up @@ -103,14 +104,15 @@ import `in`.dragonbra.javasteam.util.NetHelpers
import `in`.dragonbra.javasteam.util.log.LogListener
import `in`.dragonbra.javasteam.util.log.LogManager
import java.io.Closeable
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
import java.util.Collections
import java.util.EnumSet
import java.util.concurrent.CancellationException
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.deleteRecursively
import kotlin.io.path.pathString
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -193,6 +195,15 @@ class SteamService : Service(), IChallengeUrlChanged {
private var familyGroupMembers: ArrayList<Int> = arrayListOf()

companion object {
/* Main File Location */
private val baseDir by lazy { Environment.getExternalStorageDirectory().absolutePath }
private val pluviaPath by lazy { Paths.get(baseDir, "Pluvia") } // Yes, this is hardcoded for now.
val steamPath by lazy { pluviaPath.resolve("Steam") }
private val depotManifestsPath by lazy { steamPath.resolve("depot_manifests.zip") }
private val defaultAppInstallPath by lazy { steamPath.resolve("steamapps/common") }
private val defaultAppStagingPath by lazy { steamPath.resolve("steamapps/staging") }
private val serverListPath by lazy { instance!!.cacheDir.toPath().resolve("server_list.bin") }

private val PICS_CHANGE_CHECK_DELAY = 60.seconds

const val MAX_SIMULTANEOUS_PICS_REQUESTS = 50
Expand Down Expand Up @@ -234,44 +245,6 @@ class SteamService : Service(), IChallengeUrlChanged {
var isWaitingForQRAuth: Boolean = false
private set

// 'cached' variables are a hack to fix 'DiskReadViolation'

private var cachedServerListPath: String? = null
private val serverListPath: String
get() {
cachedServerListPath?.let { return it }
val value = Paths.get(instance!!.cacheDir.path, "server_list.bin").pathString
cachedServerListPath = value
return value
}

private var cachedDepotManifestsPath: String? = null
private val depotManifestsPath: String
get() {
cachedDepotManifestsPath?.let { return it }
val value = Paths.get(instance!!.dataDir.path, "Steam", "depot_manifests.zip").pathString
cachedDepotManifestsPath = value
return value
}

private var cachedDefaultAppInstallPath: String? = null
val defaultAppInstallPath: String
get() {
cachedDefaultAppInstallPath?.let { return it }
val value = Paths.get(instance!!.dataDir.path, "Steam", "steamapps", "common").pathString
cachedDefaultAppInstallPath = value
return value
}

private var cachedDefaultAppStagingPath: String? = null
val defaultAppStagingPath: String
get() {
cachedDefaultAppStagingPath?.let { return it }
val value = Paths.get(instance!!.dataDir.path, "Steam", "steamapps", "staging").pathString
cachedDefaultAppStagingPath = value
return value
}

val userSteamId: SteamID?
get() = instance?.steamClient?.steamID

Expand Down Expand Up @@ -365,7 +338,7 @@ class SteamService : Service(), IChallengeUrlChanged {
fun getOwnedAppDlc(appId: Int): Map<Int, DepotInfo> = getAppDlc(appId).filter {
getPkgInfoOf(it.value.dlcAppId)?.let { pkg ->
instance?.steamClient?.let { steamClient ->
pkg.ownerAccountId.contains(steamClient.steamID.accountID.toInt())
pkg.ownerAccountId.contains(steamClient.steamID!!.accountID.toInt())
}
} == true
}
Expand All @@ -386,24 +359,32 @@ class SteamService : Service(), IChallengeUrlChanged {
appName = getAppInfoOf(appId)?.name.orEmpty()
}

return Paths.get(PrefManager.appInstallPath, appName).pathString
return defaultAppInstallPath.resolve(appName).pathString
}

fun deleteApp(appId: Int): Boolean {
with(instance!!) {
scope.launch {
@OptIn(ExperimentalPathApi::class)
suspend fun deleteApp(appId: Int, isUninstalling: (Boolean) -> Unit) {
withContext(Dispatchers.Main) {
isUninstalling(true)
}

withContext(Dispatchers.IO) {
with(instance!!) {
db.withTransaction {
changeNumbersDao.deleteByAppId(appId)
fileChangeListsDao.deleteByAppId(appId)
}
}
}

val appDirPath = getAppDirPath(appId)
appCache.remove(appId)

appCache.remove(appId)
val appDirPath = getAppDirPath(appId)
Paths.get(appDirPath).deleteRecursively()
}

return File(appDirPath).deleteRecursively()
withContext(Dispatchers.Main) {
isUninstalling(false)
}
}

fun downloadApp(appId: Int): DownloadInfo? {
Expand Down Expand Up @@ -513,8 +494,8 @@ class SteamService : Service(), IChallengeUrlChanged {
ContentDownloader(instance!!.steamClient!!).downloadApp(
appId = appId,
depotId = depotId,
installPath = PrefManager.appInstallPath,
stagingPath = PrefManager.appStagingPath,
installPath = defaultAppInstallPath.pathString,
stagingPath = defaultAppStagingPath.pathString,
branch = branch,
// maxDownloads = 1,
downloadInfo.setProgress(it, jobIndex + indexOffset) },
Expand Down Expand Up @@ -1062,7 +1043,7 @@ class SteamService : Service(), IChallengeUrlChanged {
// Notification intents
when (intent?.action) {
NotificationHelper.ACTION_EXIT -> {
Timber.d("Exiting app via notification intent")
Timber.i("Exiting app via notification intent")

val event = AndroidEvent.EndProcess
PluviaApp.events.emit(event)
Expand All @@ -1077,8 +1058,8 @@ class SteamService : Service(), IChallengeUrlChanged {
val configuration = SteamConfiguration.create {
it.withProtocolTypes(PROTOCOL_TYPES)
it.withCellID(PrefManager.cellId)
it.withServerListProvider(FileServerListProvider(File(serverListPath)))
it.withManifestProvider(FileManifestProvider(File(depotManifestsPath)))
it.withServerListProvider(FileServerListProvider(serverListPath))
it.withManifestProvider(FileManifestProvider(depotManifestsPath))
}

// create our steam client instance< 4D1F /span>
Expand Down Expand Up @@ -1162,6 +1143,7 @@ class SteamService : Service(), IChallengeUrlChanged {

override fun onBind(intent: Intent?): IBinder? = null

// TODO this gets called to fast (and too many times) when there is no WIFI connection?
private fun connectToSteam() {
CoroutineScope(Dispatchers.Default).launch {
// this call errors out if run on the main thread
Expand Down Expand Up @@ -1212,9 +1194,6 @@ class SteamService : Service(), IChallengeUrlChanged {
isLoggingOut = false
isWaitingForQRAuth = false

PrefManager.appInstallPath = defaultAppInstallPath
PrefManager.appStagingPath = defaultAppStagingPath

steamClient = null
_steamUser = null
_steamApps = null
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/OxGames/Pluvia/ui/PluviaMain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,14 @@ fun PluviaMain(

LaunchedEffect(lifecycleOwner) {
if (!state.isSteamConnected) {
Timber.i("Starting Steam service.")
val intent = Intent(context, SteamService::class.java)
context.startForegroundService(intent)
}

// Go to the Home screen if we're already logged in.
if (SteamService.isLoggedIn && state.currentScreen == PluviaScreen.LoginUser) {
Timber.i("Navigating to Home")
navController.navigate(PluviaScreen.Home.route)
}
}
Expand Down
Loading
0