diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt index 537ee6df4..9fc7bf556 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/icon/CustomBrandingIconPatch.kt @@ -11,6 +11,7 @@ import app.revanced.patches.music.utils.playservice.versionCheckPatch import app.revanced.patches.music.utils.settings.ResourceUtils.setIconType import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus import app.revanced.patches.music.utils.settings.settingsPatch +import app.revanced.util.FilesCompat import app.revanced.util.ResourceGroup import app.revanced.util.Utils.trimIndentMultiline import app.revanced.util.copyAdaptiveIcon @@ -20,7 +21,6 @@ import app.revanced.util.underBarOrThrow import app.revanced.util.valueOrThrow import org.w3c.dom.Element import java.io.File -import java.nio.file.Files private const val ADAPTIVE_ICON_BACKGROUND_FILE_NAME = "adaptiveproduct_youtube_music_background_color_108" @@ -155,9 +155,9 @@ val customBrandingIconPatch = resourcePatch( val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName) group.resources.forEach { iconFileName -> - Files.write( - toDirectory.resolve(iconFileName).toPath(), - fromDirectory.resolve(iconFileName).readBytes() + FilesCompat.copy( + fromDirectory.resolve(iconFileName), + toDirectory.resolve(iconFileName) ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/materialyou/BaseMaterialYouPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/materialyou/BaseMaterialYouPatch.kt index 64255a7a8..755f66559 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/materialyou/BaseMaterialYouPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/materialyou/BaseMaterialYouPatch.kt @@ -1,8 +1,8 @@ package app.revanced.patches.shared.materialyou import app.revanced.patcher.patch.ResourcePatchContext +import app.revanced.util.FilesCompat import org.w3c.dom.Element -import java.nio.file.Files private fun ResourcePatchContext.patchXmlFile( fromDir: String, @@ -17,7 +17,7 @@ private fun ResourcePatchContext.patchXmlFile( val fromDirectory = resourceDirectory.resolve(fromDir) val toDirectory = resourceDirectory.resolve(toDir) - if (!toDirectory.isDirectory) Files.createDirectories(toDirectory.toPath()) + if (!toDirectory.isDirectory) toDirectory.mkdirs() val fromXmlFile = fromDirectory.resolve(xmlFileName) val toXmlFile = toDirectory.resolve(xmlFileName) @@ -27,9 +27,9 @@ private fun ResourcePatchContext.patchXmlFile( } if (!toXmlFile.exists()) { - Files.copy( - fromXmlFile.toPath(), - toXmlFile.toPath() + FilesCompat.copy( + fromXmlFile, + toXmlFile ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/translations/BaseTranslationsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/translations/BaseTranslationsPatch.kt index cf65fe09b..a58bccf92 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/translations/BaseTranslationsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/translations/BaseTranslationsPatch.kt @@ -2,13 +2,12 @@ package app.revanced.patches.shared.translations import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.ResourcePatchContext +import app.revanced.util.FilesCompat import app.revanced.util.doRecursively import app.revanced.util.inputStreamFromBundledResource import org.w3c.dom.Element import org.w3c.dom.Node import java.io.File -import java.nio.file.Files -import java.nio.file.StandardCopyOption import javax.xml.parsers.DocumentBuilderFactory import javax.xml.transform.OutputKeys import javax.xml.transform.TransformerFactory @@ -173,12 +172,11 @@ private fun ResourcePatchContext.copyStringsXml( )?.let { inputStream -> val directory = "values-$language-v21" val valuesV21Directory = resourceDirectory.resolve(directory) - if (!valuesV21Directory.isDirectory) Files.createDirectories(valuesV21Directory.toPath()) + if (!valuesV21Directory.isDirectory) valuesV21Directory.mkdirs() - Files.copy( + FilesCompat.copy( inputStream, - resourceDirectory.resolve("$directory/strings.xml").toPath(), - StandardCopyOption.REPLACE_EXISTING + resourceDirectory.resolve("$directory/strings.xml") ) } } diff --git a/patches/src/main/kotlin/app/revanced/util/FilesCompat.kt b/patches/src/main/kotlin/app/revanced/util/FilesCompat.kt new file mode 100644 index 000000000..6bd4a93ed --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/util/FilesCompat.kt @@ -0,0 +1,53 @@ +package app.revanced.util + +import java.io.File +import java.io.InputStream +import java.nio.file.Files +import java.nio.file.StandardCopyOption + +/** + * Provides java.nio.file.Files compatible functions. + * + * This is needed for the ReVanced Manager running on Android 5.0-7.1 + * because Android 7.1 and below does not support the Java NIO2 Files API. + */ +internal object FilesCompat { + private val useCompat = try { + // Check for the existence of java.nio.file.Files class + Class.forName("java.nio.file.Files") + false + } catch (_ : ClassNotFoundException) { + // Under Android 8.0 + true + } + + /** + * Copy a file to a target file. + * + * If the `target` file already exists, replace an existing file. + */ + fun copy(source: File, target: File) { + if (useCompat) { + source.copyTo(target, overwrite = true) + } else { + Files.copy(source.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING) + } + } + + /** + * Copies all bytes from an input stream to a file. + * + * If the `target` file already exists, replace an existing file. + */ + fun copy(source: InputStream, target: File) { + if (useCompat) { + source.use { inputStream -> + target.outputStream().use { outputStream -> + inputStream.copyTo(outputStream) + } + } + } else { + Files.copy(source, target.toPath(), StandardCopyOption.REPLACE_EXISTING) + } + } +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/util/ResourceUtils.kt b/patches/src/main/kotlin/app/revanced/util/ResourceUtils.kt index 04984db7c..04302c9b1 100644 --- a/patches/src/main/kotlin/app/revanced/util/ResourceUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/ResourceUtils.kt @@ -11,8 +11,6 @@ import org.w3c.dom.Node import org.w3c.dom.NodeList import java.io.File import java.io.InputStream -import java.nio.file.Files -import java.nio.file.StandardCopyOption private val classLoader = object {}.javaClass.classLoader @@ -115,14 +113,9 @@ fun ResourcePatchContext.copyAdaptiveIcon( if (oldIconResourceFile != newIconResourceFile) { mipmapDirectories.forEach { val mipmapDirectory = get("res").resolve(it) - Files.copy( - mipmapDirectory - .resolve("$oldIconResourceFile.png") - .toPath(), - mipmapDirectory - .resolve("$newIconResourceFile.png") - .toPath(), - StandardCopyOption.REPLACE_EXISTING + FilesCompat.copy( + mipmapDirectory.resolve("$oldIconResourceFile.png"), + mipmapDirectory.resolve("$newIconResourceFile.png") ) } } @@ -132,14 +125,9 @@ fun ResourcePatchContext.copyAdaptiveIcon( adaptiveIconMonoChromeFileName != getAdaptiveIconMonoChromeResourceFile() ) { val drawableDirectory = get("res").resolve("drawable") - Files.copy( - drawableDirectory - .resolve("$adaptiveIconMonoChromeFileName.xml") - .toPath(), - drawableDirectory - .resolve("${getAdaptiveIconMonoChromeResourceFile()}.xml") - .toPath(), - StandardCopyOption.REPLACE_EXISTING + FilesCompat.copy( + drawableDirectory.resolve("$adaptiveIconMonoChromeFileName.xml"), + drawableDirectory.resolve("${getAdaptiveIconMonoChromeResourceFile()}.xml") ) } } @@ -201,9 +189,9 @@ fun ResourcePatchContext.copyFile( val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName) group.resources.forEach { iconFileName -> - Files.write( - toDirectory.resolve(iconFileName).toPath(), - fromDirectory.resolve(iconFileName).readBytes() + FilesCompat.copy( + fromDirectory.resolve(iconFileName), + toDirectory.resolve(iconFileName) ) } } @@ -307,16 +295,15 @@ fun ResourcePatchContext.copyResources( resourceGroup.resources.forEach { resource -> val resourceDirectoryName = resourceGroup.resourceDirectoryName val targetDirectory = resourceDirectory.resolve(resourceDirectoryName) - if (!targetDirectory.isDirectory) Files.createDirectories(targetDirectory.toPath()) + if (!targetDirectory.isDirectory) targetDirectory.mkdirs() val resourceFile = "$resourceDirectoryName/$resource" inputStreamFromBundledResource( sourceResourceDirectory, resourceFile )?.let { inputStream -> - Files.copy( + FilesCompat.copy( inputStream, - resourceDirectory.resolve(resourceFile).toPath(), - StandardCopyOption.REPLACE_EXISTING, + resourceDirectory.resolve(resourceFile), ) } }