Android -- Service

15 篇文章 0 订阅

一 Service

Service和其他组件一样,都是运行在主线程中,因此不能用它来做耗时的请求或者动作。你可以在服务中开一个线程,在线程中做耗时动作。

1.1 生命周期:
(1)单独使用startService():
onCreate()->onStartCommand()->Service running->onDestroy()->Service shut down
用stopService来结束service,调用完之后就与调用者无关了,记得服务完毕后及时关闭
(2)单独使用bindService():
onCreate()->onBind()->Clients are bound to service->onUnbind()->onDestroy()->Service shut down

1.2 对同一个service进行start和bind操作,生命周期和执行顺序
(1)startServic:调用onCreate()->onStartCommand()
(2)bindService:调用onBind()
(3)stopService:没有调用onDestory() Service仍然在运行!
(4)unbindService:调用onUnbind()->onDestory() 此时Service关闭!
被停止的服务依然有ServiceConnection 与其绑定,则服务不能销毁,直至我们把所有ServiceConnection 解绑

** 1.3 startService和binderService区别 **
startService启动过后,用stopService来结束service,调用完之后就与调用者无关了,记得服务完毕后及时关闭,startservice并不能解决我们所有的需求,比如,我有时候,需要service的返回结果,我需要和service交互,startservice显然不能完成。那么我们可以使用到bindservice

3.3 前台Service

例子:音乐播放。将一个服务设置为前台服务,只需要在绑定时调用startForeground将自己设置为前台服务即可

    @Override
    public IBinder onBind(Intent intent) {
        //设置为前台服务
        Notification.Builder builder = new Notification.Builder(this);
        builder.setContentTitle("播放音乐中..").setContentText("Diamonds").setWhen(System.currentTimeMillis()).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
        Notification notifation = builder.getNotification();
        startForeground(2, notifation);
        return mBinder;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null)
            mediaPlayer.release();
        stopForeground(true);
    }

二 IntentService

IntentService是Service类的子类,用来处理异步请求。客户端通过startService(Intent)方法传递请求给IntentService,在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程

它的优先级高于Service。IntentService通过worker thread处理每个Intent对象,执行完所有工作后自动停止Service。
使用方法:
1、创建一个类并继承IntentService,重写onHandleIntent(),这里面做具体任务,构造函数super(“线程名”);
2、在AndroidManifest.xml里注册,同Service;
3、通过startService()启动。

三 系统服务 getSystemService()

四 通信

5.1 Activity 和 Service 之间的通信

(1)直接通过Intent进行传值,性能不高。intent会在onStartComment时候得到。是Activity传给Service
(2)(适用于bindservice)通过binder, service类里onbind 返回一个当前的service,然后Activity 启动 ServiceConnection,必须实现两个方法onServiceConnection(ComponentName,IBinder) 和 onServiceDisconnection。前者的IBinder就是service 里面onBind 的返回值,所以通过这个可以进行通信,二维码服务就是这样做的,这个相当于服务通知Activity消息。但是这个需要Activity每次去拿消息。
(3)(适用于bindservice)加接口,service 注册接口回调方法供外部使用,service中进度发生变化就调用接口里的抽象方法,由于Activity实现了这个接口(在onServiceConnected里面实现),所以发生变化就会改变。然后通过Handler告诉主线程发生了变化。这个做法是Service中进度发生变化主动通知Activity。
(4)通过broadcast(广播)

五 面试问题

Service的多进程模式 & 不死进程

Activity和Service之间的通信

Android N,O,P上面service是不同的,有什么不同

除了普通 service和IntentService,你还知道什么Service,不包括自定义的。

AIDL

如何保证一个后台服务不被杀死,比较省电的方式是什么

  1. 修改onStartCommand(…)方法的返回值为START_STICKY可实现停止服务之后重启服务。
    1):START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
    2):START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务
    3):START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
    4):START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
  2. 提升service优先级:AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级
  3. 提升service进程优先级:设置为前台服务,依附于和用户交互的前台进程。
  4. onDestroy方法里重启service:
 public void onDestroy(){
  Intent localIntent = new Intent();
  localIntent.setClass(this, MyService.class); // 销毁时重新启动Service
  this.startService(localIntent);
 }
  1. 就是在service的onCreate方法里边
    startForeground(1, notice);
    第一个参数是不为零的数,代表通知ID
    第二个参数是通知的内容
@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		Notification notice = new Notification();
		startForeground(1, notice);
	}
  1. 8.0 以后不希望后台应用运行后台服务,除非特殊条件
  2. 一旦通过startForegroundService() 启动前台服务,必须在service 中有startForeground() 配套,不然会出现ANR 或者crash
  3. startForeground() 中的id 和notification 不能为0 和 null
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值