Service总括

  • startService

  • 启航流程oncreate->onStartCommand->onStart

  • 几度起步 onstartCommand->onStart

    • bindService
  • oncreate->onBind

Service是安卓四大组件之一,先前讲到了Service的生命周期,以及非绑定类型的生命周期的事例,本次来享受一下绑定方式的。

什么是serice:

Service可由其余应用组件运维,並且正是顾客切换成别的使用,服务仍就要后台继续运维。
其余,组件能够绑定到劳动,以与之举行交互,乃至是实施进度间通讯 (IPC)
(能够透过将劳动注脚为个体服务,并阻碍别的使用访谈)。

Service一般分为二种样式,一种用于实践一些下载文件等操作,无需与客户实行互动,当使用组件(如Activity)通过调用
startService()
运维服务后,服务便与开行它的零件已非亲非故联,服务会平素在后台运营,直到它承受的天职成功,服务会活动终止运维。一种是与行使组件进行绑定(调用bind瑟维斯()),举例要做一个后台播放音乐,分界面UI变化要求和音乐进程交相呼应的时候,就须求让服务与该利用分界面举行绑定。多少个零件能够同一时间绑定到该服务,但总体注销绑定后,该服务即会被灭绝。

劳动能够并且以这二种艺术运营,它不只能够是运行服务(以Infiniti时运转),也允许绑定。只要完结了onStartCommand()(允许组件运营服务)和
onBind()(允许绑定服务)这一组回调方法。注意:服务是不会本身开荒贰个新线程的,若实行一些耗费时间操作,请手动开拓贰个新线程。

启动Service的方式

  • Context.startService(Intent)如下:

     Intent intent = new Intent(this,PlayService.class);
     startService(intent);
    
  • Context.bindService(Intent,ServiceConnection,BIND_AUTO_CREATE)

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("result","绑定成功");
            PlayService.MyBinder binder = (PlayService.MyBinder) service;
      }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("result","解绑成功");
      }
    };
    Intent intent = new Intent(this,PlayService.class);
    bindService(intent,conn,BIND_AUTO_CREATE);
    

只是写三遍加深影象。

service中不能够做耗费时间任务(无法超越5s),不过service能够透过新开八个线程去做耗费时间职分,完结后告知页面做完(为啥不在actiivty中央市直机关接做吗?因为activity是很轻松被销毁的,客商按下重回键?客户推出系统?等等,那样只要被销毁了,我们就不能获取到新开的要命线程,也不能够调控,但是service不雷同,service是运作在后台,尽管页面销毁了也足以找到service,通过bindservice方法,然后在servcerconnection方法中取获得IBinder,从而对service举行操作)

应用组件(客商端)能够调用bindService()绑定到贰个service。Android系统之后调用service的onBind()方法,它回到三个用来与service交互的IBinder。

几时使用劳务:

劳务是一种不畏客商未与使用交互,但它仍可以在后台运维的组件。如需在主线程外部执行专门的学业,可是只是在客商正在与运用交互时才有此必要,则应创造新线程而非服务。若只想在三个activity运维的同临时候,则可在
onCreate() 中创建线程,在 onStart() 中运行线程,然后在 onStop()
中截止线程,或许用AsyncTask 或 HandlerThread,而非古板的 Thread
类。使线程与activity同存亡就可以,不必开启贰个服务。

两种运营情势分别:
  1. startService运行今后,若无调用stopSelf()或许stopService()就能一贯在后台运维。
    bindService运营Service之后,在起步它的零部件被销毁后也会解绑并销毁。
  2. start瑟维斯()运维Service到停止,Service经历生命周期的是onCreate()、onStartCommand()、onDestory()
    而bindService()运行Service,
    Service经历的生命周期是onCreate()、onBind()、onUnbind()、onDestory()
  3. 如果即startService又bindService启动了Service,要分别unBindService()、stopSelf()/stopService()关闭Service。这里关闭未有各类限制的,比方:先startService,后bindService。甘休时先实行unBind瑟维斯,stopService,依旧各种反过来都以从未难题的。

1 概述

一种后台服务。使用时索要在Manifest申明。
两种选拔格局:

  1. 起步形式。适用于Service无需与开发银行组件交互的光景。
  2. 绑定格局。适用于Service必要与开发银行组件交互的景色,当撤除此类Service的保有绑定者后,Service也被销毁。

那也就衍生了跨进程服务aidl

绑定是异步的,bindService()会立刻回去,它不会回来IBinder给顾客端。要选用IBinder,客商端必需创设二个瑟维斯Connection的实例并传给bindService()。ServiceConnection富含四个回调方法,系统调用这么些主意来传递要回到的IBinder。

什么样贯彻service:

