Android组件---Service

151 阅读7分钟

Android组件---Service

1.定义、作用及特点

// 定义
    服务,Android四大组件之一,属于计算型组件。
​
// 作用
    提供需要在后台长期运行的服务,如复杂计算、音乐播放、下载等               
    
// 特点           
    无界面,后台运行,生命周期长    

2.生命周期

// 正常流程
方式一:startService
    Service启动--->onCreate--->onStartCommand--->Service running--->onDestory--->Service终止
    
方式二:
    Service绑定--->onCreate--->onBind--->Clients are bound to service--->onUnbind--->onDestory--->Service终止
​
// 常见4个手动调用的方法
    startService:启动服务
    stopService:关闭服务
    bindService:绑定服务
    unbindService:解绑服务
​
// 常见5个内部自动调用的方法
    onCreate:创建服务
    onStartCommand:开始服务
    onDestory:销毁服务        
    onBind:绑定服务
    onUnbind:解绑服务        
​

3.服务的类型

3.1 按照运行地点分类

类别特点优点缺点应用场景
本地服务(LocalService)运行在主线程,主线程终止后,服务也会被终止节约资源;通信方便,由于在同一进程,因此不需要IPC和AIDL限制性大(主进程被终止后,服务也会被终止)需要依附于某个进程(最常用的服务,如音乐播放)
远程服务(RemoteService)运行在独立进程;服务常驻在后台,不受其它Activity影响灵活:服务常驻在后台,不收其它Activity影响消耗资源:单独进程;使用AIDL进行IPC复杂系统级别服务

3.2 按照运行类型分类

类别特点应用场景
前台服务在通知栏显示通知(用户可看到)服务使用时,需让用户知道&进行相关的操作,如音乐播放服务; (服务终止时,通知栏的通知也会消失)
后台服务处于后台的通知(用户无法看到)服务使用时不需要让用户知道%进行相关操作,如天气预报、日期同步 (服务被终止时,用户无法知道)

3.3 按照功能分类

类别特点应用场景
不可通信的后台服务用startService启动,退出者退出后Service仍然存在服务不需要与Activity&Service通信
可通信的后台服务用bindService启动,调用者退出后,随调用者销毁服务需要与Activity&Service通信,需控制服务开启时刻
可通信的后台服务(同上)使用startService、bindService启动,调用者退出后,随着调用者销毁需要与Activity&Service通信,不需要控制服务开始时刻,(服务一开始遍运行)

4.本地Service

简介:本地Service是最普通、最常用的后台服务Service.
    
使用步骤:
    1.自定义Service继承自Service,重写对应的生命周期方法(onCreate、onStartCommand、onDestory、onBind)
    2.构建用于启动服务的intent对象
    3.调用startService启动Service,调用stopService停止服务
    4.在AndroidManifest文件中注册Service
    

5.Service的常用属性

属性说明备注
android:nameService的类名
android:labelService的名字若不设置,则默认Service的类名
android:iconService的图标
android:permission申明此Service的权限有提供该权限的应用才能控制或连接此服务
android:process表示该服务是否在另一个进程中运行(远程服务)不设置则默认本地服务;remote则默认成远程服务
android:enable系统默认启动true:Service会默认被系统启动;不设置则默认为false
android:exported该服务是否能够被其它应用程序所控制或连接不设置默认此项为false

6.可通信的服务Service

在本地Service的基础上,增加了与Activity通信的功能,即使用绑定Service服务
​
步骤如下:
    1.在新建子类继承Service类,并新建一个子类继承自Binder类,写入与Activity关联所需要的方法,创建实例
        MyService extends Service{
            onCreate、onStartCommand、onDestory、onBind、onUnbind                
            
            class MyBinder extends Binder {
                public void service_connect_activity{}
            }                
        }
    
    2.在主布局文件中增加bind与unbind按钮,分别进行bindService和unBindService操作
    3.Activity通过调用MyBinder类中的public方法来实现ActivityService的联系        
      即:实现了Activity指挥Service干什么,Service就去干什么的功能         
         //在Activity与Service解除关联的时候调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //实例化Service的内部类myBinder
            //通过向下转型得到了MyBinder的实例
            myBinder = (MyService.MyBinder) service;
            //在Activity调用Service类的方法
            myBinder.service_connect_Activity();
        }   
