Uso sencillo del Servicio en Android

Tabla de contenido

Crear un servicio

Comunicación entre Actividad y Servicio

Enlace actividad y servicio

Usar el servicio de primer plano 

Usar IntentService


Crear un servicio

Cada Servicio debe registrarse en ActivityManifest.xml y, por lo general, se registrará automáticamente.

Registrar servicio:

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

Crear servicio: 

class MyService : Service() {

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

    override fun onCreate() {
        super.onCreate()
        Log.d("MyService", "onCreate executed")
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Log.d("MyService", "onStartCommand executed")
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("MyService", "onDestroy executed")
    }

}

 En circunstancias normales, ejecutaremos algunas acciones inmediatamente después de iniciar el servicio. Esas acciones se pueden escribir en  onStartCommand , no en onCreate. OnCreate solo se llamará cuando el servicio se cree por primera vez. onDestroy() es responsable de liberar recursos cuando finaliza el servicio. Dicho servicio se crea y el siguiente paso es habilitar y detener el servicio.Primero, defina dos botones en activity_main.xml para iniciar y detener el servicio. Luego configure el evento de escucha en la actividad:

        startServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            startService(intent) // 启动Service
        }
        stopServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            stopService(intent) // 停止Service
        }

Esto completa el uso básico del servicio.

Comunicación entre Actividad y Servicio

Enlace actividad y servicio

Para realizar la comunicación entre Actividad y Servicio, se debe usar el método onBind. El método onBind mejora la conexión entre el servicio y la actividad. Es la forma de comunicación entre el servicio y la actividad, para que la actividad pueda decidir cuándo usar el servicio y ver el progreso del servicio. . Aquí se define una clase DownloadBinder heredada de Binder, y luego se definen dos métodos dentro de la clase para simular la operación de descarga (de hecho, ninguno de estos dos métodos está implementado específicamente). Finalmente, use el método onBind para pasar la instancia mBinder de esta clase a la Actividad.

class MyService : Service() {

   private val mBinder = DownloadBinder()

    class DownloadBinder : Binder() {

        fun startDownload() {
            Log.d("MyService", "startDownload executed")
        }

        fun getProgress(): Int {
            Log.d("MyService", "getProgress executed")
            return 0
        }

    }

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

    override fun onCreate() {
        super.onCreate()
        Log.d("MyService", "onCreate executed")
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Log.d("MyService", "onStartCommand executed")
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("MyService", "onDestroy executed")
    }

}

Luego vincule el servicio en la actividad y defina dos botones en activity_main.xml para vincular y desvincular el servicio. En primer lugar, implementamos la implementación de clase anónima de ServiceConnect y reescribimos el método onServiceConnected y el método onServiceDisconnected. Se llama al método onServiceConnected cuando la actividad y el servicio se vinculan con éxito, y se llama al método onServiceDisconnected cuando el servicio falla o el proceso se cancela. El método bindService se usa durante el enlace, y los parámetros que se pasan son el objeto Intent , la instancia de ServiceConnection y el indicador (aquí Context.BIND_AUTO_CREATE significa que el enlace es exitoso y el servicio se crea automáticamente. En este momento, se ejecutará onCreate, pero onStartCommand no se ejecutará). Tenga en cuenta que cuando el servicio está desvinculado, se ejecutará el método onDestroy en el servicio, pero si el método startService se ha ejecutado antes, entonces los métodos stopService y unbindService deben llamarse al mismo tiempo para destruir el servicio.

class MainActivity : AppCompatActivity() {

    lateinit var downloadBinder: MyService.DownloadBinder

    private val connection = object : ServiceConnection {

        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            downloadBinder = service as MyService.DownloadBinder
            downloadBinder.startDownload()
            downloadBinder.getProgress()
        }

        override fun onServiceDisconnected(name: ComponentName) {
            Log.d("MyService", "onServiceDisconnected")
        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        startServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            startService(intent) // 启动Service
        }
        stopServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            stopService(intent) // 停止Service
        }
        bindServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            bindService(intent, connection, Context.BIND_AUTO_CREATE) // 绑定Service
        }
        unbindServiceBtn.setOnClickListener {
            unbindService(connection) // 解绑Service
        }
    }

}

Usar el servicio de primer plano 

El servicio en segundo plano no puede garantizar un funcionamiento estable, por lo que podemos usar el servicio en primer plano para transformar el servicio, de la siguiente manera:

class MyService : Service() {

    private val mBinder = DownloadBinder()

    class DownloadBinder : Binder() {

        fun startDownload() {
            Log.d("MyService", "startDownload executed")
        }

        fun getProgress(): Int {
            Log.d("MyService", "getProgress executed")
            return 0
        }

    }

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

    override fun onCreate() {
        super.onCreate()
        Log.d("MyService", "onCreate executed")
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel("my_service", "前台Service通知", NotificationManager.IMPORTANCE_DEFAULT)
            manager.createNotificationChannel(channel)
        }
        val intent = Intent(this, MainActivity::class.java)
        val pi = PendingIntent.getActivity(this, 0, intent, 0)
        val notification = NotificationCompat.Builder(this, "my_service")
            .setContentTitle("This is content title")
            .setContentText("This is content text")
            .setSmallIcon(R.drawable.small_icon)
            .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.large_icon))
            .setContentIntent(pi)
            .build()
        startForeground(1, notification)
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Log.d("MyService", "onStartCommand executed")
        thread {
            // 处理具体的逻辑
            stopSelf()
        }
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("MyService", "onDestroy executed")
    }

}

Modifique el método onCreate y el método onStartCommand, y cambie del servicio en segundo plano al servicio en primer plano para escribir la notificación del mensaje en el servicio, porque el servicio en primer plano también necesita declarar los permisos, por lo que el archivo AndroidManifest.xml debe modificarse como sigue:

<manifiesto xmlns:android="http://schemas.android.com/apk/res/android"
          paquete="com.ejemplo.pruebaservicio">

    <usos-permiso android:name="android.permission.FOREGROUND_SERVICE"/>
...
</manifiesto>

 La razón para modificar el método onStartCommand es que el servicio se ejecuta en el subproceso principal, por lo que las operaciones que consumen mucho tiempo en el servicio causarán problemas ANR (la aplicación no responde). Por lo tanto, necesitamos abrir subprocesos en el método para manejar operaciones que consumen mucho tiempo y usar stopSelf() para detener el servicio.

Usar IntentService

Debido a que es demasiado engorroso abrir subprocesos con frecuencia cuando el servicio maneja operaciones que consumen mucho tiempo, se inicia IntentService. El método de uso es el siguiente:

class MyIntentService : IntentService("MyIntentService") {

    override fun onHandleIntent(intent: Intent?) {
        // 打印当前线程的id
        Log.d("MyIntentService", "Thread id is ${Thread.currentThread().name}")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("MyIntentService", "onDestroy executed")
    }

}

No olvide registrar el servicio en AndroidManifest.xml

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

 Las operaciones que requieren mucho tiempo se pueden realizar en onHandleIntent, que se ejecuta en subprocesos, y el uso específico en Actividad es el siguiente:

Defina un botón aquí para iniciar el IntentService

startIntentServiceBtn.setOnClickListener {
            // 打印主线程的id
            Log.d("MainActivity", "Thread id is ${Thread.currentThread().name}")
            val intent = Intent(this, MyIntentService::class.java)
            startService(intent)
        }

 

Supongo que te gusta

Origin blog.csdn.net/liny70858/article/details/127403347
Recomendado
Clasificación