mirror of
https://github.com/revanced/revanced-manager
synced 2024-05-14 13:56:57 +02:00
fix: bundles not loading on Android 14
This commit is contained in:
parent
4b12ae1531
commit
18cfb56b45
@ -10,8 +10,10 @@ import java.nio.file.StandardCopyOption
|
||||
class LocalPatchBundle(name: String, id: Int, directory: File) : PatchBundleSource(name, id, directory) {
|
||||
suspend fun replace(patches: InputStream? = null, integrations: InputStream? = null) {
|
||||
withContext(Dispatchers.IO) {
|
||||
patches?.let {
|
||||
Files.copy(it, patchesFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
patches?.let { inputStream ->
|
||||
patchBundleOutputStream().use { outputStream ->
|
||||
inputStream.copyTo(outputStream)
|
||||
}
|
||||
}
|
||||
integrations?.let {
|
||||
Files.copy(it, this@LocalPatchBundle.integrationsFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
|
@ -6,6 +6,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import java.io.File
|
||||
import java.io.OutputStream
|
||||
|
||||
/**
|
||||
* A [PatchBundle] source.
|
||||
@ -23,6 +24,16 @@ sealed class PatchBundleSource(val name: String, val uid: Int, directory: File)
|
||||
*/
|
||||
fun hasInstalled() = patchesFile.exists()
|
||||
|
||||
protected fun patchBundleOutputStream(): OutputStream = with(patchesFile) {
|
||||
// Android 14+ requires dex containers to be readonly.
|
||||
try {
|
||||
setWritable(true, true)
|
||||
outputStream()
|
||||
} finally {
|
||||
setReadOnly()
|
||||
}
|
||||
}
|
||||
|
||||
private fun load(): State {
|
||||
if (!hasInstalled()) return State.Missing
|
||||
|
||||
@ -40,7 +51,7 @@ sealed class PatchBundleSource(val name: String, val uid: Int, directory: File)
|
||||
sealed interface State {
|
||||
fun patchBundleOrNull(): PatchBundle? = null
|
||||
|
||||
object Missing : State
|
||||
data object Missing : State
|
||||
data class Failed(val throwable: Throwable) : State
|
||||
data class Loaded(val bundle: PatchBundle) : State {
|
||||
override fun patchBundleOrNull() = bundle
|
||||
|
@ -33,16 +33,19 @@ sealed class RemotePatchBundle(name: String, id: Int, directory: File, val endpo
|
||||
private suspend fun download(info: BundleInfo) = withContext(Dispatchers.IO) {
|
||||
val (patches, integrations) = info
|
||||
coroutineScope {
|
||||
mapOf(
|
||||
patches.url to patchesFile,
|
||||
integrations.url to integrationsFile
|
||||
).forEach { (asset, file) ->
|
||||
launch {
|
||||
http.download(file) {
|
||||
url(asset)
|
||||
launch {
|
||||
patchBundleOutputStream().use {
|
||||
http.streamTo(it) {
|
||||
url(patches.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
http.download(integrationsFile) {
|
||||
url(integrations.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveVersion(patches.version, integrations.version)
|
||||
|
@ -18,8 +18,11 @@ import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.core.isNotEmpty
|
||||
import io.ktor.utils.io.core.readBytes
|
||||
import it.skrape.core.htmlDocument
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
import java.io.OutputStream
|
||||
|
||||
/**
|
||||
* @author Aliucord Authors, DiamondMiner88
|
||||
@ -49,7 +52,10 @@ class HttpService(
|
||||
null
|
||||
}
|
||||
|
||||
Log.e(tag, "Failed to fetch: API error, http status: ${response.status}, body: $body")
|
||||
Log.e(
|
||||
tag,
|
||||
"Failed to fetch: API error, http status: ${response.status}, body: $body"
|
||||
)
|
||||
APIResponse.Error(APIError(response.status, body))
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
@ -59,20 +65,19 @@ class HttpService(
|
||||
return response
|
||||
}
|
||||
|
||||
suspend fun download(
|
||||
saveLocation: File,
|
||||
suspend fun streamTo(
|
||||
outputStream: OutputStream,
|
||||
builder: HttpRequestBuilder.() -> Unit
|
||||
) {
|
||||
http.prepareGet(builder).execute { httpResponse ->
|
||||
if (httpResponse.status.isSuccess()) {
|
||||
|
||||
saveLocation.outputStream().use { stream ->
|
||||
val channel: ByteReadChannel = httpResponse.body()
|
||||
val channel: ByteReadChannel = httpResponse.body()
|
||||
withContext(Dispatchers.IO) {
|
||||
while (!channel.isClosedForRead) {
|
||||
val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
|
||||
while (packet.isNotEmpty) {
|
||||
val bytes = packet.readBytes()
|
||||
stream.write(bytes)
|
||||
outputStream.write(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,6 +88,11 @@ class HttpService(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun download(
|
||||
saveLocation: File,
|
||||
builder: HttpRequestBuilder.() -> Unit
|
||||
) = saveLocation.outputStream().use { streamTo(it, builder) }
|
||||
|
||||
suspend fun getHtml(builder: HttpRequestBuilder.() -> Unit) = htmlDocument(
|
||||
html = http.get(builder).bodyAsText()
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user