为了保险应用的安全性,请始终使用显式 Intent 运维或绑定
Service,且不要为服务评释 Intent 过滤器。
运营哪个服务存在一定的不鲜明性,而一旦对这种不引人瞩目标考虑衡量极其有须要,则可为服务提供
Intent 过滤器并从 Intent 中消除相应的机件名称,但随之必得使用
setPackage() 方法设置 Intent
的软件包,那样能够尽量消除目的服务的不鲜明性。还足以因而添android:exported
属性并将其安装为 “false”,确定保障服务仅适用于您的应用。

创造服务的二种艺术:

1.瑟维斯:那是适用于具有服务的基类。

Intent intent = new Intent(this, myService.class);

startService(intent);//以此方法运营,无法获知service做什么

Intent intent = new Intent(this, myService.class);

bindService(intent,serviceConnection,
BIND_AUTO_CREATE);//BIND_AUTO_CREATE表示创造尚未激活的服务.其余或许值为
BIND_DEBUG_UNBIND 和 BIND_NOT_FOREGROUND或0(表示无)。

private ServiceConnection serviceConnection = new ServiceConnection()
{

@Override

public void onServiceDisconnected(ComponentName name) {

//Android
系统会在与劳动的接连意外中断时(比如当服务崩溃或被甘休时)调用该办法。

}

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

  myBinder = (MyBinder) service;

//myBinder是该运动和劳务相通的地方,但在实行此代码从前,活动生命周期需已改为可见

} };

public class myService extends Service {

@Override

public IBinder onBind(Intent intent) {

return myBinder;//回调,提须要移动MyBinder的指标

}

public class MyBinder extends Binder {

//可供绑定的activity调用的法子

//个人浅见,此类中的方法有些类似于接口的职能,仅表示用来和移动通讯,切勿将过多的逻辑代码放在中间。影响程序的可读性

} }

unbindService(mConnection);//当顾客端被销毁时,它将打消与服务的绑定,但一味应该在形成与劳务的竞相或Activity
暂停时撤消绑定,以便服务能够在未被挤占时关闭。

stopService(intent);//记得将后台程序关闭,极其是又运行又绑定期。

绑定是异步的。bindService()会马上回,“相对不会”使IBinder重返客商端。要接受IBinder,客商端必得创设二个瑟维斯Connection实例,并将其传递给
bindService()。ServiceConnection 满含二个回调方法,系统经过调用它来传递
IBinder。

只顾:1.要时刻记得service要想改造UI时,要用Handler,因为她们身处八个线程中。

        2.唯有Activity、服务和剧情提供程序能够绑定到劳动,广播接收器无法绑定到服务。

2.IntentService:那是 Service的子类,它采纳专门的职业线程逐个管理全体运维恳求。若是不必要服务相同的时候管理四个诉求,那是最棒的选取。
只需兑现 onHandleIntent() 方法就可以,该方法会接收每一种运营要求的 Intent。

IntentService 实行以下操作:

•创设暗中同意的劳作线程,用于在动用的主线程外实行传递给 onStartCommand()
的兼具 Intent。

•创造职业行列,用于将贰个 Intent 逐个传递给 onHandleIntent()
实现,那样恒久不要忧郁二十四线程难点。

•在拍卖完全体运行央浼后结束服务,由此不用调用 stopSelf()。

•提供 onBind() 的默许完结(重临 null)。

•提供 onStartCommand() 的默许完成,可将
Intent依次发送到职业行列和onHandleIntent() 达成。

只必要贰个构造函数和叁个 onHandleIntent()
达成就能够。而且不要从中调用超类的独一格局就是onBind()(仅当服务允许绑定期,才要求达成该方法)。

public class MyService extends IntentService {

public MyService() {

super(“MyService”);

}

@Override

protected void onHandleIntent(Intent intent) {

//大家常见会做一些专业,举例下载叁个文本。为示范,大家只睡5秒。

long endTime = System.currentTimeMillis() + 5*1000;

while (System.currentTimeMillis() < endTime) {

synchronized (this) {

try {

wait(endTime – System.currentTimeMillis());

} catch (Exception e) {

}

} } } }

运行未来再也启航的生命周期
  1. 在startService之后,再举行startService,只会再度施行Service的onStartCommond方法,而不会再施行onCreate
  2. 在bindService之后,再实行bindService,不会再奉行Service的onBind。

2 声明

选拔Service前需求在Manifest中声称,其性质有:

  1. exported[true|false]。是或不是辅助隐式调用。
  2. name
  3. permission
  4. process[:xxx|xxx]留心这里的冒号,有冒号代表经过名称叫“包名:xxx”,无冒号代表经过名称为不加包名前缀的“xxx”。
  5. isolatedProcess[true|false]。进程与其余进度分开且无权力,通讯只好通过Service的API(bindstart)。
  6. enable。父标签(若有)和子标签必需相同的时间为true,该服务才使得。

aidl跨进程

(通过三个service的操作把各类进度链接起来,service正是其一节点)

  1. aidl 初学指南
  2. 家弦户诵你要学aidl干嘛?
  3. aidl能干嘛
  4. aidl怎么干的

