Android开发基础--Service

本文详细介绍了Android Service的基础知识,包括Service的声明、启动方式、生命周期、startService与bindService的区别,并特别提到了IntentService的工作原理,强调了它们在后台运行和跨进程访问中的应用。

一、Service简述

主要应用场景:后台运行和跨进程访问。
Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互。

二、AndroidManifest.xml 中声明

要使用Service,必须要在 AndroidManifest.xml 文件中声明

<service android:name=".service.TestService"/>
<service android:name=".service.BindService"/>

您还可在 元素中加入其他属性,以定义一些特性,如启动服务及其运行时所在进程需要的权限。android:name 属性是唯一必需的属性,用于指定服务的类名。

Service其他属性

参考官方文档:应用清单文件 -> service

<service android:description="string resource"
         android:directBootAware=["true" | "false"]
         android:enabled=["true" | "false"]
         android:exported=["true" | "false"]
         android:foregroundServiceType=["connectedDevice" | "dataSync" |
                                        "location" | "mediaPlayback" | "mediaProjection" |
                                        "phoneCall"]
         android:icon="drawable resource"
         android:isolatedProcess=["true" | "false"]
         android:label="string resource"
         android:name="string"
         android:permission="string"
         android:process="string" >
    . . .
</service>
属性说明
android:description向用户描述服务的字符串。您应将此标签设置为对字符串资源的引用,以便可以像对界面中的其他字符串那样对其进行本地化。
android:directBootAware服务是否支持直接启动,即其是否可以在用户解锁设备之前运行,默认值为 “false”。
android:enabled系统是否可实例化服务,默认值为“true”
android:exported其他应用的组件是否能调用服务或与之交互,默认值为“true”。
android:foregroundServiceType阐明服务是满足特定用例要求的前台服务。例如,“location” 类型的前台服务表示应用正在获取设备的当前位置,目的通常是继续用户发起的操作,且该操作与设备位置相关。
android:icon表示服务的图标。必须将该属性设置为对包含图像定义的可绘制资源的引用。
android:isolatedProcess如果设置为 true,则此服务将在与系统其余部分隔离的特殊进程下运行。此服务自身没有权限,只能通过 Service API 与其进行通信(绑定和启动)。
android:label可向用户显示的服务名称。如果未设置该属性,则转而使用为应用整体设置的标签。
android:name实现服务的 Service 子类的名称,没有默认值。必须指定该名称。
android:permission实体启动服务或绑定到服务所必需的权限的名称。
android:process将运行服务的进程的名称。组件可以使用自己的 process 属性替换默认值,让您可以将应用散布到多个进程中。

三、Service启动方式

  • Context.startService()
  • Context.bindService()

1. Context.startService()

启动完之后该service就在后台运行,其生命周期跟启动它的Context没有任何关系。也不能跟Context通讯。

启动

private void testStartService() {
    Intent intent = new Intent(this, TestService.class);
    intent.putExtra(TestConstant.KEY_TEST_DATA,"data transfer");
    startService(intent);
}

结束

private void testStopService() {
    Intent intent = new Intent(this, TestService.class);
    stopService(intent);
}

2. Context.bindService()

启动之后生命周期跟启动它的Context有关,比如Activity、fragment、service等。在Context中解绑之后,如果改Service没有任何绑定后该Service也就结束。

被绑定的Service:BindService

package com.example.testapp.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class BindService extends Service {

    private static final String TAG = "BindService";
    
    public BindService() {
        super();
        Log.d(TAG, "BindService: ");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ");
        return new LocalBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ");
        return super.onUnbind(intent);
    }

    public String getTestString () {
        return "binder successful";
    }

    public class LocalBinder extends Binder {
        public BindService getBindSer() {
            return BindService.this;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }
}

调用方式:先创建ServiceConnection

mSerConn = new ServiceConnection() {
    /*
    与Service交互的接口方法
    获取绑定Service传递过来的IBinder对象
    通过这个IBinder对象,与Service进行交互
     */
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mBindService = ((BindService.LocalBinder)service).getBindSer();
        String testString = mBindService.getTestString();
        Log.d(TAG, "onServiceConnected: " + "testString = " + testString);
    }

    /*
    异常情况下取消绑定时回调(绑定失败)
     */
    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "onServiceDisconnected:");
    }
};

绑定Service

Intent intent = new Intent(this,BindService.class);
bindService(intent,mSerConn,Service.BIND_AUTO_CREATE);

解绑Service
如果Activity绑定Service,要在 onDestroy() 时解绑Service

if(mBindService != null) {
    mBindService = null;
    unbindService(mSerConn);
}

四、Service生命周期

1.通过startService启动

onCreate() -> onStartCommand() -> onDestroy()

2.通过bindService启动

onCreate -> onBind() -> onUnbind() -> onDestroy()

五、区别与总结

startService总结

  1. 定义一个类继承Service
  2. 在Manifest.xml文件中配置该Service
  3. 使用Context.startService(Intent)方法启动该Service
  4. 不再使用时,调用stopService(Intent)方法停止该服务

如果服务已经开启,不会重复的执行onCreate(), 而是会调用onStart()和onStartCommand()。

一旦服务开启跟调用者(开启者)就没有任何关系了。开启者退出了,开启者挂了,服务还在后台长期的运行。开启者不能调用服务里面的方法。

bindService总结

  1. 定义一个类继承Service
  2. 在Manifest.xml文件中配置该Service
  3. 使用Context.bindService(Intent, ServiceConnection, flags)方法启动该Service
  4. 不再使用时,调用unbindService(ServiceConnection)方法停止该服务

绑定服务不会调用onstart()或者onstartcommand()方法

bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。
绑定者可以调用服务里面的方法。

六、IntentService

可以看做是Service和HandlerThread的结合体,在完成了使命之后会自动停止,适合需要在工作线程处理UI无关任务的场景。

  • IntentService 是继承自 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作。
  • 当任务执行完后,IntentService 会自动停止,不需要我们去手动结束。
  • 如果启动 IntentService 多次,那么每一个耗时操作会以工作队列的方式在 IntentService 的 onHandleIntent 回调方法中执行,依次去执行,使用串行的方式,执行完自动结束。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值