基于Kotlin Multiplatform实现静态文件服务器(四)

Android前台服务

Android前台服务用于执行用户可察觉的操作。

前台服务显示状态栏通知,让用户知道您的 应用正在前台执行任务并消耗系统资源。

文件服务启动和停止

在JVM上,通过守护线程来启动文件服务。

class DesktopServerViewModel : ServerViewModel, ViewModel() {
    ...
    override fun startFileServer(httpServerConfig: HttpFileServerConfig?) {
        startServerDaemon(httpServerConfig)
    }

    override fun stopFileServer() {
        stopServerDaemon()
    }
}

actual fun getMsgViewModel(): ServerViewModel = DesktopServerViewModel()
class ServerDaemon(private val httpServerConfig: HttpFileServerConfig) : Thread() {
    override fun run() {
        bootStrapServer.startServer(httpServerConfig)
    }

    companion object {
        private lateinit var serverDaemon: ServerDaemon

        fun startServerDaemon(httpServerConfig: HttpFileServerConfig?) {
            httpServerConfig ?: run {
                LogTool.e("不能加载配置文件")
                return
            }
            serverDaemon = ServerDaemon(httpServerConfig).also {
                it.isDaemon = true
                it.name = "Server-daemon-thread"
            }.apply {
                start()
            }
        }

        fun stopServerDaemon() {
            try {
                bootStrapServer.stopServer()
                if (serverDaemon.isAlive) {
                    serverDaemon.interrupt()
                }
            } catch (e: InterruptedException) {
                e.printStackTrace()
            }
        }
    }
}

在Android中,为了避免由于界面退出或锁屏后被系统杀死进程导致文件服务中断,使用前台服务实现。

@Suppress("DEPRECATION")
class AndroidServerViewModel : ViewModel(), ServerViewModel {
    ...
    @RequiresApi(VERSION_CODES.O)
    override fun startFileServer(httpServerConfig: HttpFileServerConfig?) {
        FileServerApp.app.startForegroundService(fileServerIntent.also { //启动前台服务
            it.putExtra("serverPort", httpServerConfig?.serverPort)
            it.putExtra("fileDirectory", httpServerConfig?.fileDirectory)
        })
    }

    override fun stopFileServer() {
        FileServerApp.app.stopService(fileServerIntent) // 停止前台服务。
    }
    ...

    private companion object {
        ...
        val fileServerIntent = Intent().also {
            it.setClass(FileServerApp.app.applicationContext, FileServerService::class.java)
        }
    }
}

actual fun getMsgViewModel(): ServerViewModel = AndroidServerViewModel()

创建FileServerService,并声明为前台服务。声明前台服务,需要在AndroidManifest.xml中声明,并申请权限。 权限相关可参阅https://blog.csdn.net/luckyion/article/details/141305213

class FileServerService : Service() {
    override fun onBind(intent: Intent): IBinder? = null

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate() {
        super.onCreate()
        getSystemService(NotificationManager::class.java).apply {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel(
                    NotificationChannel(
                        MY_CHANNEL_ID,
                        MY_CHANNEL_NAME,
                        NotificationManager.IMPORTANCE_HIGH
                    )
                )
            }
        }
        try {
            startForeground(MY_NOTIFICATION_ID, getNotification(this))
            LogTool.i("startForeground")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        LogTool.i("onStartCommand")
        startServer(
            HttpFileServerConfig(
                intent?.getIntExtra("serverPort", 80)!!,
                intent.getStringExtra("fileDirectory")!!
            )
        )
        return super.onStartCommand(intent, flags, startId)
    }

    private fun startServer(httpServerConfig: HttpFileServerConfig) {
        LogTool.i("startServer")
        startServerDaemon(httpServerConfig) // 启动文件服务线程
    }

    private fun stopServer() {
        stopServerDaemon()  // 停止文件服务线程
    }

    override fun onDestroy() {
        stopServer()
        super.onDestroy()
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun getNotification(context: Context) = // 前台服务通知,创建前台服务,必须发送一个通知。
        Notification.Builder(context, MY_CHANNEL_ID)
            .setShowWhen(true)
            .setSmallIcon(R.drawable.explore)
            .setContentTitle("服务服务器")
            .setContentText("服务已启动").also {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    it.setChannelId(MY_CHANNEL_ID)
                }
            }.build()


    private companion object {
        private const val MY_CHANNEL_ID = "File-server-foreground-service-channel"
        private const val MY_CHANNEL_NAME = "File-server-foreground-service-channel-name"
        private const val MY_NOTIFICATION_ID = 10086
    }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin Multiplatform 是一种由 JetBrains 开发的跨平台开发框架。它允许开发人员使用 Kotlin 语言编写代码,然后在多个平台上运行,包括 Android、iOS、Web 等。与传统的跨平台解决方案相比,Kotlin Multiplatform 提供了更高的灵活性和性能。 Kotlin Multiplatform 的核心思想是共享代码。开发人员可以编写一个通用的 Kotlin 模块,其中包含与平台无关的业务逻辑和算法。然后,他们可以根据不同的目标平台,编写平台特定的代码。这样,开发人员可以在不同平台之间共享核心逻辑,减少了重复代码的编写,并且保持了一致性。 Kotlin Multiplatform 目前已经应用于许多项目中。对于 Android 开发人员来说,它提供了更好的性能和开发体验。它允许开发人员在 Android 和 iOS 上使用相同的 Kotlin 代码库,从而加快了开发速度和代码复用。对于 iOS 开发人员来说,Kotlin Multiplatform 可以通过共享核心业务逻辑来简化跨平台开发,并且可以与现有的 Objective-C 或 Swift 代码无缝集成。 总之,Kotlin Multiplatform 是一个强大的跨平台开发框架,可以大大简化和提高开发人员的工作效率。它同时适用于 Android 和 iOS 开发,并且允许开发人员在不同平台之间共享核心逻辑。在未来,我们可以预见 Kotlin Multiplatform 将会在跨平台开发领域发挥更大的作用,并且有望成为开发人员的首选解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值