Android核心主题1------服务1(Android Service:前台服务、后台服务、绑定服务)

1.什么是Service:

  1. Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。

  2. 此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互。

2. 服务分为三种不同的类型:

  1. 前台服务

前台服务执行一些用户能注意到的操作。例如,音频应用会使用前台服务来播放音频曲目。前台服务必须显示通知。即使用户停止与应用的交互,前台服务仍会继续运行。

首先,Service类中使用startForeground方法来设置前台服务并显示通知。

kotlin 复制代码
import android.app.Notification
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.media.MediaPlayer
import android.os.IBinder
import androidx.core.app.NotificationCompat

class AudioPlayerService : Service() {

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        startForegroundService()
        return START_NOT_STICKY
    }

    // 当服务启动时调用此方法。
    private fun startForegroundService() {
        // 创建一个意图以在通知被点击时启动MainActivity。
        val notificationIntent = Intent(this, MainActivity::class.java)
        // 创建一个PendingIntent来包装notificationIntent。
        val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0)

        // 使用NotificationCompat.Builder构建通知。
        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("音频播放器") // 设置通知的标题。
            .setContentText("正在播放音频") // 设置通知的文本内容。
            .setSmallIcon(R.drawable.ic_notification) // 设置通知的小图标。
            .setContentIntent(pendingIntent) // 设置通知的PendingIntent。
            .build()

        // 使用给定的通知启动前台服务。
        startForeground(NOTIFICATION_ID, notification)
    }

    // 当服务被销毁时调用此方法。
    override fun onDestroy() {
        super.onDestroy()
        // 停止服务在前台运行。
        stopForeground(true)
    }

    // 当客户端绑定到服务时调用此方法。
    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    companion object {
        private const val CHANNEL_ID = "audio_channel" // 通知渠道的ID。
        private const val NOTIFICATION_ID = 1 // 通知的ID。
    }
}

接下来,在Activity中启动Service。

kotlin 复制代码
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = Intent(this, AudioPlayerService::class.java)
		startService(intent)
    }
}

注意:WorkManager API提供了一种灵活的任务调度方式,在许多情况下,可以使用WorkManager,这比直接使用前台服务更可取。

  1. 后台服务

后台服务执行用户不会直接注意到的操作。例如,如果应用使用某个服务来压缩其存储空间,则此服务通常是后台服务。

示例代码:

kotlin 复制代码
import android.app.Service
import android.content.Intent
import android.os.IBinder

class CompressionService : Service() {

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

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        // 在这里执行压缩存储空间的操作
        compressStorage()

        // 压缩完成后,停止服务
        stopSelf()

        return START_NOT_STICKY
    }

    private fun compressStorage() {
        // 执行压缩存储空间的操作
    }
}

要在应用中启动此后台服务,可以在适当的位置(例如,活动或广播接收器)中使用以下代码:

kotlin 复制代码
val intent = Intent(context, CompressionService::class.java)
context.startService(intent)

这将触发CompressionService的onStartCommand方法,在其中执行压缩存储空间的操作。执行完操作后,服务将调用stopSelf()方法停止自身。

注意:如果您的应用面向 API 级别 26 或更高版本,当应用本身未在前台运行时,系统会对运行后台服务施加限制。在诸如此类的大多数情况下,您的应用应改为使用WorkManager

  1. 绑定服务

当应用组件通过调用 bindService() 绑定到服务时,服务即处于绑定状态。绑定服务会提供客户端-服务器接口,以便组件与服务进行交互、发送请求、接收结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

一个常见的例子是音乐播放器应用程序。以下是一个简化的示例,展示了如何使用绑定服务在应用程序中播放和控制音乐。

首先,创建一个Service类,名为MusicPlayerService,用于处理音乐播放的逻辑。

kotlin 复制代码
import android.app.Service
import android.content.Intent
import android.media.MediaPlayer
import android.os.Binder
import android.os.IBinder

class MusicPlayerService : Service() {
    private val binder = MusicPlayerBinder()
    private var mediaPlayer: MediaPlayer? = null

    inner class MusicPlayerBinder : Binder() {
        fun getService(): MusicPlayerService = this@MusicPlayerService
    }

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

    fun playMusic() {
        // 在这里实现播放音乐的逻辑
        mediaPlayer = MediaPlayer.create(this, R.raw.my_music)
        mediaPlayer?.start()
    }

    fun pauseMusic() {
        // 在这里实现暂停音乐的逻辑
        mediaPlayer?.pause()
    }

    fun stopMusic() {
        // 在这里实现停止音乐的逻辑
        mediaPlayer?.stop()
        mediaPlayer?.release()
        mediaPlayer = null
    }
}

接下来,在你的Activity中,你可以使用ServiceConnection来绑定服务并与之交互。以下是一个示例Activity的代码:

kotlin 复制代码
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private var isServiceBound = false
    private var musicPlayerService: MusicPlayerService? = null

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder = service as MusicPlayerService.MusicPlayerBinder
            musicPlayerService = binder.getService()
            isServiceBound = true
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            isServiceBound = false
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val playButton = findViewById<Button>(R.id.play_button)
        val pauseButton = findViewById<Button>(R.id.pause_button)
        val stopButton = findViewById<Button>(R.id.stop_button)

        playButton.setOnClickListener {
            if (isServiceBound) {
                musicPlayerService?.playMusic()
            }
        }

        pauseButton.setOnClickListener {
            if (isServiceBound) {
                musicPlayerService?.pauseMusic()
            }
        }

        stopButton.setOnClickListener {
            if (isServiceBound) {
                musicPlayerService?.stopMusic()
            }
        }
    }

    override fun onStart() {
        super.onStart()
        val intent = Intent(this, MusicPlayerService::class.java)
        bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }

    override fun onStop() {
        super.onStop()
        if (isServiceBound) {
            unbindService(connection)
            isServiceBound = false
        }
    }
}

在这个示例中,我们在Activity的onStart方法中使用bindService方法来绑定MusicPlayerService服务,并在onStop方法中使用unbindService方法来解绑服务。

Thank you for your reading, best regards!

相关推荐
Just_Paranoid1 天前
【AOSP】Android Dump 信息快速定位方法
android·adb·framework·service·aosp·dumpsys
帅得不敢出门1 天前
MTK Android11获取真实wifi mac地址
android·mtk
成都大菠萝1 天前
2-2-16 快速掌握Kotlin-泛型扩展函数
android
I'm Jie1 天前
Gradle 多模块依赖集中管理方案,Version Catalogs 详解(Kotlin DSL)
android·java·spring boot·kotlin·gradle·maven
BoomHe1 天前
Android 13 (API 33)开发自己的 Settings ,如何配置 WiFi BT 权限
android
城东米粉儿1 天前
ConcurrentHashMap实现原理 笔记
android
佳哥的技术分享1 天前
System.setProperty vs adb setprop (Android SystemProperties)
android·adb
Railshiqian1 天前
通过adb命令获取某个window或View/子View的绘制内容并输出为png图片的方法
android·adb·dump view
XI锐真的烦1 天前
新手该如何选择 Android 开发框架?
android
走在路上的菜鸟1 天前
Android学Dart学习笔记第二十六节 并发
android·笔记·学习·flutter