世家学aidl 是为着跨进度通讯,可是一个app为何要跨进程呢?因为android
每一个app就是运转在三个单身的历程中,一旦经过中稍加逻辑未有拍卖好,或然是据有内部存储器过大,引发了oom,crash会导致当前app直接闪退,严重影响了客商体验,所以大家就要把一些不是那么主要的天职管理也许要求极大的内部存储器的职责,恐怕是轻巧吸引oom(webview内存泄漏)放在新的经过中,那样
就足以幸免主app闪退,可是如此就有七个进程,进度间通讯那么就用到了aidl

aidl用于缓慢解决进度通讯。aidl原理(利用binder机制
笔者晓得的外表意思,利用service达成(service能够退出组件单独共处,所以具备比组件更加长的生命周期))

先是注册二个service并注脚在新的线程中然后通过service的onBind方法重临aidl的指标,aidl中贯彻具体的办法,在组件中落到实处serviceconnection中达成了足以调用到aidl中艺术
那样大家就完成了脚下进程调用另一个进度中的方法,落成了跨进程通讯

接下去大家现实说一下aidl(搭建景况是android studio2.3.3)

1.第一是综上说述aidl能传递什么类型的字段,总体来讲能传递java原生的连串,就像什么int,long,float,list,map等等都可以,不过如若一旦想传递温馨定三个的门类,那么该品种必得贯彻Parcelable接口(那是四个android提供类别化的格局)

2.创设aidl文件 里面定义你要促成的点子(在android studio中 新建的主意如图

图片 1image.png

)(不带本人创办的类的aidl)新建达成后
就把里面自带的不胜格局删掉(不删也行,个人习于旧贯),然后写出您想要达成的方法,那样就能够了(如图

图片 2image.png)当中connect,plus那三个章程就是大功告成原生类型的aidl方法,

若果想要完毕参数是协和的类,那么首先那一个类在您本人的app中要完结Parcelable方法这些还非常不足,还要创设一个一见钟情的aidl文件,不过创立发掘,android
studio会提醒重名了?(那个你绝不管,随意弄三个名字创办四个aidl,然后把内部的事物删掉,改成如图

图片 3image.png

那样,这里
Message改成你本人想要的类名就行)然后正是发端创办和睦的aidl实例

