Servicio en Android usando Kotlin (Andorid O)


Ejemplo de como implementar un servicio de Android usando Kotlin y que use Foreground de Android O, mostrando la notificación permamente.

  • Creación del subproceso Foreground
  • Notificación permamente (requisito Android O)
  • Control del servicio StartService / StopService

Preparativos

En AndroidManifest.xml deberemos añadir la directiva para poder usar servicios en Android O

<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

Añadir la declaración del servicio

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="false" />

La propiedad enabled es para activar o desactivar el servicio.
La propiedad exported si está en true el servicio puede ser llamado des de otra aplicación

Servicio en Kotlin

Creación del servicio MyService clase que se extiende de Service

class MyService : Service() {

    companion object {
        const val CHANNEL_ID = "ForegroundService Kotlin"

        fun startService(context: Context, message: String) {
            val startIntent = Intent(context, MyService::class.java)
            startIntent.putExtra("inputExtra", message)
            ContextCompat.startForegroundService(context, startIntent)
        }

        fun stopService(context: Context) {
            val stopIntent = Intent(context, MyService::class.java)
            context.stopService(stopIntent)
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        //do heavy work on a background thread
        val input: String? = intent?.getStringExtra("inputExtra")
        createNotificationChannel()
        val notificationIntent = Intent(this, MainActivity::class.java)
        val pendingIntent: PendingIntent = PendingIntent.getActivity(
            this,
            0, notificationIntent, 0
        )
        val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle(getText(R.string.service_title))
            .setContentText(input)
            .setSmallIcon(R.drawable.ic_android_24dp)
            .setContentIntent(pendingIntent)
            .build()
        startForeground(1, notification)
        return START_NOT_STICKY
    }

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

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(
                CHANNEL_ID, "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            val manager: NotificationManager? = getSystemService(NotificationManager::class.java)
            manager!!.createNotificationChannel(serviceChannel)
        }
    }
}

En está clase, se hace diferentes cosas, primero se crea el canal de notificación y las funciones para iniciar y parar el servicio, en onStartCommand es donde el subproceso (foreground service) debe lanzar la tarea a realizar, createNotificationChannel es para la creación de la notificación permanente, requisito a partir de Android Oreo incluido

Iniciando y parando el Servicio

Cuando deseamos iniciar el servicio

MyService.startService(this, "Foreground Service is running...")

Cuando deseamos parar el servicio

MyService.stopService(this)

Cómo detectar si el servicio está activo

Si se desea detectar el servicio si está activo, en kotlin podemos usar la siguiente extensión de funcionalidad

@Suppress("DEPRECATION")
fun <T> Context.isServiceRunning(service: Class<T>): Boolean {
    return (getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Integer.MAX_VALUE)
        .any { it.service.className == service.name }
}

Su uso

if (isServiceRunning(MyService::class.java)) {
   //Servicio corriendo
} else {
   //Servicio parado o finalizado
}

ADB Test

Podemos usar el ADB para obtener información del servicio, con el comando

adb shell dumpsys activity services <service>

Si el servicio no está ejecutandose se obtendrá

ACTIVITY MANAGER SERVICES (dumpsys activity services)
  (nothing)

Y si el servicio está corriendo y asegurar que está en primer plano, la propiedad isForeground=true

ACTIVITY MANAGER SERVICES (dumpsys activity services)
  User 0 active services:
...
 isForeground=true foregroundId=1 
...

Código fuente

Git con el código fuente usado para el apunte

Relacionado con servicios

Publicado por Codelaby

Mobile DevDesigner

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: