Service全方位了然

ca88会员登录中心

Service作为四大组件之一,在Android开垦中的地位十分重要。Service首要用以完毕后台任务,遵照使用情形的例外,Service有着不相同的特色,在本篇小说中将主要介绍。

一、Service简介

Service是Android程序中四大基础零部件之一,是在后台运营的零件。

Service是Android中完成程序后台运维的应用方案,它不行适用于去实践那么些没有要求和客商交互何况还须要短期运维的职分。Service暗中同意并不会运作在子线程中,它也不运转在二个独自的进度中,它一律进行在UI线程中,由此,不要在Service中实行耗费时间的操作,除非你在Service中开创了子线程来形成耗费时间操作。

<br />

Service是Android中贯彻程序后台运转的缓慢解决方案,它可怜适用于去施行那多少个无需和客商交互况兼还要长时间运营的天职。

一、Service简介

Service是Android程序中四大基础零部件之一,它和Activity同样都是Context的子类,只然则它未有UI分界面,是在后台运营的零件。

Service是Android中贯彻程序后台运维的减轻方案,它丰盛适用于去实施那多少个无需和客户交互何况还需要长时间运维的天职。Service暗中同意并不会运作在子线程中,它也不运营在一个独门的长河中,它相同进行在UI线程中,由此,不要在瑟维斯中进行耗费时间的操作,除非你在Service中开创了子线程来实现耗费时间操作。

二、Service分类

  • Service生命周期
    Service生命周期能够从二种运维Service的情势开始讲起,分别是context.startService()context.bindService()

    • startService的运转格局下的生命周期:当大家第三回选取startService()运行四个劳务时,系统会实例化三个Service实例,依次调用其onCreate()和onStartCommand()方法,然后进入运营境况。此后,假设再选取start瑟维斯()运转服务时,不再次创下立新的劳动对象,每一个服务只会存在三个实例,系统会活动找到刚才创设的Service实例,间接调用了onStartCommand()方法(onStartCommand()中又调用了onStart()方法)。假若大家想要停掉三个服务,可采取stopService()方法,此时onDestroy()方法会被调用。必要小心的是,不管后边使用了数13遍startService(),只需贰遍stopService(),或小编的stopSelf()方法,就能够停掉服务。
    • bindService起步形式下的生命周期:在这种方式下,当调用者第贰遍选取bindService()绑定多个劳务时,系统会实例化贰个Service实例,并逐一调用其onCreate()方法和onBind()方法,不管未来调用
      bindService()
      几遍,onCreate()方法都只会调用二回,同期onBind()方法始终不会被调用。如若大家必要破除与那些服务的绑定,可调用Context.unbindService()
      断开连接大概此前调用bind瑟维斯()的 Context
      不设有了(如Activity被finish的时候),系统将会自行终止Service,此时onUnbind()方法和onDestroy()方法会被调用。
      两种艺术的流水线:

二、Service种类

按运营地点分类:

图片 1按运营项目分类:图片 2按使用办法分类:图片 3

按运营项目分类:

图片 2

图片 5

三、Service生命周期

图片 6

OnCreate()系统在service第贰回创制时施行此形式,来实施只运转一遍的初叶化工作。假诺service已经运维,这一个法子不会被调用。

onStartCommand()老是客商端调用startService()方法运维该Service都会回调该办法(几度调用)。一旦这些办法实行,service就运转而且在后台长期运转。通过调用stopSelf()或stopService()来终止服务。