public class LibHandler extends IHandler.Stub { private RemoteCallbackList<ICallback> iCallbackRemoteCallbackList; private Handler handler = new Handler(); public LibHandler() { iCallbackRemoteCallbackList = new RemoteCallbackList<>(); } @Override public void connect() throws RemoteException { Log.d("aidl", "connect; } @Override public void sendMessage(Message message) throws RemoteException { Log.d("aidl", message.content); } @Override public int plus(int a, int b) throws RemoteException { Log.d("aidl", a + " " + b); pushMessage(); return a + b; } int i = 1; private void pushMessage() { i++; handler.postDelayed(new Runnable() { @Override public void run() { try { int length = iCallbackRemoteCallbackList.beginBroadcast(); Log.d("aidl", " " + length); for (int i = 0; i < length; i++) { iCallbackRemoteCallbackList.getBroadcastItem.callback(new Random().nextInt; } } catch (RemoteException e) { e.printStackTrace(); } iCallbackRemoteCallbackList.finishBroadcast(); pushMessage(); } }, 2000); } @Override public void register(final ICallback callback) throws RemoteException { if (callback != null) { iCallbackRemoteCallbackList.register; } } @Override public void unregister(ICallback callback) throws RemoteException { if (callback != null) { iCallbackRemoteCallbackList.unregister; } } @Override public IBinder asBinder() { Log.d("aidl", "asBinder"); return super.asBinder(); }}

如同那样就行了,如若中间出现有的怎么着找不到类的报错 build-》make
project一下,android studio
会生成aidl对应的java文件,那样大家后续的aidl文件就能被as找到然后在service的onBind方法中回到大家的aidl
就足以了(如图

图片 4image.png

如此 大家的service就到底产生了远程的service

接下去看看组件中 是怎么落到实处与长途service链接的

 Intent intent = new Intent(); intent.setAction("com.boger.aidl.service"); intent.setPackage("com.boger.aidldemo"); bindService(intent, connection, Context.BIND_AUTO_CREATE); ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mServer = IHandler.Stub.asInterface; try {// String content = null; mServer.connect(); int value = mServer.plus; Message message = new Message(); message.setContent("content"); message.setId; mServer.sendMessage; mServer.register; tv.setText(value + ""); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mServer = null; } }; ICallback callback = new ICallback.Stub() { @Override public void callback throws RemoteException { handler.sendEmptyMessage; } };

就那样 就足以了

理所当然我那是一种隐式调用(针对别的app运转该service,本人的app能够一贯Intent
intent = new Intent(package,
Servicename.class)),在5.0之上service禁止隐式调用,会报四个 ServiceIntent must be explicit,去contextImpl源码中窥见
系统会推断service的package是还是不是为空,所以大家要设置package(正是中远距离服务所在的提请)所以要intent.setpackage

那就造成了,大要实现了跨进度通讯了

  • 实现ServiceConnection

劳务的生命周期:

图片 5

左:由startService() 创建,右:由bindService() 创建

劳务生命周期(从创建到销毁)可以听从两条差别的门道:

1.运转服务:该服务在其余零件调用 startService()
时创设,然后无有效期运营,且必得通过调用 stopSelf()
来自行结束运转,恐怕其余零件通过调用 stopService()
来终止服务。服务结束后,系统会将其销毁。

2.绑定服务:该服务在另贰个组件调用 bindService() 时创设。然后,客商端通过
IBinder 接口与劳务拓宽通讯。客商端能够透过调用 unbindService()
关闭连接。四个客商端可以绑定到一样服务,何况当全部绑定全体撤回后,系统即会销毁该服务。
(服务不必自行结束运维。)

这两条门路并非完全部独用立。例如,能够经过应用
Intent(标志要播放的音乐)调用 start瑟维斯()
来运维后台音乐服务。随后,Activity 能够由此调用 bindService()
绑定到劳动。在这种地方下,除非全数客商端均撤废绑定,不然 stop瑟维斯()
或 stopSelf() 不会真的甘休服务。

透过落到实处那些措施,您能够监察和控制服务员命周期的八个嵌套循环:

•服务的整个生命周期从调用 onCreate() 开头起,到 onDestroy()
再次回到时结束。与 Activity 类似,服务也在 onCreate() 中做到初始设置,并在
onDestroy() 中放出具备盈余资源。

•服务的实用生命周期从调用 onStartCommand() 或 onBind()
方法伊始。每一种格局均有 Intent 对象,该指标分别传递到 startService() 或
bindService()。

对此运转服务,有效生命周期与一切生命周期同期终止(即便是在
onStartCommand()
重返之后,服务照旧处在活动状态)。对于绑定服务,有效生命周期在
onUnbind() 重临时截至。

注:尽管运行服务是经过调用 stopSelf() 或 stopService()
来终止,不过该服务并无相应的回调(未有 onStop()
回调)。因而,除非服务绑定到客商端,不然在劳动结束时,系统会将其销毁—onDestroy()
是吸收接纳到的独一遍调。

图 2 表明了劳务的榜第一遍调方法。尽管该图分开介绍通过 start瑟维斯()
创建的服务和透过 bindService()
创建的劳务,不过请牢记,不管运维格局如何,任何劳动均有希望同意顾客端与其绑定。由此,最早使用
onStartCommand()(通过顾客端调用 startService())运维的劳动仍可接纳对
onBind()的调用(当客商端调用bindService() 时)。

和Activity交互

  • Activity在运行Service的时候,能够经过Intent.putExtra来给Service传递数据(二种艺术均可)

  • 通过bindService()运营Service,通过onBind()再次来到的Binder来指挥Service来张开操作

       class MyBinder extends Binder{
         public void action()
       }
    
  • Service给Activity回传数据,能够经过在Service中发送广播,在Activity注册广播接收数据

3 运行服务

填补一下 aidl完成回调

(要事先
一向是客商端直接通过措施去找aidl要东西,回调就兑现了aidl主动给顾客端东西)其实总体思路正是相似的接口回调(回调的思绪正是在aidl设置一个接口作为参数,然后aidl中callback.callbackMethod就能够了把params传给了客商端,接口回调不懂的能够看自个儿的早先时期小说,有讲的)

那么将要定义aidl接口,其实就是新建一个接口的aidl文件就行了如图(

图片 6image.png

)然后就在我们的aidl设置这几个接口为参数就行了,那样就足以了

自己要说小心的地点便是在registerCallback

private RemoteCallbackList<ICallback> iCallbackRemoteCallbackList;
供给求经过那个来for循环来注册种种callback,具体请看笔者的Libhandler中的达成

讲讲怎么那样,因为是远程服务,所以不自然独有叁个callback,所以就要求map把各种callback与种种注册的长途服务相绑定,真心钦佩android人士统一计划的神妙

福寿齐天必须重写八个回调方法:

IntentService与Service

  1. IntentService比Service好在哪?

IntentService 是接二连三于 Service 并管理异步诉求的三个类,在 IntentService内有叁个行事线程来拍卖耗费时间操作,运维 IntentService 的措施和开发银行守旧Service 同样,同有的时候间,当职分实践完后,IntentService会自动终止,而无需大家去手动调控。别的,可以运转 IntentService多次,而每二个耗费时间操作会以办事行列的法子在IntentService 的
onHandleIntent
回调方法中实施,并且,每一次只会进行叁个做事线程,推行完第一个再执行第贰个,就那样推算。

  1. IntentService 为何能够管理耗费时间义务? 

相应从源码上边来解析,IntentService 是一直接轨与 Service的,内部在
onCreate()时,新建了二个HandlerThread 实例。

(HandlerThread 是五个Thread的 子类,HandlerThread 内部
有一点点线我们的UI线程,内部二个Looper loop循环平素轮询音讯 获得消息处理新闻。)

而IntentService, 内部有一个Handler子类
ServiceHandler,它的Looper用的是那些HandlerThread 的Looper,IntentSerivce
在onStart()通过发送Message,ServiceHandler在管理Message 调用的是
onHandleIntent。

所以一言以蔽之叁个IntentService,内部就成立了一个线程,通过Android提供的
Handler Message
Looper,这一个音讯管理的类构成了二个新闻处理的模子。所以IntentService的onHandleIntent 这一个艺术其实是在IntentService中开荒的贰个子线程中管理的。

Service是运维在UI线程的

  • 一经急需在Service中做耗费时间操作,要求别的起贰个线程。
  • 当然你还足以应用IntentService

3.1 startService启动

这种措施运营的Service不会趁着运行者的退出而停下,能够用stopService(Intent)照旧服务本人调用stopSelf停止。
每一次运行都会调用onStartCommand

总结

那正是作者精晓的aidl,希望对阅读的你具有协理,当然
这里若是有不足,迎接建议和笔者联系.

onServiceConnected()

IntentService

IntentService优点如下:

  • Service中的事情管理达成未来,它会调用stopSelf()甘休自个儿
  • Service能够一向管理耗费时间操作

Intent瑟维斯的为主使用如下:

  public class DownloadService extends IntentService {
      public DownloadService() {
          super("DownLoadService");
      }
      @Override
      public void onCreate() {
          super.onCreate();
          Log.e("result", "onCreate");
      }
      @Override
      public void onStart(@Nullable Intent intent, int startId) {
          super.onStart(intent, startId);
      }
      @Override
      public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
          Log.e("result", "onStartCommand");
          return super.onStartCommand(intent, flags, startId);
      }
      @Override
      protected void onHandleIntent(Intent intent) {
          Log.e("result", "onHandleIntent");
      }
  }

亟需注意的是:它的构造方法必需给他提供贰个无参构造方法,名字就命名叫类名就能够。

  • IntentService的原理
    IntentService封装了HandlerThread和Handler,HandlerThread正是贰个Thread(具体再剖析),Handler
    handler = new
    Handler(handerThread.getLooper()),handler是由子线程中的Looper构造的,约等于在子线程中有个一个MessageQueue音信队列,大家每一回startService(),正是sendMessage()加多一个消息到行列中,然后该childThread的Looper不断的从MessageQueue中抽出音讯去处理。

亟待关怀的艺术

  • onCreate
    第一遍创制Service时回调此情势,之后不会再回调。

  • onStartCommand(Intent intent,int flag,int startId)
    startService时会回调,然后运维服务。

    • @params
      intent是开发银行服务时的传参。
      flag有三个值:
      1.0,无参数。
      2.START_FLAG_REDELIVERY。代表本办法的重返值为
      START_REDELIVER_INTENT,当service因内部存款和储蓄器不足被系统关闭后,会
      用最后贰个传诵的intent用作参数再一次调用本办法(onStartCommand)。
      3.意味着当本方法调用后直接从未再次来到值时,会另行调用本办法。
      startId此时此刻服务id。
    • @return
      多个可选值:
      1.START_STICKY。Service因内部存款和储蓄器不足被杀死后,尝试再次创立此服务并回调onStartCommand,传入intent为空(除非有挂起的pendingIntent)。适用于无有效期运行等待作业的播放器等。
      2.START_NOT_STICKY。不重启。
      3.START_REDELIVER_INTENT。重启并传递最终的intent。适用于回复下载等。
  • onDestroy
    在这里清理全数能源。

系统调用那几个来传送在service的onBind()中回到的IBinder。

牢记:Handler构造中的Looper在哪个线程,该Handler就为哪个线程服务。假使是无参构造正是MainThread,因为当中调用了looper.myLooper()。

3.2 bindService启动

Service处于绑定状态时,也正是“client-server”模型中的server,client通过代理与server交互。
绑定的Service的生命周期与宿主绑定,宿主退出即服务销毁。
鲜明,在绑定服务时必须提供IBinder接口的达成。

OnServiceDisconnected()

AIDL进度间通讯

  1. 在服务端定义aidl文件:在src/main目录下创立aidl文件夹,然后在文件夹内创造aidl文件如下:

     package com.thc.aidldemo;
     interface AidlTest1 {
           int test1(int a,int b);
     }
    

成立之后要sync project with gradle

  1. 在服务端的Service上校作为Binder重回给绑定服务的机件,代码如下:

     public class AidlService1 extends Service {
          @Override
          public void onCreate() {
               super.onCreate();
               Log.e("result", "onCreate()");
          }
           @Override
          public IBinder onBind(Intent intent) {
               return binder;
          }
           @Override
           public boolean onUnbind(Intent intent) {
               Log.e("result", "onUnbind()");
               return super.onUnbind(intent);
           }
          /**
            * 这里为什么可以这样写呢?因为Stub其实就是Binder的子类,所以在onBind()方法中可以直接返回Stub的实现。
            */
           AidlTest1.Stub binder = new AidlTest1.Stub() {
               @Override
               public int test1(int a, int b) throws RemoteException {
                   return a+b;
               }
           };
       }
    
  2. 借使是八个应用的话,需求在Client端定义和Server端同样的aidl文件,切记目录也要完全平等

  3. 然后再Client端通过BindService调用长途服务,代码如下,和bindService同样:

     public class MainActivity extends AppCompatActivity {
    
       private ServiceConnection conn = new ServiceConnection() {
           @Override
           public void onServiceConnected(ComponentName name, IBinder service) {
                 Log.e("result", "远程服务绑定成功");
                 aidlTest1 = AidlTest1.Stub.asInterface(service);
           }
           @Override
           public void onServiceDisconnected(ComponentName name) {
               Log.e("result", "远程服务解绑成功");
           }  
       };
       private AidlTest1 aidlTest1;
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           Intent intent = new Intent();
           intent.setComponent(new ComponentName("com.thc.aidldemo", "com.thc.aidldemo.AidlService1"));
           bindService(intent, conn, BIND_AUTO_CREATE);
       }
    
       public void caculate(View view) {
           try {
               int i = aidlTest1.test1(1, 2);
               Log.e("result", "计算之后的值:" + i);
           } catch (RemoteException e) {
               e.printStackTrace();
           }
       }
     }
    

定义Service接口的二种艺术

1.扩展Binder类。
client通过binder调用service提供的力量。常用来service作为本金和利息用的后台线程的动静,比方下载、播放等。
独一不适用的场景是service须要提须求别的app调用。
2.使用Messenger
Messenger用于跨进度传递数据(基于Handler、AIDL,本质是包裹之后的AIDL),可以选择其为服务定制接口。
Messenger串行管理客商端发来的音信(线程安全)。
3.使用AIDL
同意相同的时候管理四个跨进度的央求。
貌似同一时间利用线程安全式设计。使用时须要自定义.aidl文件。SDK工具利用该公文生成达成接口并拍卖IPC的抽象类,随后对其实行扩展。

Android系统在同service的连接意外错过时调用这么些.例如当service崩溃了或被强杀了.当客商端解除绑定期,这一个办法不会被调用。

静心:跨进度start瑟维斯()要显示运营,即:
    new ComponentName("com.thc.aidldemo", "com.thc.aidldemo.AidlService1")

背后的类名也要丰盛包名.类名
AidlDemo地址

3.2.1 扩展Binder类

1.在Service的子类(指标业务类)中开创贰个兑现Binder接口的实例对象,并实现国有艺术用于客商端调用
2.onBind()回调重返此Binder实例;
3.在客商端中,从onServiceConnected()回调方法接收Binder,并用提供的措施调用服务的技术。

标准气象是后台音乐服务。劳务和客商端必得在一直以来进度内。

// flag 0代表不创建service,BIND_AUTO_CREATE代表绑定时自动创建service
bindService(intent,conn,Service.BIND_AUTO_CREATE);



conn = new ServiceConnection() {
    /**
     * @param name 封装组件的描述信息,很少使用
     * 与服务器端交互的接口方法 绑定服务的时候被回调,在这个方法获取绑定Service传递过来的IBinder对象,
     * 通过这个IBinder对象,实现宿主和Service的交互。
     */
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "绑定成功调用:onServiceConnected");
        // 获取Binder
        // 注意这里是将IBinder接口强转为Binder实现类
        LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
        mService = binder.getService();
    }
    /**
     * 当取消绑定的时候被回调。但正常情况下是不被调用的,它的调用时机是当Service服务被意外销毁时,
     * 例如内存的资源不足时这个方法才被自动调用。
     * 当客户端取消绑定,不会回调此方法
     */
    @Override
    public void onServiceDisconnected(ComponentName name) {
        mService=null;
    }
};

几度调用bindServiceunbindService,对应的onBindonUnbind也只会回调一遍。
绑定格局的service生命周期为onCreate->onBind->onUnbind->onDestroy