​
         //点击绑定Service
            case R.id.bindService:
                //构建绑定服务的Intent对象
                Intent bindIntent = new Intent(this, MyService.class);
                //调用bindService()方法,以此停止服务
​
                bindService(bindIntent,connection,BIND_AUTO_CREATE);
                //参数说明
                //第一个参数:Intent对象
                //第二个参数:上面创建的Serviceconnection实例
                //第三个参数:标志位
                //这里传入BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service
                //这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行
                break;
​
            //点击解绑Service
            case R.id.unbindService:
                //调用unbindService()解绑服务
                //参数是上面创建的Serviceconnection实例
                unbindService(connection);
                break;
        
    

7.前台Service

// 前台Service和后台Service(普通)最大的区别在于:
    前台Service在下拉通知栏有显示通知,但后台Service没有;
    前台服务的优先级比较高,不会由于系统内存不足而被回收;
    后台服务优先级较低,当系统出现内存不足情况时,很有可能会被回收。
        
// 具体使用
    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("执行了onCreat()");
​
        //添加下列代码将后台Service变成前台Service
        //构建"点击通知后打开MainActivity"的Intent对象
        Intent notificationIntent = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);
​
        //新建Builer对象
        Notification.Builder builer = new Notification.Builder(this);
        builer.setContentTitle("前台服务通知的标题");//设置通知的标题
        builer.setContentText("前台服务通知的内容");//设置通知的内容
        builer.setSmallIcon(R.mipmap.ic_launcher);//设置通知的图标
        builer.setContentIntent(pendingIntent);//设置点击通知后的操作
​
        Notification notification = builer.getNotification();//将Builder对象转变成普通的notification
        startForeground(1, notification);//让Service变成前台Service,并在系统的状态栏显示出来
    }        
        

8.远程Service

https://www.jianshu.com/p/34326751b2c6

9.Service与Thread的区别

Service与Thread无任何关系
后台:后台任务完全不依赖UI,即使Activity被销毁,程序被关闭,只要进程还在,后台任务就可继续运行
    
类型相同点不同点
作用运行线程运行范围
Service执行异步操作主线程进程: 完全不依赖UI/Activity,只要进程还在,Service就可继续运行; 所有Activity都可以与Service关联,并获取binder实例 & 操作其中的方法 若要处理耗时操作,则在Service里创建Thread子线程执行
Thread执行异步操作工作线程Activity 依赖与某个Activity 在一个Activity中创建的子线程,另一个Activity无法对其进行操作 Activity很难控制Thread 当Activity被销毁后,都无法再获取到之前创建的子线程实例

一般情况下,Service和Thread会联合一起使用,即在Service中再创建一个线程(工作线程),去处理耗时操作逻辑,如下代码:

方式1@Override  
public int onStartCommand(Intent intent, int flags, int startId) {  
//新建工作线程
    new Thread(new Runnable() {  
        @Override  
        public void run() {  
            // 开始执行后台任务  
        }  
    }).start();  
    return super.onStartCommand(intent, flags, startId);  
}  
​
方式2class MyBinder extends Binder {
    public void service_connect_Activity() {
    //新建工作线程
    new Thread(new Runnable() {
        @Override
        public void run() {
            // 执行具体的下载任务
        }
    }).start();
}
​

10.Service、IntentService及其他线程的区别

Service和IntentService的区别

类型运行线程结束服务 操作备注
IntentService(继承自Service)创建一个工作线程处理多线程任务不需要 在所有Activity被处理完后,系统会自动关闭服务1.IntentService为Service的onBind方法提供了默认实现:返回null 2.IntentService为Service的onStartCommand方法提供了默认实现,将请求的intent添加到队列
Service主线程(不能处理耗时操作,否则会出现ANR)需要主动调用stopService

IntentService和其他线程的区别

类型线程属性作用线程优先级
IntentService类似于后台线程(采用HandlerThread实现)后台服务(继承了Service)高 (不容易被系统杀死)
其他线程普通线程普通多线程任务低 (如进程中无活动的四大组件,则该线程的优先级非常低,容易被系统杀死)