OnBind()当组件调用bindService()想要绑定到service时(例如想要实施进程间通讯)系统调用此办法(三次调用,一旦绑定后,后一次再调用bindService。在您的落实中,你必得提供八个回到一个IBinder来以使顾客端能够利用它与service通信,你必须三番五次完毕那几个办法,不过要是您不容许绑定,那么您应重回null。

OnUnbind()当前组件调用unbindService(),想要解除与service的绑定期系统调用此办法(二次调用,一旦解除绑定后,后一次再调用unbindService。

OnDestory()系统在service不再被利用并要销毁时调用此方法(一遍调用).service应在此办法中自由财富,例如线程,已登记的侦听器,接收器等等.那是service收到的末段八个调用。

下边介绍两种差异情形下Service的生命周期情状。

生命周期顺序:onCreate->onStartCommand->onDestroy

倘若三个Service被有个别Activity 调用
Context.startService方法运行,那么不论是是不是有Activity使用bindService绑定或unbindService解除绑定到该Service,该瑟维斯都在后台运转,直到被调用stopService,或自身的stopSelf方法。当然如若系统财富不足,android系统也恐怕终结劳动,还会有一种方法能够关闭服务,在安装中,通过应用->找到自身使用->甘休。

注意点:

①第贰次 startService 会触发 onCreate 和
onStartCommand,现在在劳动运作进程中,每一回 startService 都只会触发
onStartCommand

②无论 startService 多少次,stopService 三遍就能够结束服务

生命周期顺序:onCreate->onBind->onUnBind->onDestroy

假如三个Service在某些Activity中被调用bindService方法运营,不论bindService被调用三次,Service的onCreate方法只会进行二回,同临时间onStartCommand方法始终不会调用。

当创建连接后,Service会一向运行,除非调用unbindService来接触绑定、断开连接或调用该Service的Context不设有了(如Activity被Finish——即透过bindService运行的Service的生命周期依赖于运行它的Context),系统在此刻会自动甘休该Service。

注意点:

率先次 bindService 会触发 onCreate 和 onBind,未来在劳动运转进度中,每一次bindService 都不会触发任何回调

当贰个Service在被运维(startService)的同不经常候又被绑定(bindService),该Service将会平素在后台运转,并且不管调用一回,onCreate方法始终只会调用叁次,onStartCommand的调用次数与startService调用的次数一致(使用bindService方法不会调用onStartCommand)。同不日常候,调用unBindService将不会终止Service,必需调用stopService或Service自己的stopSelf来终止服务。

①假设你只是想要运转贰个后台服务长时间进行某项职务那么使用 startService便得以了。

②比如你想要与正在运营的 Service 获得联络,那么有三种办法,一种是选取broadcast ,别的是选取 bindService,前者的劣点是只要交换比较频仍,轻便导致质量上的难题,并且布罗兹castReceiver
本人实施代码的时间是异常的短的(恐怕推行到百分之五十,前面包车型大巴代码便不会试行),而后面一个则并未有那么些主题材料,因而我们一定选取选拔bindService(今年你便相同的时候在动用 startService 和 bindService 了,那在
Activity 中创新 Service 的某个运维境况是一定平价的)。

③就算您的劳务只是明目张胆叁个长距离接口,供连接上的客服端(android 的 Service是C/S架构)远程调用实践措施。那个时候你能够不让服务一最初就运营,而只用
bindService ,那样在首先次 bindService的时候才会创立服务的实例运维它,那会省去非常多系统能源,特别是借令你的劳务是Remote
Service,那么该意义会越显明(当然在 瑟维斯成立的时候会花去认定期间,你应有注意到那点)。那部分首要使用是AIDL,能够看那篇小说。

按使用方式分类:

图片 3

<br />

Service生命周期.png

四、Service的二种典型使用实例

不可互相的后台服务便是普通的Service,通过startService()方式拉开。Service的生命周期非常粗略,分别为onCreate、onStartCommand、onDestroy这多少个。

创造服务类:

public class BackService extends Service { private Thread mThread; @Override public void onCreate() { super.onCreate(); } @Nullable @Override public IBinder onBind(Intent intent) { System.out.println; return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { //执行耗时操作 mThread = new Thread() { @Override public void run() { try { while  { //等待停止线程 if (this.isInterrupted { throw new InterruptedException(); } //耗时操作。 System.out.println; } } catch (InterruptedException e) { e.printStackTrace(); } } }; mThread.start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); //停止线程 mThread.interrupt(); }}

布局服务:

 <service android:name=".BackService"></service>

假若想布署成远程服务,加如下代码:

android:process="remote"

布局好Service类,只须要在前台,调用startService()方法,就能够运转耗时操作。

注意:

①不运维在多少个独门的长河中,它同样举办在UI线程中,因此,在Service中开创了子线程来形成耗费时间操作。

②当Service关闭后,如若在onDestory()方法中不停歇线程,你会意识大家的子线程进行的耗时操作是一向留存的,此时关门该子线程的法子供给直接关闭该应用程序。由此,在onDestory()方法中要扩充供给的清理专门的学问。

可相互的后台服务是指前台页面能够调用后台服务的法子,通过bindService()格局展开。Service的生命周期很简短,分别为onCreate、onBind、onUnBind、onDestroy这八个。可交互的后台服务达成步骤是和不得相互的后台服务完结步骤是大同小异的,区别在于运转的措施和获得Service的代理对象。

创造服务类和平日Service分歧在于这里重临三个代理对象,再次回到给前台实行获取,即前台可以获取该代理对象进行后台服务的章程

public class BackService extends Service { @Override public void onCreate() { super.onCreate(); } @Nullable @Override public IBinder onBind(Intent intent) { //返回MyBinder对象 return new MyBinder(); } //需要返回给前台的Binder类 class MyBinder extends Binder { public void showTip(){ System.out.println("我是来此服务的提示"); } } @Override public void onDestroy() { super.onDestroy(); }}

前台调用透过以下方式绑定服务:

bindService(mIntent,con,BIND_AUTO_CREATE);

里面第2个参数:

private ServiceConnection con = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { BackService.MyBinder myBinder = (BackService.MyBinder) service; myBinder.showTip(); } @Override public void onServiceDisconnected(ComponentName name) { } };

当建构绑定后,on瑟维斯Connected中的service就是Service类中onBind的重回值。如此便足以调用后台服务类的章程,达成互动。

当调用unbindService()截至服务,同期要在onDestory()方法中盘活清监护人业。

在意:通过bindService运营的Service的生命周期依附于运维它的Context。由此当前台调用bindService的Context销毁后,那么服务会活动结束。

将地点三种运转形式组成起来正是混合性交互的后台服务了,即能够单独运营后台服务,也足以运作后台服务中提供的办法,其完整的生命周期是:onCreate->onStartCommand->onBind->onUnBind->onDestroy

所谓前台服务只不是透过自然的不二等秘书诀将服务所在的经过等第升高了。前台服务会直接有叁个正在运行的Logo在系统的情况栏突显,极度周围于通告的效用。

出于后台服务先行级相对相当低,当系统出现内部存款和储蓄器不足的情景下,它就有希望会被回收掉,所从前台服务正是来弥补这一个毛病的,它能够一贯维持运转意况而不被系统回收。

成立服务类前台服务成立很简短,其实就在瑟维斯的底子上创办三个Notification,然后选择Service的startForeground()方法就能够运营为前台服务。

public class ForeService extends Service{ @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); beginForeService(); } private void beginForeService() { //创建通知 Notification.Builder mBuilder = new Notification.Builder .setSmallIcon(R.mipmap.ic_launcher) .setContentText("2017-2-27") .setContentText("您有一条未读短信..."); //创建点跳转的Intent(这个跳转是跳转到通知详情页) Intent intent = new Intent(this,NotificationShow.class); //创建通知详情页的栈 TaskStackBuilder stackBulider = TaskStackBuilder.create; //为其添加父栈 当从通知详情页回退时,将退到添加的父栈中 stackBulider.addParentStack(NotificationShow.class); PendingIntent pendingIntent = stackBulider.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT); //设置跳转Intent到通知中 mBuilder.setContentIntent(pendingIntent); //获取通知服务 NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //构建通知 Notification notification = mBuilder.build(); //显示通知 nm.notify(0,notification); //启动前台服务 startForeground(0,notification); }}

开发银行前台服务

startService(new Intent(this, ForeService.class));

至于TaskStackBuilder 这一段,只怕不是看的很领会,上面详细介绍。

三、Service生命周期

图片 6

OnCreate()系统在service第贰次创制时实行此情势,来实施只运转一回的起先化职业。要是service已经运营,那几个方法不会被调用。
<br />
onStartCommand()老是客商端调用startService()方法运行该Service都会回调该方法(往往调用)。一旦这一个法子实践,service就开动况且在后台短时间运营。通过调用stopSelf()或stopService()来终止服务。
<br />

OnBind()当组件调用bindService()想要绑定到service时(举例想要实行进度间通讯)系统调用此方法(一回调用,一旦绑定后,后一次再调用bindService()不会回调该形式)。在您的完成中,你必需提供二个回到三个IBinder来以使客商端能够利用它与service通信,你必得三番五次完成那一个点子,可是如果您不允许绑定,那么你应重回null。
<br />
OnUnbind()近年来组件调用unbindService(),想要解除与service的绑定期系统调用此办法(一遍调用,一旦解除绑定后,后一次再调用unbindService()会抛出非常)。
<br />
OnDestory()系统在service不再被应用并要销毁时调用此措施(二遍调用).service应在此格局中自由财富,比方线程,已登记的侦听器,接收器等等.那是service收到的末尾三个调用。
<br />


彩蛋/(●’◡’●)

下边珍视关怀下onStartCommand(Intent intent, int flags, int
startId)
方法。
内部参数flags私下认可处境下是0,对应的常量名称为START_STICKY_COMPATIBILITY。startId是一个唯一的整型,用于表示此次Client实践startService(…)的伸手乞求标志,在接二连三startService(…)的图景下,呈现0,1,2….递增。别的,此函数具备三个int型的再次来到值,具体的可选值及意义如下:
START_NOT_STICKY:当Service因为内部存款和储蓄器不足而被系统kill后,接下去年今年后的有些时刻内,尽管系统内部存款和储蓄器充裕可用,系统也不会尝试再次创造此Service。除非主次中Client分明再次调用startService(…)运转此Service。
START_STICKY:当瑟维斯因为内部存款和储蓄器不足而被系统kill后,接下去现在的有些时间内,当系统内部存款和储蓄器丰裕可用的情事下,系统将会尝试再次创立此Service,一旦创设成功后将回调onStartCommand(…)方法,但当中的Intent将是null,pendingintent除了那些之外。
START_REDELIVER_INTENT:与START_STICKY唯一不一致的是,回调onStartCommand(…)方法时,在那之中的Intent将是非空,将是最后一遍调用startService(…)中的intent。
START_STICKY_COMPATIBILITY:compatibility version of {@link
#START_STICKY} that does not guarantee that {@link #onStartCommand}
will be called again after being
killed。此值一般不会利用,所以注意近来三种景况就好。
<br />
如上的陈述中,”当Service因为内部存储器不足而被系统kill后“一定要这一个潜心,因为此函数的再次回到值设定只是针对此种情状才有含义的,换言之,当认为的kill掉瑟维斯进度,此函数再次回到值无论怎么设定,接下去年今年后的某些时间内,就算系统内部存款和储蓄器充分可用,Service也不会重启。
<br />
华为手机对准这里做了改换:
别的,要求留心的是,红米手提式无线电话机对准这里做了一定的修改。在“自运行管理”中有四个自运转应用列表,私下认可情形下,独有少使用(如微信、QQ、YY、360等)默许是足以自运维的,其余应用默许都以不准的。顾客可以手动增加自运行应用,加多后的采取中一旦Started
ServiceonStartCommand(…)回调重临值是START_STICKY或START_REDELIVER_INTENT,当客商在OPPO手提式无线电话机上长按Home键甘休App后,接下去现在的某部时刻内,当系统内部存款和储蓄器丰裕可用时,Service还是能够遵从上述规定重启。当然,要是顾客在
设置 >> 应用 >>
强制kill掉App进度,此时Service是不会重启的。
注:以上实验结论基于Nokia2S亲测。


上面介绍两种分裂情况下Service的生命周期情状。

  • 1-startService-stopService)1.startService / stopService
    生命周期顺序:onCreate->onStartCommand->onDestroy
    若果二个Service被有个别Activity 调用
    Context.startService方法运营,那么不论是是或不是有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行,直到被调用stopService,或本身的stopSelf方法。当然假若系统财富不足,android系统也或然终结劳动,还大概有一种方法能够关闭服务,在安装中,通过行使->找到自个儿使用->甘休。
    注意点:
    ①第贰次 startService 会触发 onCreate 和
    onStartCommand,今后在劳动运作进度中,每一次 startService 都只会触发
    onStartCommand
    ②无论 startService 多少次,stopService 三遍就能够告一段落服务
  • 2-bindService-unbindService)2.bindService / unbindService
    生命周期顺序:onCreate->onBind->onUnBind->onDestroy
    要是二个瑟维斯在某些Activity中被调用bindService方法运营,不论bindService被调用三遍,Service的onCreate方法只会实行叁遍,同一时候onStartCommand方法始终不会调用。
    当建构连接后,Service会一贯运维,除非调用unbindService来接触绑定、断开连接或调用该Service的Context不设有了(如Activity被Finish——即透过bindService运转的Service的生命周期依赖于运维它的Context),系统在此刻会自动结束该Service。
    注意点:
    首先次 bind瑟维斯 会触发 onCreate 和
    onBind,以往在劳动运作进度中,每便 bindService 都不会接触任何回调
  • 3.混合型(上面二种办法的交互)
    当三个Service在被运维(startService)的同一时候又被绑定(bindService),该Service将会一直在后台运转,并且不管调用一次,onCreate方法始终只会调用一遍,onStartCommand的调用次数与startService调用的次数一致(使用bindService方法不会调用onStartCommand)。同时,调用unBindService将不会告一段落Service,必须调用stopService或瑟维斯自己的stopSelf来终止服务。
    在什么样动静下选用 startService 或 bindService 或 同不经常间使用startService和 bindService?
    ①假若你只是想要运营一个后台服务长期举办某项职责那么使用 startService便能够了。
    ②若是您想要与正在运行的 Service 获得联系,那么有三种办法,一种是选拔broadcast ,其它是使用 bindService,前面一个的弱项是一旦交换相比较频仍,轻易形成品质上的主题素材,并且布罗兹castReceiver
    本人施行代码的日子是十分的短的(可能实施到五成,后面的代码便不会试行),而后人则并没有这么些主题素材,由此大家一定选拔使用
    bindService(这一年你便同时在行使 startService 和 bindService了,那在 Activity 中更新 Service 的一些运长势况是一定实惠的)。
    ③比如你的劳动只是大庭广众三个长距离接口,供连接上的客服端(android 的
    Service是C/S架构)远程调用实施格局。这一年你能够不让服务一发端就运行,而只用
    bindService ,那样在率先次 bindService的时候才会成立服务的实例运营它,这会省去比很多系统能源,特别是如若你的劳动是Remote
    Service,那么该意义会越通晓(当然在 Service创制的时候会花去确定期期,你应该注意到那点)。这一部分重大行使是AIDL,能够看那篇小说。

<br />

注:

TaskStackBuilder在Notification通告栏中的使用

先是是用一般的PendingIntent来开展跳转

mBuilder = new NotificationCompat.Builder.setContent .setSmallIcon(R.drawable.icon).setTicker .setWhen(System.currentTimeMillis .setOngoing .setAutoCancel; Intent intent = new Intent(this, NotificationShow.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); mBuilder.setContentIntent(pendingIntent); 

此处是直接用PendingIntent来跳转到NotificationShow。

在运转效果上来看,首头阵送了一条Notification到布告栏上,然后那时,退出程序,即MainActivity已经不设有了,回到home主菜单,看到Notification依然存在,当然,大家还不曾点击也许cancel它,今后去点击Notification,跳转到NotificationShow分界面,然后大家按下Back键,开采直接重回home菜单了。未来大大多android应用都以在布告栏中只要有Notification通告的话,点击它,然后会直接跳转到对应的应用程序的某部分界面,那时假使回落,即按下Back键,会再次来到到该应用程序的主分界面,并非系统的home菜单。所以用地点这种PendingIntent的做法达不到指标。这里大家采纳TaskStackBuilder来做。

mBuilder = new NotificationCompat.Builder.setContent .setSmallIcon(R.drawable.icon).setTicker .setWhen(System.currentTimeMillis .setOngoing .setAutoCancel; Intent intent = new Intent(this, NotificationShow.class); TaskStackBuilder stackBuilder = TaskStackBuilder.create; stackBuilder.addParentStack(NotificationShow.class); stackBuilder.addNextIntent; PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); // PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, // intent, PendingIntent.FLAG_UPDATE_CURRENT); mBuilder.setContentIntent(pendingIntent);

来得用TaskStackBuilder.create创设三个stackBuilder实例,接下去addParentStack();

有关那个点子,大家查一下官方API文书档案:

Add the activity parent chain as specified by the parentActivityName
attribute of the activity (or activity-alias) element in the
application’s manifest to the task stack builder

那句话意思是:为跳转后的activity增多三个父activity,在activity中的manifest中增多parentActivityName就可以。

那正是说我们就在manifest文件中增加那个性情

<activity android:name="com.lvr.service.NotificationShow" android:parentActivityName=".MainActivity" > </activity>

这里我让它的parentActivity为MainActivity,相当于说在NotificationShow这一个分界面点击回退时,会跳转到MainActivity那个分界面,并不是像上面一样直接重返了home菜单。

专心:通过
stopForeground()方法能够收回布告,将在前台服务降为后台服务。此时劳动照旧未有停下。通过stopService()能够把前台服务甘休。

如上是关于Service的开始和结果。

四、Service的两种标准使用实例

  • 1.不得相互的后台服务
    不可相互的后台服务就是普通的Service,通过start瑟维斯()格局展开。Service的生命周期很简短,分别为onCreate、onStartCommand、onDestroy那多少个。
    创办服务类:

public class BackService extends Service {
    private Thread mThread;
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("onBind");
        return null;
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //执行耗时操作
        mThread = new Thread() {
            @Override
            public void run() {
                try {
                    while (true) {
                        //等待停止线程
                        if (this.isInterrupted()) {
                            throw new InterruptedException();
                        }
                        //耗时操作。
                        System.out.println("执行耗时操作");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        mThread.start();
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        //停止线程
        mThread.interrupt();
    }
}

布置服务:

<service android:name=".BackService"></service>

若是想安顿成远程服务,加如下代码:

android:process="remote"

布署好Service类,只要求在前台,调用startService()方法,就能够运维耗费时间操作。
注意:
①不运营在二个独门的长河中,它一律施行在UI线程中,因而,在Service中创设了子线程来实现耗费时间操作。
②当Service关闭后,如若在onDestory()方法中不休息线程,你会发觉大家的子线程进行的耗费时间操作是平素留存的,此时闭馆该子线程的格局供给直接关闭该应用程序。由此,在onDestory()方法中要举行需求的清理职业。

  • 2.可互相的后台服务
    可相互的后台服务是指前台页面能够调用后台服务的法子,通过bindService()格局展开。Service的生命周期很简短,分别为onCreate、onBind、onUnBind、onDestroy那八个。可相互的后台服务达成步骤是和不得相互的后台服务完毕步骤是同一的,不一样在于运营的章程和获取Service的代理对象。
    制造服务类和一般瑟维斯分歧在于这里重返二个代理对象,再次回到给前台进行获取,即前台能够博得该代理对象施行后台服务的秘技

public class BackService extends Service {

@Override
public void onCreate() {
super.onCreate();

}

@Nullable
@Override
public IBinder onBind(Intent intent) {
//返回MyBinder对象
return new MyBinder();
}
//需要返回给前台的Binder类
class MyBinder extends Binder {
public void showTip(){
System.out.println("我是来此服务的提示");
}
}
@Override
public void onDestroy() {
super.onDestroy();

}
}

前台调用通过以下方式绑定服务:

bindService(mIntent,con,BIND_AUTO_CREATE);

其间第三个参数:

private ServiceConnection con = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
BackService.MyBinder myBinder = (BackService.MyBinder) service;
myBinder.showTip();
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

当创设绑定后,on瑟维斯Connected中的service正是瑟维斯类中onBind的重返值。如此便能够调用后台服务类的点子,完结互动。
当调用unbindService()甘休服务,同不时间要在onDestory()方法中抓好清管事人业。
专一:通过bindService运维的Service的生命周期依靠于运营它的Context。由此当前台调用bindService的Context销毁后,那么服务会自行结束。

  • 3.混合型后台服务
    将地方三种运维格局组成起来正是混合性交互的后台服务了,即能够单独运维后台服务,也足以运作后台服务中提供的办法,其全部的生命周期是:onCreate->onStartCommand->onBind->onUnBind->onDestroy
  • 4.前台服务

所谓前台服务只不是经过自然的形式将服务所在的进度等级升高了。前台服务会一直有一个正在运转的Logo在系统的情况栏显示,特别类似于通告的作用。
出于后台服务先行级相对非常低,当系统出现内部存储器不足的动静下,它就有望会被回收掉,所之前台服务就是来弥补那么些毛病的,它能够直接维系运转情况而不被系统回收。
开创服务类前台服务制造一点也不细略,其实就在Service的基本功上创建三个Notification,然后利用Service的startForeground()方法就可以运行为前台服务。

public class ForeService extends Service{
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
super.onCreate();
beginForeService();
}

private void beginForeService() {
//创建通知
Notification.Builder mBuilder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("2017-2-27")
.setContentText("您有一条未读短信...");
//创建点跳转的Intent(这个跳转是跳转到通知详情页)
Intent intent = new Intent(this,NotificationShow.class);
//创建通知详情页的栈
TaskStackBuilder stackBulider = TaskStackBuilder.create(this);
//为其添加父栈 当从通知详情页回退时,将退到添加的父栈中
stackBulider.addParentStack(NotificationShow.class);
PendingIntent pendingIntent = stackBulider.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
//设置跳转Intent到通知中
mBuilder.setContentIntent(pendingIntent);
//获取通知服务
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//构建通知
Notification notification = mBuilder.build();
//显示通知
nm.notify(0,notification);
//启动前台服务
startForeground(0,notification);
}
}

运维前台服务

startService(new Intent(this, ForeService.class));

有关TaskStackBuilder 这一段,大概不是看的很明亮,上边详细介绍。
TaskStackBuilder在Notification通告栏中的使用
率先是用一般的PendingIntent来开展跳转

mBuilder = new NotificationCompat.Builder(this).setContent(view) 
.setSmallIcon(R.drawable.icon).setTicker("新资讯")
.setWhen(System.currentTimeMillis())
.setOngoing(false)
.setAutoCancel(true);
Intent intent = new Intent(this, NotificationShow.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);

此处是直接用PendingIntent来跳转到NotificationShow。
在运作效果上来看,首先发送了一条Notification到文告栏上,然后那时,退出程序,即MainActivity已经荒诞不经了,回到home主菜单,看到Notification还是存在,当然,大家还未有一点点击或许cancel它,以后去点击Notification,跳转到NotificationShow分界面,然后我们按下Back键,发掘直接再次来到home菜单了。未来大相当多android应用都以在布告栏中只要有Notification布告的话,点击它,然后会直接跳转到对应的应用程序的某部分界面,那时假设回降,即按下Back键,会回去到该应用程序的主分界面,并不是系统的home菜单。所以用地点这种PendingIntent的做法达不到指标。这里大家选用TaskStackBuilder来做。

mBuilder = new NotificationCompat.Builder(this).setContent(view) 
.setSmallIcon(R.drawable.icon).setTicker("新资讯")
.setWhen(System.currentTimeMillis())
.setOngoing(false)
.setAutoCancel(true);
Intent intent = new Intent(this, NotificationShow.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(NotificationShow.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
// PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, 
// intent, PendingIntent.FLAG_UPDATE_CURRENT); 
mBuilder.setContentIntent(pendingIntent);

来得用TaskStackBuilder.create(this)制造一个stackBuilder实例,接下去addParentStack();
至于那些法子,我们查一下合法API文书档案:

Add the activity parent chain as specified by the parentActivityName
attribute of the activity (or activity-alias) element in the
application’s manifest to the task stack builder

那句话意思是:为跳转后的activity加多一个父activity,在activity中的manifest中增加parentActivityName就能够。
那么大家就在manifest文件中丰硕那些个性

<activity 
android:name="com.lvr.service.NotificationShow" 
android:parentActivityName=".MainActivity" >
</activity>

此处小编让它的parentActivity为MainActivity,也正是说在NotificationShow那么些分界面点击回落时,会跳转到MainActivity那些分界面,实际不是像上边同样一直回到了home菜单。
<br />
小心:通过
stopForeground()方法能够撤除通告,将要前台服务降为后台服务。此时劳动依旧未有甘休。通过stopService()可以把前台服务甘休。

  • 当贰个Service被甘休(1、调用stopService();2、调用stopSelf();3、不再有绑定的连接(未有被运转))时,onDestroy()方法将会被调用,在此间您应有做一些解除专门的学问,如截止在Service中创制并运维的线程。
  • 在调用 bindService绑定到Service的时候,你就应该保管在某处调用unbindService解除绑定(即便 Activity 被 finish()
    的时候绑定会自行清除,何况Service会自动终止)。
  • 还要接纳 startService() 与 bind瑟维斯()
    要注意到,Service的终止,须求unbindService()与stopService()同有的时候间调用,才具甘休Service,不管
    start瑟维斯() 与 bindService() 的调用顺序,借使先调用
    unbindService() 此时劳动不会自行终止,再调用 stopService()
    之后服务才会停下,假如先调用 stopService()
    此时服务也不会告一段落,而再调用 unbindService() 只怕 此前调用
    bindService() 的 Context 不设有了(如Activity 被 finish()
    的时候)之后服务才会自行停止;
  • 当在打转手提式有线电话机荧屏的时候,当手机荧屏在“横”“竖”转换时,此时一经您的
    Activity 倘若会自行旋转的话,旋转其实是 Activity
    的再一次创立,由此旋转此前的运用 bindService创设的连年便会断开(Context
    一纸空文了),对应服务的生命周期与上述同样。
  • 一般是重写onStartCommand方法,。

startService()示例:

public class MyService extends Service {  

    private static final String TAG = "MyService";  

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

    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        Log.i(TAG, "onStartCommand called.");  
        return super.onStartCommand(intent, flags, startId);  
    }  

    @Override  
    public void onStart(Intent intent, int startId) {  
        super.onStart(intent, startId);  
        Log.i(TAG, "onStart called.");  
    }  

    @Override  
    public IBinder onBind(Intent intent) {  
        Log.i(TAG, "onBind called.");  
        return null;  
    }  

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

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

每个Service必须在AndroidManifest.xml中 通过<service>来注册。

<service android:name=".service.MyService" ></service>  

上述代码表示五个在行使包service目录下的承继Service的Myservice服务。

点击事件:

/** 
 * 启动服务按钮方法 
 * @param view 
 */  
public void start(View view) {  
    Intent intent = new Intent(this, MyService.class);  
    startService(intent);  
}  

/** 
 * 停止服务按钮方法 
 * @param view 
 */  
public void stop(View view) {  
    Intent intent = new Intent(this, MyService.class);  
    stopService(intent);  
}  

bindService()示例:
因为前边服务中的onBind方法重返值为null,由此,要想达成绑定操作,必得回到贰个贯彻了IBinder接口类型的实例,该接口描述了与长途对象开展交互的架空合同,有了它我们才具与劳务扩充相互。

@Override  
public IBinder onBind(Intent intent) {  
    Log.i(TAG, "onBind called.");  
    return new Binder() {};  
}  

回到了三个Binder的实例,而以此Binder恰恰是完成了IBinder接口,那样就足以达成绑定服务的操作了。

public class MainActivity extends AppCompatActivity{  

    private static final String TAG = "MainActivity";  
    private boolean binded;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
    }  

    private ServiceConnection conn = new ServiceConnection() {  

        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            binded = true;  
            Log.i(TAG, "onServiceConnected called.");  
        }  

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

    /** 
     * 绑定服务 
     * @param view 
     */  
    public void bind(View view) {  
        Intent intent = new Intent(this, MyService.class);  
        bindService(intent, conn, Context.BIND_AUTO_CREATE);  
    }  

    /** 
     * 解除绑定 
     * @param view 
     */  
    public void unbind(View view) {  
        unbindService();    
    }  

    //在MainActivity销毁之前如果没有进行解除绑定会导致后台出现异常信息
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        unbindService();  
    } 

    /** 
     * 解除服务绑定 
     */  
    private void unbindService() {  
        if (binded) {  
            unbindService(conn);  
            binded = false;  
        }  
    } 
}  

在利用bindService()绑定服务时,大家要求一个ServiceConnection代表与服务的连接,使用bindService()运维服务后调用者和劳动绑定到了伙同,当调用者被销毁,服务也登时结终止。

  • 创造前台服务
    前台服务的亮点:Service暗中认可是运作在后台的,因此,它的优先级相对十分低,当系统出现内存不足的意况时,它就有非常的大希望被回收掉。要是将Service运转在前台,Service就足以一贯维系运长势况,而不会被系统因内部存款和储蓄器不足回收。它能够在布告栏显示新闻,当服务被结束的时候,文告栏的
    Notification
    也会消退,这样对于客户有自然的照看成效。常见的如更新天气消息,音乐播放服务。设置服务为前台服务,使用的措施是
    startForeground()与 stopForeground()

public class WeatherService extends Service{
    private static final int NOTIFY_ID = 123;

    @Override
    public void onCreate(){
        super.onCreate();
        showNotification();
    }

    //在通知栏显示天气信息
    private void showNotification(){
        NotificationCompat.Builder mBuilder = 
            new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.weather)
                .setContentTitle(getText(R.string.the_day))
                .setContentText(getText(R.string.weather));
        //创建通知被点击时触发的Intent
        Intent resultIntent = new Intent(this, MainActivity.class);

        //创建任务栈Builder
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MainActivity.class);
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent = 
            stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(resultPendingIntent);

        NotificationManager mNotification = 
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        //构建通知
        final Notification notification = mBuilder.builder();
        //显示通知
        mNotification.notify(NOTIFY_ID, notification);
        //启动前台服务
        startForeground(NOTIFY_ID, notification);
    }
}

使用 startForeground(),如果NOTIFY_ID为 0
,那么notification将不会议及展览示。
另:
使用Notification通告栏的时候,用TaskStackBuilder来获取PendingIntent管理点击跳转到别的Activity。使用TaskStackBuilder来完结在通告栏中假使有Notification照会的话,点击它,然后会一直跳转到对应的应用程序的某些分界面,那时要是按下Back键,会回到到该应用程序的主分界面,实际不是系统的主分界面。addParentStack()是用来增添三个Activity,与那几个Activity的AndroidManifest.xml文件中的parentActivityName的特性相关联。

<activity  
    android:name="....."  
    android:parentActivityName=".MainActivity" >  
</activity>  

  • 进度内与服务通讯
    进度内与劳务通讯实际上正是经过bind瑟维斯的主意与劳动绑定,获取到通讯中介Binder实例,然后经过调用那个实例的法门,完结对劳务的种种操作。

public class MyService extends Service {  

    private static final String TAG = "MyService";  

    @Override  
    public IBinder onBind(Intent intent) {  
        Log.i(TAG, "onBind called.");  
        return new MyBinder();  
    }  

    /** 
     * 绑定对象 
     * @author user 
     * 
     */  
    public class MyBinder extends Binder {  

        /** 
         * 问候 
         * @param name 
         */  
        public void greet(String name) {  
            Log.i(TAG, "hello, " + name);  
        }  
    }  
}  

我们创造了二个MyBinder的内部类,定义了三个greet方法,在onBind方法中就将这些MyBinder的实例再次来到,只要调用者获取到这些实例,就能够像拿着游戏手柄一样对劳务拓宽操作。

public class MainActivity extends AppCompatActivity{  

    /** 
     * 绑定对象实例 
     */  
    private MyService.MyBinder binder;  
    private boolean binded;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
    }  

    private ServiceConnection conn = new ServiceConnection() {  

        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            binder = (MyService.MyBinder) service;  //获取其实例  
            binder.greet("coder");                  //调用其方法  
        }  

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

    /** 
     * 绑定服务 
     * @param view 
     */  
    public void bind(View view) {  
        Intent intent = new Intent(this, MyService.class);  
        bindService(intent, conn, Context.BIND_AUTO_CREATE);  
    }  

     /** 
     * 解除绑定 
     * @param view 
     */  
    public void unbind(View view) {  
        unbindService();    
    }  

    //在MainActivity销毁之前如果没有进行解除绑定会导致后台出现异常信息
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        unbindService();  
    } 

    /** 
     * 解除服务绑定 
     */  
    private void unbindService() {  
        if (binded) {  
            unbindService(conn);  
            binded = false;  
        }  
    } 
}

在绑定服务成功时将IBinder类型的service参数强转为MyService.MyBinder类型,获取绑定中介实例,然后调用其greet方法。绑定服务后,去操作binder对象,只怕它还为null,这就便于招惹空指针十分,正确的做法是把那么些操作放到绑定成功以往。


发表评论

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

网站地图xml地图