  • 调用bindService(),传给它ServiceConnection的实现。

  • 当系统调用你的on瑟维斯Connected()方法时,你就足以选取接口定义的办法们起先调用service了。

  • 要与service断开连接,调用unbindService()。

  • 程序                                                                                          

    public class MainActivity extends Activity {
    
        private Button btn_start;
        private Button btn_stop;
        private Button btn_change;
        private Button btn_bind;
        private Button btn_unbind;
    
        private MyConn myConn;
    
        private IService myBinder;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btn_start = (Button) findViewById(R.id.btn_start);
            btn_stop = (Button) findViewById(R.id.btn_stop);
            btn_change = (Button) findViewById(R.id.btn_change);
            btn_bind = (Button) findViewById(R.id.btn_bind);
            btn_unbind = (Button) findViewById(R.id.btn_unbind);
            buttonListener bl = new buttonListener();
            btn_change.setOnClickListener(bl);
            btn_start.setOnClickListener(bl);
            btn_stop.setOnClickListener(bl);
            btn_bind.setOnClickListener(bl);
            btn_unbind.setOnClickListener(bl);
    

前台Service

3.2.2 Messenger

用来差别进程间的通讯。若是急需相互发送音讯,要求在服务端和客商端都布署Messenger和Handler。大约进度如下:
1.服务端达成Handler,用于吸收接纳顾客端的回调;
2.施用上述Handler创建Messenger
3.用Messenger创建IBinder,在serviceonBind措施中,将其归来客商端;return mMessenger.getBinder();
4.客商端收到IBinder后,用实际例化Messengernew Message(iBinder)),用其发送Message
5.MessengerHandler中(handleMessage())接收Message并处理。

图片 7

messenger.jpg

        }

        class buttonListener implements OnClickListener
        {

            @Override
            public void onClick(View v) {
                switch (v.getId()) {
                case R.id.btn_start:
                    Intent intent_start = new Intent(getApplicationContext(),BindService.class);
                    startService(intent_start);
                    break;
                case R.id.btn_stop:
                    Intent intent_stop = new Intent(getApplicationContext(),BindService.class);
                    stopService(intent_stop);
                    break;
                case R.id.btn_change:
                    if(myBinder != null)
                        myBinder.doChange("啦啦啦");
                    break;
                case R.id.btn_bind:
                    if(myConn == null)
                    {
                        myConn = new MyConn();
                        Intent intent_bind = new Intent(getApplicationContext(),BindService.class);
                        bindService(intent_bind, myConn, BIND_AUTO_CREATE);
                    }
                    break;
                case R.id.btn_unbind:
                    Intent intent_unbind = new Intent(getApplicationContext(),BindService.class);
                    if(myConn != null && myBinder != null)
                    {
                        unbindService(myConn);
                        myConn = null;
                        myBinder = null;
                    }
                    break;

                default:
                    break;
                }

            }

        }

        private class MyConn implements ServiceConnection
        {

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                System.out.println("代理人返回回来了,onServiceConnected");
                myBinder = (IService) service;

            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                System.out.println("接触绑定了,onServiceDisconnected");

            }

        }


    }

