kotlin 如何在jetpack组合中使用服务

jxct1oxe  于 2023-03-03  发布在  Kotlin
关注(0)|答案(1)|浏览(140)

我想在jetpack compose中使用服务。我尝试在compose应用程序中绑定服务,但它总是向我返回null。我尝试了这个stack overflow。但它对我不起作用。有人指导我吗?

import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Binder
import android.os.IBinder
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext

@Composable
inline fun <reified BoundService : Service, reified BoundServiceBinder : Binder> rememberBoundLocalService(
    crossinline getService: @DisallowComposableCalls BoundServiceBinder.() -> BoundService,
): BoundService? {
    val context: Context = LocalContext.current
    var boundService: BoundService? by remember(context) { mutableStateOf(null) }
    val serviceConnection: ServiceConnection = remember(context) {
        object : ServiceConnection {
            override fun onServiceConnected(className: ComponentName, service: IBinder) {
                boundService = (service as BoundServiceBinder).getService()
            }

            override fun onServiceDisconnected(arg0: ComponentName) {
                boundService = null
            }
        }
    }
    DisposableEffect(context, serviceConnection) {
        context.bindService(Intent(context, BoundService::class.java), serviceConnection, Context.BIND_AUTO_CREATE)
        onDispose { context.unbindService(serviceConnection) }
    }
    return boundService
}

蓝牙服务.kt

class BluetoothService : Service() {

    companion object {
        const val ACTION_GATT_CONNECTED =
            "com.abc.app.ACTION_GATT_CONNECTED"
        const val ACTION_GATT_DISCONNECTED =
            "com.abc.app.ACTION_GATT_DISCONNECTED"

        private const val STATE_DISCONNECTED = 0
        private const val STATE_CONNECTED = 2
    }

    private var connectionState = STATE_DISCONNECTED
    private var bluetoothAdapter: BluetoothAdapter? = null
    private val binder = LocalBinder()
    private var bluetoothGatt: BluetoothGatt? = null
    private val bluetoothGattCallback = object : BluetoothGattCallback() {
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                // successfully connected to the GATT Server
                connectionState = STATE_CONNECTED
                broadcastUpdate(ACTION_GATT_CONNECTED)
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                // disconnected from the GATT Server
                connectionState = STATE_DISCONNECTED
                broadcastUpdate(ACTION_GATT_DISCONNECTED)
            }
        }
    }

    override fun onBind(intent: Intent): IBinder {
        return binder
    }

    inner class LocalBinder : Binder() {
        fun getService(): BluetoothService {
            return this@BluetoothService
        }
    }

    fun initialize(adapter: BluetoothAdapter?): Boolean {
        bluetoothAdapter = adapter
        if (bluetoothAdapter == null) {
            logE(">> Unable to obtain a BluetoothAdapter.")
            return false
        }
        return true
    }

    fun connect(address: String): Boolean {
        bluetoothAdapter?.let { adapter ->
            try {
                val device = adapter.getRemoteDevice(address)
                // connect to the GATT server on the device
                bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback)
                return true
            } catch (exception: IllegalArgumentException) {
                logE("Device not found with provided address.")
                return false
            }
        } ?: run {
            logE("BluetoothAdapter not initialized")
            return false
        }
    }

    override fun onUnbind(intent: Intent?): Boolean {
        close()
        return super.onUnbind(intent)
    }

    private fun close() {
        bluetoothGatt?.let { gatt ->
            gatt.close()
            bluetoothGatt = null
        }
    }

    private fun broadcastUpdate(action: String) {
        val intent = Intent(action)
        sendBroadcast(intent)
    }
}

我尝试使用bluetoothService,但在签入条件时它总是返回null

蓝牙连接内容状态.kt

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun BluetoothConnectionContentStateful(
    context: Context = LocalContext.current,
    viewModel: BloodPressurePairViewModel = getViewModel(),
    router: Router = get()
) {
    val activity = context as ComponentActivity
    val bluetoothService = rememberBoundLocalService<BluetoothService, BluetoothService.LocalBinder> { getService() }
    val scanDeviceList = viewModel.scanLeDevices.collectAsStateWithLifecycle()
    if (bluetoothService != null) {
        if (!bluetoothService.initialize(rememberPairScreenState.bluetoothAdapter)) {
            activity.logE(">> Unable to initialize Bluetooth")
        } else {
            activity.logE(">> initialize Bluetooth")
        }
    }else{
        activity.logE(">> bluetoothService null")
    }
}

bluetoothService总是返回空值,对此有什么想法吗?

kpbpu008

kpbpu0081#

  • 将可组合对象与服务绑定不是一个好的做法
  • 可组合应该只涉及侦听视图模型中状态的表示层
  • 您可以将组合对象绑定到ViewModel或存储库,并侦听组合对象中的状态

在这个项目中,我可以调用一个API作为服务,你可以用你的服务代替-***Github link of source code and implementation***

相关问题