Android中Service的简单使用

目录

创建一个Service

Activity与Service之间的通信

绑定Activity与Service

使用前台Service 

使用IntentService


创建一个Service

每一个Service都是需要在ActivityManifest.xml中进行注册的,一般都会自动注册好。

注册service:

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

创建service: 

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")
    }

}

 一般情况下,我们开启service之后会立即去执行一些动作,那些执行的动作可以写在 onStartCommand中,不要写在onCreate中,onCreate只会在第一次创建service的时候调用。 onDestroy()则负责在service结束时进行资源的释放操作。这样一个service就创建好了,下一步就是启用和停止service了,首先在activity_main.xml中定义两个按钮,用于启动和停止service。然后在activity中设置监听事件:

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

这样就完成了service的基本使用。

Activity与Service之间的通信

绑定Activity与Service

要实现 Activity与Service之间的通信还要借助onBind方法,onBind方法增强service与activity之间的联系,是service与activity之间通信的方式,使activity可以决定什么时候时候使用service和查看service的进度。这里定义了一个继承自Binder的DownloadBinder类,然后在类内部定义了两个方法用于模拟进行下载操作(实际上这两个方法都没有具体实现)。最后用onBind方法向Activity传递该类的实例mBinder。

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")
    }

}

然后在Activity中对service进行绑定,在activity_main.xml中再定义两个按钮,用于绑定和解绑service。首先,我们实现了ServiceConnect的匿名类实现,并重写onServiceConnected方法和onServiceDisconnected方法,onServiceConnected方法在Activity和service绑定成功的时候调用,而onServiceDisconnected方法在service崩溃或者进程被杀掉的时候调用。绑定时使用了bindService方法,传入的参数为 Intent对象ServiceConnection实例标志位(这里Context.BIND_AUTO_CREATE表示绑定成功自动创建service,此时onCreate会执行,但onStartCommand不会执行)。注意,当service解绑之后,service中的onDestroy方法就会执行,而要是之前执行过startService方法,那就需要同时调用stopService和  unbindService方法才能销毁service。

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
        }
    }

}

使用前台Service 

后台的service并不能保证稳定运行,所以我们可以使用前台service,将service改造,如下:

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")
    }

}

修改了onCreate方法和 onStartCommand方法 ,从后台service转变为前台service其实就是将消息通知写入service中,因为前台service还要进行权限的声明,所以还要修改AndroidManifest.xml文件如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.servicetest">

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

 而修改 onStartCommand方法是因为service是在主线程中运行的,所以service中的耗时操作会导致ANR(application not responding)问题。因此,我们需要在方法里面开启子线程来处理耗时操作,使用 stopSelf()来停止service。

使用IntentService

因为service处理耗时操作时频繁开启线程过于繁琐,所以推出了IntentService。使用方法如下:

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")
    }

}

别忘了在AndroidManifest.xml中注册service

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

 耗时操作在onHandleIntent中进行即可,它是在子线程中运行的,而在Activity中的具体使用如下:

这里定义一个按钮来开启IntentService

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

猜你喜欢

转载自blog.csdn.net/liny70858/article/details/127403347