Service类:

    public class BindService extends Service {

        @Override
        public IBinder onBind(Intent intent) {
            System.out.println("Service绑定成功,onBind");
            //返回自定义的代理对象
            return new MyBinder();//这里的返回是返回到MainActivity里面的绑定myConn
        }



        @Override
        public boolean onUnbind(Intent intent) {
            System.out.println("Service解绑成功,onUnbind");
            return super.onUnbind(intent);
        }



        public class MyBinder extends Binder implements IService
        {
            //间接的利用代理人调用了changeServiceThing的方法
            public void doChange(String what)
            {
                changeServiceThing(what);
            }
        }

        @Override
        public void onCreate() {
            System.out.println("Service开启,onCreate");
            super.onCreate();
        }

        @Override
        public void onDestroy() {
            System.out.println("Service关闭,onDestroy");
            super.onDestroy();
        }

        public void changeServiceThing(String what)
        {
            Toast.makeText(getApplicationContext(), what+"变换了,changeServiceThing", Toast.LENGTH_LONG).show();
        }



    }

IService:

    public interface IService {
        public void doChange(String what);
    }

**结果                                                                                           
**

点击“开启服务”之后,再“绑定服务”,这样执行之后直接点“关闭服务”是没用的,要先“解除服务”,再“关闭服务”。如果直接“绑定服务”,那么点击“关闭服务”没有用,需要点击“解绑服务”。

