mirror of
https://github.com/revanced/revanced-cli.git
synced 2024-12-12 05:07:48 +01:00
feat: Allow selecting first Adb device, if none supplied automatically by updating dependencies
This commit is contained in:
parent
3765957043
commit
e7c3d64bf1
@ -116,7 +116,7 @@ ReVanced CLI is divided into the following fundamental commands:
|
|||||||
```bash
|
```bash
|
||||||
java -jar revanced-cli.jar utility uninstall \
|
java -jar revanced-cli.jar utility uninstall \
|
||||||
--package-name <package-name> \
|
--package-name <package-name> \
|
||||||
<device-serial>
|
[<device-serial>]
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
@ -128,7 +128,7 @@ ReVanced CLI is divided into the following fundamental commands:
|
|||||||
```bash
|
```bash
|
||||||
java -jar revanced-cli.jar utility install \
|
java -jar revanced-cli.jar utility install \
|
||||||
-a input.apk \
|
-a input.apk \
|
||||||
<device-serial>
|
[<device-serial>]
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
[versions]
|
[versions]
|
||||||
shadow = "8.1.1"
|
shadow = "8.1.1"
|
||||||
kotlin-test = "1.9.10"
|
kotlin-test = "1.9.20"
|
||||||
kotlinx-coroutines-core = "1.7.3"
|
kotlinx-coroutines-core = "1.7.3"
|
||||||
picocli = "4.7.3"
|
picocli = "4.7.3"
|
||||||
revanced-patcher = "19.0.0"
|
revanced-patcher = "19.0.0"
|
||||||
revanced-library = "1.2.0"
|
revanced-library = "1.3.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin-test" }
|
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin-test" }
|
||||||
|
@ -18,10 +18,9 @@ import java.io.PrintWriter
|
|||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
|
|
||||||
|
|
||||||
@CommandLine.Command(
|
@CommandLine.Command(
|
||||||
name = "patch",
|
name = "patch",
|
||||||
description = ["Patch an APK file."]
|
description = ["Patch an APK file."],
|
||||||
)
|
)
|
||||||
internal object PatchCommand : Runnable {
|
internal object PatchCommand : Runnable {
|
||||||
private val logger = Logger.getLogger(PatchCommand::class.java.name)
|
private val logger = Logger.getLogger(PatchCommand::class.java.name)
|
||||||
@ -37,25 +36,25 @@ internal object PatchCommand : Runnable {
|
|||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-i", "--include"],
|
names = ["-i", "--include"],
|
||||||
description = ["List of patches to include."]
|
description = ["List of patches to include."],
|
||||||
)
|
)
|
||||||
private var includedPatches = hashSetOf<String>()
|
private var includedPatches = hashSetOf<String>()
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--ii"],
|
names = ["--ii"],
|
||||||
description = ["List of patches to include by their index in relation to the supplied patch bundles."]
|
description = ["List of patches to include by their index in relation to the supplied patch bundles."],
|
||||||
)
|
)
|
||||||
private var includedPatchesByIndex = arrayOf<Int>()
|
private var includedPatchesByIndex = arrayOf<Int>()
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-e", "--exclude"],
|
names = ["-e", "--exclude"],
|
||||||
description = ["List of patches to exclude."]
|
description = ["List of patches to exclude."],
|
||||||
)
|
)
|
||||||
private var excludedPatches = hashSetOf<String>()
|
private var excludedPatches = hashSetOf<String>()
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--ei"],
|
names = ["--ei"],
|
||||||
description = ["List of patches to exclude by their index in relation to the supplied patch bundles."]
|
description = ["List of patches to exclude by their index in relation to the supplied patch bundles."],
|
||||||
)
|
)
|
||||||
private var excludedPatchesByIndex = arrayOf<Int>()
|
private var excludedPatchesByIndex = arrayOf<Int>()
|
||||||
|
|
||||||
@ -68,14 +67,14 @@ internal object PatchCommand : Runnable {
|
|||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--exclusive"],
|
names = ["--exclusive"],
|
||||||
description = ["Only include patches that are explicitly specified to be included."],
|
description = ["Only include patches that are explicitly specified to be included."],
|
||||||
showDefaultValue = ALWAYS
|
showDefaultValue = ALWAYS,
|
||||||
)
|
)
|
||||||
private var exclusive = false
|
private var exclusive = false
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-f","--force"],
|
names = ["-f", "--force"],
|
||||||
description = ["Bypass compatibility checks for the supplied APK's version."],
|
description = ["Bypass compatibility checks for the supplied APK's version."],
|
||||||
showDefaultValue = ALWAYS
|
showDefaultValue = ALWAYS,
|
||||||
)
|
)
|
||||||
private var force: Boolean = false
|
private var force: Boolean = false
|
||||||
|
|
||||||
@ -91,48 +90,52 @@ internal object PatchCommand : Runnable {
|
|||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-d", "--device-serial"],
|
names = ["-d", "--device-serial"],
|
||||||
description = ["ADB device serial to install to."],
|
description = ["ADB device serial to install to. If not supplied, the first connected device will be used."],
|
||||||
|
fallbackValue = "", // Empty string to indicate that the first connected device should be used.
|
||||||
|
arity = "0..1",
|
||||||
)
|
)
|
||||||
private var deviceSerial: String? = null
|
private var deviceSerial: String? = null
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--mount"],
|
names = ["--mount"],
|
||||||
description = ["Install by mounting the patched APK file."],
|
description = ["Install by mounting the patched APK file."],
|
||||||
showDefaultValue = ALWAYS
|
showDefaultValue = ALWAYS,
|
||||||
)
|
)
|
||||||
private var mount: Boolean = false
|
private var mount: Boolean = false
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--keystore"],
|
names = ["--keystore"],
|
||||||
description = ["Path to the keystore to sign the patched APK file with. " +
|
description = [
|
||||||
"Defaults to the same directory as the supplied APK file."],
|
"Path to the keystore to sign the patched APK file with. " +
|
||||||
|
"Defaults to the same directory as the supplied APK file.",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
private var keystoreFilePath: File? = null
|
private var keystoreFilePath: File? = null
|
||||||
|
|
||||||
// key store password
|
// key store password
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--keystore-password"],
|
names = ["--keystore-password"],
|
||||||
description = ["The password of the keystore to sign the patched APK file with. Empty password by default."]
|
description = ["The password of the keystore to sign the patched APK file with. Empty password by default."],
|
||||||
)
|
)
|
||||||
private var keyStorePassword: String? = null // Empty password by default
|
private var keyStorePassword: String? = null // Empty password by default
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--alias"],
|
names = ["--alias"],
|
||||||
description = ["The alias of the key from the keystore to sign the patched APK file with."],
|
description = ["The alias of the key from the keystore to sign the patched APK file with."],
|
||||||
showDefaultValue = ALWAYS
|
showDefaultValue = ALWAYS,
|
||||||
)
|
)
|
||||||
private var alias = "ReVanced Key"
|
private var alias = "ReVanced Key"
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--keystore-entry-password"],
|
names = ["--keystore-entry-password"],
|
||||||
description = ["The password of the entry from the keystore for the key to sign the patched APK file with."]
|
description = ["The password of the entry from the keystore for the key to sign the patched APK file with."],
|
||||||
)
|
)
|
||||||
private var password = "" // Empty password by default
|
private var password = "" // Empty password by default
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--signer"],
|
names = ["--signer"],
|
||||||
description = ["The name of the signer to sign the patched APK file with."],
|
description = ["The name of the signer to sign the patched APK file with."],
|
||||||
showDefaultValue = ALWAYS
|
showDefaultValue = ALWAYS,
|
||||||
)
|
)
|
||||||
private var signer = "ReVanced"
|
private var signer = "ReVanced"
|
||||||
|
|
||||||
@ -147,33 +150,35 @@ internal object PatchCommand : Runnable {
|
|||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-p", "--purge"],
|
names = ["-p", "--purge"],
|
||||||
description = ["Purge the temporary resource cache directory after patching."],
|
description = ["Purge the temporary resource cache directory after patching."],
|
||||||
showDefaultValue = ALWAYS
|
showDefaultValue = ALWAYS,
|
||||||
)
|
)
|
||||||
private var purge: Boolean = false
|
private var purge: Boolean = false
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-w", "--warn"],
|
names = ["-w", "--warn"],
|
||||||
description = ["Warn if a patch can not be found in the supplied patch bundles."],
|
description = ["Warn if a patch can not be found in the supplied patch bundles."],
|
||||||
showDefaultValue = ALWAYS
|
showDefaultValue = ALWAYS,
|
||||||
)
|
)
|
||||||
private var warn: Boolean = false
|
private var warn: Boolean = false
|
||||||
|
|
||||||
@CommandLine.Parameters(
|
@CommandLine.Parameters(
|
||||||
description = ["APK file to be patched."],
|
description = ["APK file to be patched."],
|
||||||
arity = "1..1"
|
arity = "1..1",
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private fun setApk(apk: File) {
|
private fun setApk(apk: File) {
|
||||||
if (!apk.exists()) throw CommandLine.ParameterException(
|
if (!apk.exists()) {
|
||||||
|
throw CommandLine.ParameterException(
|
||||||
spec.commandLine(),
|
spec.commandLine(),
|
||||||
"APK file ${apk.name} does not exist"
|
"APK file ${apk.name} does not exist",
|
||||||
)
|
)
|
||||||
|
}
|
||||||
this.apk = apk
|
this.apk = apk
|
||||||
}
|
}
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-m", "--merge"],
|
names = ["-m", "--merge"],
|
||||||
description = ["One or more DEX files or containers to merge into the APK."]
|
description = ["One or more DEX files or containers to merge into the APK."],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private fun setIntegrations(integrations: Array<File>) {
|
private fun setIntegrations(integrations: Array<File>) {
|
||||||
@ -186,7 +191,7 @@ internal object PatchCommand : Runnable {
|
|||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["-b", "--patch-bundle"],
|
names = ["-b", "--patch-bundle"],
|
||||||
description = ["One or more bundles of patches."],
|
description = ["One or more bundles of patches."],
|
||||||
required = true
|
required = true,
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private fun setPatchBundles(patchBundles: Array<File>) {
|
private fun setPatchBundles(patchBundles: Array<File>) {
|
||||||
@ -198,14 +203,16 @@ internal object PatchCommand : Runnable {
|
|||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ["--custom-aapt2-binary"],
|
names = ["--custom-aapt2-binary"],
|
||||||
description = ["Path to a custom AAPT binary to compile resources with."]
|
description = ["Path to a custom AAPT binary to compile resources with."],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
private fun setAaptBinaryPath(aaptBinaryPath: File) {
|
private fun setAaptBinaryPath(aaptBinaryPath: File) {
|
||||||
if (!aaptBinaryPath.exists()) throw CommandLine.ParameterException(
|
if (!aaptBinaryPath.exists()) {
|
||||||
|
throw CommandLine.ParameterException(
|
||||||
spec.commandLine(),
|
spec.commandLine(),
|
||||||
"AAPT binary ${aaptBinaryPath.name} does not exist"
|
"AAPT binary ${aaptBinaryPath.name} does not exist",
|
||||||
)
|
)
|
||||||
|
}
|
||||||
this.aaptBinaryPath = aaptBinaryPath
|
this.aaptBinaryPath = aaptBinaryPath
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,22 +220,20 @@ internal object PatchCommand : Runnable {
|
|||||||
// region Setup
|
// region Setup
|
||||||
|
|
||||||
val outputFilePath = outputFilePath ?: File("").absoluteFile.resolve(
|
val outputFilePath = outputFilePath ?: File("").absoluteFile.resolve(
|
||||||
"${apk.nameWithoutExtension}-patched.${apk.extension}"
|
"${apk.nameWithoutExtension}-patched.${apk.extension}",
|
||||||
)
|
)
|
||||||
|
|
||||||
val resourceCachePath = resourceCachePath ?: outputFilePath.parentFile.resolve(
|
val resourceCachePath = resourceCachePath ?: outputFilePath.parentFile.resolve(
|
||||||
"${outputFilePath.nameWithoutExtension}-resource-cache"
|
"${outputFilePath.nameWithoutExtension}-resource-cache",
|
||||||
)
|
)
|
||||||
|
|
||||||
val optionsFile = optionsFile ?: outputFilePath.parentFile.resolve(
|
val optionsFile = optionsFile ?: outputFilePath.parentFile.resolve(
|
||||||
"${outputFilePath.nameWithoutExtension}-options.json"
|
"${outputFilePath.nameWithoutExtension}-options.json",
|
||||||
)
|
)
|
||||||
|
|
||||||
val keystoreFilePath = keystoreFilePath ?: outputFilePath.parentFile
|
val keystoreFilePath = keystoreFilePath ?: outputFilePath.parentFile
|
||||||
.resolve("${outputFilePath.nameWithoutExtension}.keystore")
|
.resolve("${outputFilePath.nameWithoutExtension}.keystore")
|
||||||
|
|
||||||
val adbManager = deviceSerial?.let { serial -> AdbManager.getAdbManager(serial, mount) }
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Load patches
|
// region Load patches
|
||||||
@ -238,7 +243,8 @@ internal object PatchCommand : Runnable {
|
|||||||
val patches = PatchBundleLoader.Jar(*patchBundles.toTypedArray())
|
val patches = PatchBundleLoader.Jar(*patchBundles.toTypedArray())
|
||||||
|
|
||||||
// Warn if a patch can not be found in the supplied patch bundles.
|
// Warn if a patch can not be found in the supplied patch bundles.
|
||||||
if (warn) patches.map { it.name }.toHashSet().let { availableNames ->
|
if (warn) {
|
||||||
|
patches.map { it.name }.toHashSet().let { availableNames ->
|
||||||
(includedPatches + excludedPatches).filter { name ->
|
(includedPatches + excludedPatches).filter { name ->
|
||||||
!availableNames.contains(name)
|
!availableNames.contains(name)
|
||||||
}
|
}
|
||||||
@ -246,6 +252,7 @@ internal object PatchCommand : Runnable {
|
|||||||
if (unknownPatches.isEmpty()) return@let
|
if (unknownPatches.isEmpty()) return@let
|
||||||
logger.warning("Unknown input of patches:\n${unknownPatches.joinToString("\n")}")
|
logger.warning("Unknown input of patches:\n${unknownPatches.joinToString("\n")}")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
@ -255,14 +262,17 @@ internal object PatchCommand : Runnable {
|
|||||||
resourceCachePath,
|
resourceCachePath,
|
||||||
aaptBinaryPath?.path,
|
aaptBinaryPath?.path,
|
||||||
resourceCachePath.absolutePath,
|
resourceCachePath.absolutePath,
|
||||||
true
|
true,
|
||||||
)
|
),
|
||||||
).use { patcher ->
|
).use { patcher ->
|
||||||
val filteredPatches = patcher.filterPatchSelection(patches).also { patches ->
|
val filteredPatches = patcher.filterPatchSelection(patches).also { patches ->
|
||||||
logger.info("Setting patch options")
|
logger.info("Setting patch options")
|
||||||
|
|
||||||
if (optionsFile.exists()) patches.setOptions(optionsFile)
|
if (optionsFile.exists()) {
|
||||||
else Options.serialize(patches, prettyPrint = true).let(optionsFile::writeText)
|
patches.setOptions(optionsFile)
|
||||||
|
} else {
|
||||||
|
Options.serialize(patches, prettyPrint = true).let(optionsFile::writeText)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// region Patch
|
// region Patch
|
||||||
@ -292,7 +302,8 @@ internal object PatchCommand : Runnable {
|
|||||||
ApkUtils.copyAligned(apk, this, patcherResult)
|
ApkUtils.copyAligned(apk, this, patcherResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mount) ApkUtils.sign(
|
if (!mount) {
|
||||||
|
ApkUtils.sign(
|
||||||
alignedFile,
|
alignedFile,
|
||||||
outputFilePath,
|
outputFilePath,
|
||||||
ApkUtils.SigningOptions(
|
ApkUtils.SigningOptions(
|
||||||
@ -300,16 +311,20 @@ internal object PatchCommand : Runnable {
|
|||||||
keyStorePassword,
|
keyStorePassword,
|
||||||
alias,
|
alias,
|
||||||
password,
|
password,
|
||||||
signer
|
signer,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
} else {
|
||||||
else alignedFile.renameTo(outputFilePath)
|
alignedFile.renameTo(outputFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Install
|
// region Install
|
||||||
|
|
||||||
adbManager?.install(AdbManager.Apk(outputFilePath, patcher.context.packageMetadata.packageName))
|
deviceSerial?.let { serial ->
|
||||||
|
AdbManager.getAdbManager(deviceSerial = serial.ifEmpty { null }, mount)
|
||||||
|
}?.install(AdbManager.Apk(outputFilePath, patcher.context.packageMetadata.packageName))
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
@ -320,7 +335,6 @@ internal object PatchCommand : Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter the patches to be added to the patcher. The filter is based on the following:
|
* Filter the patches to be added to the patcher. The filter is based on the following:
|
||||||
*
|
*
|
||||||
@ -344,17 +358,20 @@ internal object PatchCommand : Runnable {
|
|||||||
it.any { version -> version == packageVersion }
|
it.any { version -> version == packageVersion }
|
||||||
} ?: true
|
} ?: true
|
||||||
|
|
||||||
if (!matchesVersion) return@patch logger.warning(
|
if (!matchesVersion) {
|
||||||
"$patchName is incompatible with version $packageVersion. "
|
return@patch logger.warning(
|
||||||
+ "This patch is only compatible with version "
|
"$patchName is incompatible with version $packageVersion. " +
|
||||||
+ packages.joinToString(";") { pkg ->
|
"This patch is only compatible with version " +
|
||||||
|
packages.joinToString(";") { pkg ->
|
||||||
pkg.versions!!.joinToString(", ")
|
pkg.versions!!.joinToString(", ")
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
}
|
||||||
} ?: return@patch logger.fine(
|
} ?: return@patch logger.fine(
|
||||||
"$patchName is incompatible with $packageName. "
|
"$patchName is incompatible with $packageName. " +
|
||||||
+ "This patch is only compatible with "
|
"This patch is only compatible with " +
|
||||||
+ packages.joinToString(", ") { `package` -> `package`.name })
|
packages.joinToString(", ") { `package` -> `package`.name },
|
||||||
|
)
|
||||||
|
|
||||||
return@let
|
return@let
|
||||||
} ?: logger.fine("$patchName has no constraint on packages.")
|
} ?: logger.fine("$patchName has no constraint on packages.")
|
||||||
@ -374,8 +391,11 @@ internal object PatchCommand : Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun purge(resourceCachePath: File) {
|
private fun purge(resourceCachePath: File) {
|
||||||
val result = if (resourceCachePath.deleteRecursively()) "Purged resource cache directory"
|
val result = if (resourceCachePath.deleteRecursively()) {
|
||||||
else "Failed to purge resource cache directory"
|
"Purged resource cache directory"
|
||||||
|
} else {
|
||||||
|
"Failed to purge resource cache directory"
|
||||||
|
}
|
||||||
logger.info(result)
|
logger.info(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,24 +5,23 @@ import picocli.CommandLine.*
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
|
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "install",
|
name = "install",
|
||||||
description = ["Install an APK file to devices with the supplied ADB device serials"]
|
description = ["Install an APK file to devices with the supplied ADB device serials"],
|
||||||
)
|
)
|
||||||
internal object InstallCommand : Runnable {
|
internal object InstallCommand : Runnable {
|
||||||
private val logger = Logger.getLogger(InstallCommand::class.java.name)
|
private val logger = Logger.getLogger(InstallCommand::class.java.name)
|
||||||
|
|
||||||
@Parameters(
|
@Parameters(
|
||||||
description = ["ADB device serials"],
|
description = ["ADB device serials. If not supplied, the first connected device will be used."],
|
||||||
arity = "1..*"
|
arity = "0..*",
|
||||||
)
|
)
|
||||||
private lateinit var deviceSerials: Array<String>
|
private var deviceSerials: Array<String>? = null
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
names = ["-a", "--apk"],
|
names = ["-a", "--apk"],
|
||||||
description = ["APK file to be installed"],
|
description = ["APK file to be installed"],
|
||||||
required = true
|
required = true,
|
||||||
)
|
)
|
||||||
private lateinit var apk: File
|
private lateinit var apk: File
|
||||||
|
|
||||||
@ -32,11 +31,13 @@ internal object InstallCommand : Runnable {
|
|||||||
)
|
)
|
||||||
private var packageName: String? = null
|
private var packageName: String? = null
|
||||||
|
|
||||||
override fun run() = deviceSerials.forEach { deviceSerial ->
|
override fun run() {
|
||||||
try {
|
fun install(deviceSerial: String? = null) = try {
|
||||||
AdbManager.getAdbManager(deviceSerial, packageName != null).install(AdbManager.Apk(apk, packageName))
|
AdbManager.getAdbManager(deviceSerial, packageName != null).install(AdbManager.Apk(apk, packageName))
|
||||||
} catch (e: AdbManager.DeviceNotFoundException) {
|
} catch (e: AdbManager.DeviceNotFoundException) {
|
||||||
logger.severe(e.toString())
|
logger.severe(e.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deviceSerials?.forEach(::install) ?: install()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,10 +14,10 @@ internal object UninstallCommand : Runnable {
|
|||||||
private val logger = Logger.getLogger(UninstallCommand::class.java.name)
|
private val logger = Logger.getLogger(UninstallCommand::class.java.name)
|
||||||
|
|
||||||
@Parameters(
|
@Parameters(
|
||||||
description = ["ADB device serials"],
|
description = ["ADB device serials. If not supplied, the first connected device will be used."],
|
||||||
arity = "1..*"
|
arity = "0..*"
|
||||||
)
|
)
|
||||||
private lateinit var deviceSerials: Array<String>
|
private var deviceSerials: Array<String>? = null
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
names = ["-p", "--package-name"],
|
names = ["-p", "--package-name"],
|
||||||
@ -33,11 +33,13 @@ internal object UninstallCommand : Runnable {
|
|||||||
)
|
)
|
||||||
private var unmount: Boolean = false
|
private var unmount: Boolean = false
|
||||||
|
|
||||||
override fun run() = deviceSerials.forEach { deviceSerial ->
|
override fun run() {
|
||||||
try {
|
fun uninstall(deviceSerial: String? = null) = try {
|
||||||
AdbManager.getAdbManager(deviceSerial, unmount).uninstall(packageName)
|
AdbManager.getAdbManager(deviceSerial, unmount).uninstall(packageName)
|
||||||
} catch (e: AdbManager.DeviceNotFoundException) {
|
} catch (e: AdbManager.DeviceNotFoundException) {
|
||||||
logger.severe(e.toString())
|
logger.severe(e.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deviceSerials?.forEach { uninstall(it) } ?: uninstall()
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user