Compose for Desktop桌面端简单的APK工具

2,692 阅读3分钟

前言

在推荐中看到了这篇文章 《使用ComposeDesktop开发一款桌面端多功能APK工具》 感觉这个工具很不错,自己也会用到。早就知道Compose可以跨平台了,也写过Flutter,不知道和Flutter Desktop哪个好用。

正好,趁这个机会,自己也动手写一个符合自己业务需求的APK工具。

效果

image.png 没错,主题布局颜色不能说和 《使用ComposeDesktop开发一款桌面端多功能APK工具》很像,简直就是一模一样,哈哈哈。

但功能相比,这个就差很多了。《使用ComposeDesktop开发一款桌面端多功能APK工具》是互联网一整套APK打包流程。由于我们应用是内网环境,结合自身需求和发布流程(水平有限 0-0),开发了一个简单的APK工具。功能也主要集中在 APK签名部分!

APK打包

主要是通过代码跳转到浏览器的 Jenkins 打包,也没什么好说的了。

Desktop.getDesktop().browse(URI("http://..."))

image.png

APK加固

加固部分用的是 360加固助手,由于没有会员,不能使用命令行执行,也只能享受最简单的dex加固。想着自己来实现dex加密加壳,水平有限,暂时没有实现!希望有相关经验的小伙伴给予指导,万分感谢!

APK签名

签名部分

签名用的是官方的 apksigner。目前是V3级。

image.png

文件选择器

使用的是 JFileChooser 。如果文件和文件夹都可以选择,fileSelectionMode 设置成 JFileChooser.FILES_AND_DIRECTORIES

文件拖拽

使用ComposeDesktop开发一款桌面端多功能APK工具》中博主已经贴出了主要代码。但有几个点博主没有细说,这里补充一下:

  • ComposeWindow,这个window应该是 main() applicationFrameWindowScopewindow。用全局的 window 去添加一个 JPanel
  • DropTarget,这个target 要赋值给 window 中 Component 的 dropTarget。如:window.contentPane.getComponent(1).dropTarget = target
  • window 的 contentPane 会有多个,需要找到自己想要能够拖拽区域的 JPanel 并进行 target 赋值。如:window.contentPane.getComponent(1)

完整代码:

@Composable
fun DropBoxPanel(
    modifier: Modifier,
    window: ComposeWindow,
    component: JPanel = JPanel(),
    onFileDrop: (String) -> Unit
) {

    val dropBoundsBean = remember {
        mutableStateOf(DropBoundsBean())
    }

    Box(
        modifier = modifier.onPlaced {
            dropBoundsBean.value = DropBoundsBean(
                x = it.positionInWindow().x,
                y = it.positionInWindow().y,
                width = it.size.width,
                height = it.size.height
            )
        }) {
        LaunchedEffect(true) {
            component.setBounds(
                dropBoundsBean.value.x.roundToInt(),
                dropBoundsBean.value.y.roundToInt(),
                dropBoundsBean.value.width,
                dropBoundsBean.value.height
            )
            window.contentPane.add(component)

            //https://dev.to/tkuenneth/from-swing-to-jetpack-compose-desktop-2-4a4h
            val target = object : DropTarget() {
                @Synchronized
                override fun drop(evt: DropTargetDropEvent) {
                    evt.acceptDrop(DnDConstants.ACTION_REFERENCE)
                    val droppedFiles = evt.transferable.getTransferData(DataFlavor.javaFileListFlavor) as List<*>
                    droppedFiles.first()?.let {
                        onFileDrop.invoke(it.toString())
                    }
                }
            }
            window.contentPane.getComponent(1).dropTarget = target
        }

        SideEffect {
            component.setBounds(
                dropBoundsBean.value.x.roundToInt(),
                dropBoundsBean.value.y.roundToInt(),
                dropBoundsBean.value.width,
                dropBoundsBean.value.height
            )
        }

        DisposableEffect(true) {
            onDispose {
                window.contentPane.remove(component)
            }
        }
    }
}

效果:

search-input.gif

APK上传到手机

手机APK需要传到定制手机连接VPN发布,就是那么独特。这个本来想做一个adb读取手机内存卡的东西呢,最后还是算了吧,直接用电脑驱动读取复制粘贴不香吗...

最后

工具非常简单,满足现在业务的发包需求。 Compose 开发,还是那个味,只是增加了window的一些内容。Android的很多东西都能拿来用,比如:Retrofit。 相比较Flutter 的 Dart,Compose 用起来就太爽了。Flutter的 widget 太多了。有利有弊,Flutter多就相对完善一些,Compose for Desktop库就少很多。

参考

使用ComposeDesktop开发一款桌面端多功能APK工具