**aidl                                                                                           **


进程间通信-&gt;调用者和Service如果不在一个进程内,就需要使用android中的远程Service调用机制。

android使用AIDL定义进程间的通信接口。AIDL的语法与java接口类似,需要注意以下几点:

-   AIDL文件必须以.aidl作为后缀名。
-   AIDL接口中用到的数据类型, 除了基本类型, String, List, Map,
    CharSequence之外, 其他类型都需要导包, 即使两种在同一个包内.
    List和Map中的元素类型必须是AIDL支持的类型。
-   接口名需要和文件名相同。
-   方法的参数或返回值是自定义类型时,
    该自定义的类型必须实现了Parcelable接口。
-   所有非java基本类型参数都需要加上in, out, inout标记,
    以表明参数是输入参数, 输出参数, 还是输入输出参数。
-   接口和方法前不能使用访问修饰符和static, final等修饰。

进程间通信需要创建aidl文件,IService.aidl:

    public interface IService {
        public void doChange(String what);
    }

接口中有一个static的抽象内部类Stub,Stub类继承了Binder类并实现了IRemoteService接口。

    public class MainActivity extends Activity {

        private Intent intent;
        private IService iService;
        private ServiceConnection myConn;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

        }

        public void bind(View view) {
            intent = new Intent();
            intent.setAction("com.yydcdut.alipay");
            myConn = new MyConn();
            boolean flag = bindService(intent, myConn, BIND_AUTO_CREATE);
            System.out.println("flag------>" + flag);
        }

        private class MyConn implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                iService = IService.Stub.asInterface(service);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        }

        public void method(View view) {
            try {
                iService.callMethodInService();
            } catch (RemoteException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
        }

    }

