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!

相关推荐
Estar.Lee3 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
温辉_xh3 小时前
uiautomator案例
android
工业甲酰苯胺5 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
少说多做3435 小时前
Android 不同情况下使用 runOnUiThread
android·java
Estar.Lee6 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯7 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey8 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!10 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟11 小时前
Android音频采集
android·音视频
小白也想学C12 小时前
Android 功耗分析(底层篇)
android·功耗