package io.legato.kazusa.base import android.content.Intent import android.os.Build import android.os.IBinder import androidx.annotation.CallSuper import androidx.lifecycle.LifecycleService import androidx.lifecycle.lifecycleScope import io.legato.kazusa.R import io.legato.kazusa.help.LifecycleHelp import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.coroutine.Coroutine import io.legato.kazusa.lib.permission.Permissions import io.legato.kazusa.lib.permission.PermissionsCompat import io.legato.kazusa.utils.LogUtils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.isActive import kotlinx.coroutines.sync.Semaphore import kotlin.coroutines.CoroutineContext abstract class BaseService : LifecycleService() { private val simpleName = this::class.simpleName.toString() private var isForeground = false fun execute( scope: CoroutineScope = lifecycleScope, context: CoroutineContext = Dispatchers.IO, start: CoroutineStart = CoroutineStart.DEFAULT, executeContext: CoroutineContext = Dispatchers.Main, semaphore: Semaphore? = null, block: suspend CoroutineScope.() -> T ) = Coroutine.async(scope, context, start, executeContext, semaphore, block) @CallSuper override fun onCreate() { super.onCreate() LifecycleHelp.onServiceCreate(this) if (!AppConfig.permissionChecked) { AppConfig.permissionChecked = true checkPermission() } } @CallSuper override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { LogUtils.d(simpleName) { "onStartCommand $intent ${intent?.toUri(0)}" } if (!isForeground) { startForegroundNotification() isForeground = true } return super.onStartCommand(intent, flags, startId) } @CallSuper override fun onTaskRemoved(rootIntent: Intent?) { LogUtils.d(simpleName, "onTaskRemoved") super.onTaskRemoved(rootIntent) stopSelf() } override fun onBind(intent: Intent): IBinder? { super.onBind(intent) return null } @CallSuper override fun onDestroy() { super.onDestroy() LifecycleHelp.onServiceDestroy(this) } @CallSuper override fun onTimeout(startId: Int, fgsType: Int) { super.onTimeout(startId, fgsType) LogUtils.d(simpleName, "onTimeout startId:$startId fgsType:$fgsType") stopSelf() } /** * 开启前台服务并发送通知 */ open fun startForegroundNotification() { } /** * 检测通知权限和后台权限 */ private fun checkPermission() { PermissionsCompat.Builder() .addPermissions(Permissions.POST_NOTIFICATIONS) .rationale(R.string.notification_permission_rationale) .onGranted { if (lifecycleScope.isActive) { startForegroundNotification() } } .request() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PermissionsCompat.Builder() .addPermissions(Permissions.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) .rationale(R.string.ignore_battery_permission_rationale) .request() } } }