在实现这个的时候我建立了两个程序,这样可以做到进程间通信。附带了源码。

**我是天王盖地虎的分割线                                                               
**

源代码:<http://pan.baidu.com/s/1dD1Qx01>

service学习2.zip

aidl学习.zip

aidl学习配套2.zip

 

 

转载请注明出处:<http://www.cnblogs.com/yydcdut>

补充

onStartCommand()方法的重回值难点:

   /**
     * 返回值释义:
     * START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。
     * 随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。
     * 如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
     *
     * START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
     *
     * START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
     *
     * START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
     */

3.2.3 绑定服务注意

1.多少个客商端能够何况绑定多少个服务,唯有第贰次绑定回调onBind,别的景况系统会活动传送IBinder;除非startService也运转了该服务,不然最终叁个顾客端打消绑定期,服务被销毁。
2.应该在客商端的引进和剥离时刻绑定、注销服务。只要求在activity可知时存在的劳务应绑定在onStartonStop;需求在activity存活时期都运营的劳务,应该绑定在onCreateonDestroy,並且应该做实进程的权重。
3.不该在onPauseonResume以内绑定、撤销绑定,它们太频仍,还要只怕引起服务的绝迹和重新建立
4.远程主意也许引起DeadObjectException,由连续中断引发,表示调用的对象已去世(service对象已灭绝),那是长途方法的头一无二卓殊,承继RemoteException
5.bindService艺术内部,系统会调用服务的onBind方法,重回用于与服务交互的IBinder该方式是异步的

 

3.2.4 运行服务、绑定服务的开始的一段时期级难点

startService(运转服务)的事先级大于bindService(绑定服务)。若同临时常候运行、绑定了劳动,在调用stopService或者stopSelf事先,纵然具有客商端都收回绑定了,服务在成功前也不会甘休。
同样,在仍有顾客端绑定在服务上时,stopService或者stopSelf也不会终止服务。

3.3 服务在其托管进度的主线程运维

一经急需实行耗费时间操作,供给另起新的线程。

3.4 前台服务以及布告

前台服务在场地栏提供无法解决通告(除非服务甘休也许在此从前台删除),例如音乐播放器。
七个有关的艺术:
1.startForeground(int
id,Notification)。参数字突显然为标记id(不得为0)和通报。
2.stopForeground(boolean removeNotification)
此前台删除服务并剔除文告。

3.5 常见使用处境

下载文件,service后台实行,notification前台展现,thread异步下载。
app维持service从互连网获取推送服务。
此间引进商量IntentService

3.6 生命周期

图片 8

service_life.jpg

3.7 展现、隐式运维

  • 来得运转

Intent  intent=new Intent(this,xxxService.class);
startService(intent);
  • 隐式运营
    重在用以运营别的使用的Service。
    Intent设置action,可以是劳务的整整径名,此时android:exported默认为true

Intent intent=new Intent();
intent.setAction("com.android.xxxService");
startService(intent);

隐式运行在4.4版本会警告,5.0以上会抛格外,因为隐式注明intent去运营瑟维斯是不安全的。

  • 急需同有的时候候设置action和packageName
    就是加多

intent.setPackage(getPackageName());//设置应用包名
  • 退换为显式运营
    需要为intent设置component再开行服务。

public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
    // Retrieve all services that can match the given intent
     PackageManager pm = context.getPackageManager();
     List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
     // Make sure only one match was found
     if (resolveInfo == null || resolveInfo.size() != 1) {
         return null;
     }
     // Get component info and create ComponentName
     ResolveInfo serviceInfo = resolveInfo.get(0);
     String packageName = serviceInfo.serviceInfo.packageName;
     String className = serviceInfo.serviceInfo.name;
     ComponentName component = new ComponentName(packageName, className);
     // Create a new intent. Use the old one for extras and such reuse
     Intent explicitIntent = new Intent(implicitIntent);
     // Set the component to be explicit
     explicitIntent.setComponent(component);
     return explicitIntent;
    }

参照文章

zejian_-关于Android
Service真正的一丝一毫详解,你须要了解的全数

发表评论

电子邮件地址不会被公开。 必填项已用*标注