diff --git a/src/jvmMain/kotlin/Main.kt b/src/jvmMain/kotlin/Main.kt index 5f1b132..2f90b2b 100644 --- a/src/jvmMain/kotlin/Main.kt +++ b/src/jvmMain/kotlin/Main.kt @@ -89,6 +89,8 @@ fun App(fileStorageHelper: FileStorageHelper, savedPath: String?, adbSavedPath: var isAdbSetupDone by remember { mutableStateOf(false) } var adbPath by remember { mutableStateOf("") } var showLoadingDialog by remember { mutableStateOf(Pair("", false)) } + var isDeviceIdEnabled by remember { mutableStateOf(false) } + var deviceSerialId by remember { mutableStateOf("") } // TODO: (Fixed this issue need to test more!) - Can't update file path once saved, For now Delete path.kb file inside storage directory. savedJarPath?.let { @@ -420,6 +422,56 @@ fun App(fileStorageHelper: FileStorageHelper, savedPath: String?, adbSavedPath: Strings.AUTO_UNZIP ) Spacer(modifier = Modifier.padding(8.dp)) + if (isAdbSetupDone) { + Text( + text = Strings.DEVICE_OPTIONS, + style = Styles.TextStyleBold(16.sp), + modifier = Modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 8.dp) + ) + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + CheckboxWithText( + Strings.DEVICE_ID, + isDeviceIdEnabled, + onCheckedChange = { + isDeviceIdEnabled = it + }, + Strings.DEVICE_ID_INFO + ) + if (isDeviceIdEnabled) { + CustomTextField( + deviceSerialId, + Strings.SERIAL_ID, + forPassword = false, + onValueChange = { + deviceSerialId = it + } + ) + ButtonWithToolTip( + Strings.FETCH_DEVICES, + onClick = { + CommandExecutor() + .executeCommand( + CommandBuilder() + .getAdbFetchCommand(adbSavedPath!!), + coroutineScope, + onSuccess = { + logs += it + }, + onFailure = { + logs += it.printStackTrace() + } + ) + }, + Strings.FETCH_DEVICES_INFO, + icon = "device_fetch" + ) + } + } + Spacer(modifier = Modifier.padding(8.dp)) + } if (isLoading) { CircularProgressIndicator( modifier = Modifier.size(size = 40.dp) diff --git a/src/jvmMain/kotlin/command/CommandBuilder.kt b/src/jvmMain/kotlin/command/CommandBuilder.kt index 4fab55a..c2ce31c 100644 --- a/src/jvmMain/kotlin/command/CommandBuilder.kt +++ b/src/jvmMain/kotlin/command/CommandBuilder.kt @@ -16,6 +16,8 @@ class CommandBuilder { private var keyAlias: String = "" private var keyPassword: String = "" private var adbVerifyCommandExecute = Pair(false, "") + private var isDeviceIdEnabled: Boolean = false + private var adbSerialId: String = "" fun bundletoolPath(path: String) = apply { this.bundletoolPath = path } fun aabFilePath(path: Pair) = apply { this.aabFilePath = path } @@ -31,6 +33,10 @@ class CommandBuilder { fun verifyAdbPath(value: Boolean, path: String) = apply { this.adbVerifyCommandExecute = Pair(value, path) } + fun isDeviceSerialIdEnabled(value: Boolean) = apply { this.isDeviceIdEnabled = value } + + fun adbSerialId(value: String) = apply { this.adbSerialId = value } + fun getAdbVerifyCommand(): String { val (forVerify, path) = adbVerifyCommandExecute if (forVerify) { @@ -39,6 +45,10 @@ class CommandBuilder { return "" } + fun getAdbFetchCommand(adbPath: String): String { + return "\"${adbPath}\" devices" + } + fun validateAndGetCommand(): Pair { if (bundletoolPath.isEmpty()) { return Pair("bundletoolPath", false) @@ -52,36 +62,40 @@ class CommandBuilder { if (signingMode == SigningMode.RELEASE && (keyStorePath.isEmpty() || keyStorePassword.isEmpty() || keyAlias.isEmpty() || keyPassword.isEmpty())) { return Pair("Check Keystore Info!", false) } + if (isDeviceIdEnabled && adbSerialId.isEmpty()) { + return Pair("Invalid Serial ID", false) + } return Pair(getCommand(), true) } private fun getCommand(): String { val commandBuilder = StringBuilder() - if (Utils.isWindowsOS()) { - commandBuilder.append("java -jar \"${bundletoolPath}\" build-apks ") - if (isUniversalMode) { - commandBuilder.append("--mode=universal ") - } - if (isOverwrite) { - commandBuilder.append("--overwrite ") - } - if (isAapt2PathEnabled) { - commandBuilder.append("--aapt2=\"$aapt2Path\" ") - } - commandBuilder.append( - "--bundle=\"${aabFilePath.first}${aabFilePath.second}\" --output=\"${aabFilePath.first}${ - aabFilePath.second.split( - "." - )[0] - }.apks\" " - ) + commandBuilder.append("java -jar \"${bundletoolPath}\" build-apks ") + if (isUniversalMode) { + commandBuilder.append("--mode=universal ") + } + if (isOverwrite) { + commandBuilder.append("--overwrite ") + } + if (isAapt2PathEnabled) { + commandBuilder.append("--aapt2=\"$aapt2Path\" ") + } + commandBuilder.append( + "--bundle=\"${aabFilePath.first}${aabFilePath.second}\" --output=\"${aabFilePath.first}${ + aabFilePath.second.split( + "." + )[0] + }.apks\" " + ) - if (signingMode == SigningMode.RELEASE) { - commandBuilder.append("--ks=$keyStorePath --ks-pass=pass:$keyStorePassword --ks-key-alias=$keyAlias --key-pass=pass:$keyPassword ") - } + if (signingMode == SigningMode.RELEASE) { + commandBuilder.append("--ks=$keyStorePath --ks-pass=pass:$keyStorePassword --ks-key-alias=$keyAlias --key-pass=pass:$keyPassword ") + } - return commandBuilder.toString() + if (isDeviceIdEnabled) { + commandBuilder.append("--device-id=$adbSerialId ") } - return "" + + return commandBuilder.toString() } } \ No newline at end of file diff --git a/src/jvmMain/kotlin/utils/Strings.kt b/src/jvmMain/kotlin/utils/Strings.kt index cee16d7..9df72af 100644 --- a/src/jvmMain/kotlin/utils/Strings.kt +++ b/src/jvmMain/kotlin/utils/Strings.kt @@ -36,6 +36,9 @@ object Strings { const val ABD_SETUP_DONE = "Adb Connected" const val SETUP_ADB_INFO = "Setup ADB path to create builds based on connected device" const val DEVICE_ID = "Device Id" - const val DEVICE_ID_INFO = "Device Id based on the Serial Number" + const val DEVICE_ID_INFO = "Device Id based on the Serial Number. Use with Mode Universal to get one apk." const val VERIFYING_ADB_PATH = "Verifying ADB Path.." + const val SERIAL_ID = "Serial Id" + const val FETCH_DEVICES = "Fetch Devices" + const val FETCH_DEVICES_INFO = "Fetch Connected Devices Info in LogView" } \ No newline at end of file diff --git a/src/jvmMain/resources/device_fetch.svg b/src/jvmMain/resources/device_fetch.svg new file mode 100644 index 0000000..2d8124b --- /dev/null +++ b/src/jvmMain/resources/device_fetch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/jvmTest/kotlin/command/CommandBuilderTest.kt b/src/jvmTest/kotlin/command/CommandBuilderTest.kt index 53a089d..feeb665 100644 --- a/src/jvmTest/kotlin/command/CommandBuilderTest.kt +++ b/src/jvmTest/kotlin/command/CommandBuilderTest.kt @@ -56,6 +56,7 @@ class CommandBuilderTest { .keyAlias("keyAlias") .keyPassword("keyPassword") .isUniversalMode(false).validateAndGetCommand() + println(result) assertEquals( "java -jar \"bundletool.jar\" build-apks --bundle=\"/path/to/file.aab\" --output=\"/path/to/file.apks\" --ks=/path/to/keystore.jks --ks-pass=pass:keystorePassword --ks-key-alias=keyAlias --key-pass=pass:keyPassword ", result.first @@ -71,6 +72,7 @@ class CommandBuilderTest { .signingMode(SigningMode.DEBUG) .isUniversalMode(false) .validateAndGetCommand() + println(result) assertEquals( "java -jar \"bundletool.jar\" build-apks --bundle=\"/path/to/file.aab\" --output=\"/path/to/file.apks\" ", result.first @@ -93,6 +95,7 @@ class CommandBuilderTest { .aabFilePath(Pair("/path/to/", "file.aab")) .isUniversalMode(true) .validateAndGetCommand() + println(result) assertEquals( "java -jar \"bundletool.jar\" build-apks --mode=universal --bundle=\"/path/to/file.aab\" --output=\"/path/to/file.apks\" ", result.first @@ -107,10 +110,46 @@ class CommandBuilderTest { .aabFilePath(Pair("/path/to/", "file.aab")) .isOverwrite(true) .isUniversalMode(false).validateAndGetCommand() + println(result) assertEquals( "java -jar \"bundletool.jar\" build-apks --overwrite --bundle=\"/path/to/file.aab\" --output=\"/path/to/file.apks\" ", result.first ) assertEquals(true, result.second) } + + @Test + fun `validateAndGetCommand should return error when device id enabled but serial id is empty`() { + val result = CommandBuilder() + .bundletoolPath("bundletool.jar") + .aabFilePath(Pair("/path/to/", "file.aab")) + .isOverwrite(false) + .isUniversalMode(false) + .isDeviceSerialIdEnabled(true) + .adbSerialId("") + .validateAndGetCommand() + assertEquals( + "Invalid Serial ID", + result.first + ) + assertEquals(false, result.second) + } + + @Test + fun `validateAndGetCommand should return valid command with device id enabled`() { + val result = CommandBuilder() + .bundletoolPath("bundletool.jar") + .aabFilePath(Pair("/path/to/", "file.aab")) + .isOverwrite(false) + .isUniversalMode(false) + .isDeviceSerialIdEnabled(true) + .adbSerialId("RZCWC0EZLEH") + .validateAndGetCommand() + println(result) + assertEquals( + "java -jar \"bundletool.jar\" build-apks --bundle=\"/path/to/file.aab\" --output=\"/path/to/file.apks\" --device-id=RZCWC0EZLEH ", + result.first + ) + assertEquals(true, result.second) + } } diff --git a/src/jvmTest/kotlin/command/CommandExecutorTest.kt b/src/jvmTest/kotlin/command/CommandExecutorTest.kt deleted file mode 100644 index ce178c6..0000000 --- a/src/jvmTest/kotlin/command/CommandExecutorTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package command - -import junit.framework.TestCase.assertTrue -import kotlinx.coroutines.runBlocking -import org.hamcrest.MatcherAssert.assertThat -import org.junit.Before -import org.junit.Test - -class CommandExecutorTest { - private lateinit var commandExecutor: CommandExecutor - - @Before - fun setUp() { - commandExecutor = CommandExecutor() - } - - // These test cases may not work for MAC and Linux need to verify. - @Test - fun `execute valid command successfully`() { - val expectedOutput = "openjdk 11.0.18 2023-01-17" - val cmd = "java --version" - - runBlocking { - commandExecutor.executeCommand( - cmd, - this, - onSuccess = { - println("SUCCESS -> $it") - assertThat(expectedOutput, it.contains(expectedOutput)) - }, - onFailure = { - println("ERROR -> ${it.message}") - assertThat(expectedOutput, it.message?.contains(expectedOutput) ?: false) - } - ) - } - } - - @Test - fun `execute invalid command and handle failure`() { - val cmd = "invalid_command" - runBlocking { - commandExecutor.executeCommand( - cmd, - this, - onSuccess = { - assertTrue(it.isEmpty()) - }, - onFailure = { - assertTrue(it.message?.contains("The system cannot find the file specified") ?: false) - } - ) - } - } -} \ No newline at end of file