标签:
Android的服务:
1:已启动方式:
startService()和bindService();
startService:启动后,如果Activity关闭了,服务依然运行,除非stopService;
bindService:创建开启服务器,但是在程序关闭的时候,会自动关闭服务;
通过ServiceConnectionjava接口获取service的IBinder接口;
2:控制服务(绑定服务);
(1)但是上述两个方式都是通过Intent创建启动服务的,没有通过new,所以没有直接控制service的对象;
上述可以通过bindService获取IBinder接口后,控制service,但是这也比较麻烦,这样需要写一个新的IBinder接口,实现很多函数控制service,然后外部相关类通过这个接口间接的控制服务;
(2)我们可以理解一个service就是一个单例模式的设计,不论通过startService还是通过 bindService创建启动函数,最终都都只有一个内存对象创建,所以这里我们可以改变思路,直接获取service的对象;
就是通过一个静态变量,和一个静态函数;在构造函数中直接获取this对象;
示例:
class MyBinder extends Binder { } public class MyService extends Service { public MyService() { m_serviceObj = this; Log.w("", "MyService: 构造函数"); } private static MyService m_serviceObj = null; public static MyService GetInstance() { return m_serviceObj; } public void set_dbg_text( String str ) { Log.w("", "set_dbg_text"); Log.w("", "set_dbg_text: " + str ); } int m_nCount = 0; @Override public IBinder onBind(Intent intent) { Log.w("", "MyService-onBind"); // return null; m_serviceObj = this; return new MyBinder(); } }
(3): 上述可以在同一个进程总中,也就事同一个工程中,直接简单的应用;
不同进程间访问service,可以通过AIDL;
AIDL文件语法和java接口语法很像,build工程后,会根据aidl文件生成相应的Java接口的java文件,这个接口文件可以理解为IBinder接口的实现,所以可以在服务中知己诶应用,然后别的应用程序可以根据AIDL文件(这里就C/C++的头文件)和service绑定了;
在AndroidStudio中还是比较好实现的;
(4):如果进程间的简单通信,也可以通过 广播消息 Intent 的 Bundle参数,这样的方式进行;
当然进程间通信的方式很多;
转几篇文章:
一、首先,让我们确认下什么是service?
service就是android系统中的服务,它有这么几个特点:它无法与用户直接进行交互、它必须由用户或者其他程序显式的启动、它的优先级比较高,它比处于前台的应用优先级低,但是比后台的其他应用优先级高,这就决定了当系统因为缺少内存而销毁某些没被利用的资源时,它被销毁的概率很小哦。
二、那么,什么时候,我们需要使用service呢?
我们知道,service是运行在后台的应用,对于用户来说失去了被关注的焦点。这就跟我们打开了音乐播放之后,便想去看看图片,这时候我们还不想音乐停止,这里就会用到service;又例如,我们打开了一个下载链接之后,我们肯定不想瞪着眼睛等他下载完再去做别的事情,对吧?这时候如果我们想手机一边在后台下载,一边可以让我去看看新闻啥的,就要用到service。
三、service分类:
一般我们认为service分为两类,本地service和远程service。
本地service顾名思义,那就是和当前应用在同一个进程中的service,彼此之间拥有共同的内存区域,所以对于某些数据的共享特别的方便和简单;
远程service:主要牵扯到不同进程间的service访问。因为android的系统安全的原因导致了我们在不同的进程间无法使用一般的方式共享数据。在这里android为我们提供了一个AIDL工具。(android interface description language)android接口描述语言。在后边我们将会对其进行详细的介绍。
四、service生命周期:
和Activity相比,service的生命周期已经简单的不能再简单了,只有onCreate()->onStart()->onDestroy()三个方法。
Activity中和service有关的方法:
startService(Intent intent):启动一个service
stopService(Intent intent) :停止一个service
如果我们想使用service中的一些数据或者访问其中的一些方法,那么我们就要通过下面的方法:
public boolean bindService(Intent intent, ServiceConnection conn, int flags) ;
public void unbindService(ServiceConnection conn);
intent是跳转到service的intent,如 Intent intent = new Intent(); intent.setClass(this,MyService.class);
conn则是一个代表与service连接状态的类,当我们连接service成功或失败时,会主动触发其内部的onServiceConnected或onServiceDisconnected方法。如果我们想要访问service中的数据,可以在onServiceConnected()方法中进行实现,
使用service的步骤:
第一步:我们要继承service类,实现自己的service。
如果想要访问service中的某些值,我们通常会提供一个继承了Binder的内部类,通过onBund()方法返回给service请求。这里实际上巧妙的利用了内部类能够访问外部类属性的特点。
第二步:在androidManifest.xml中进行注册,如:
<!-- service配置开始 -->
<service android:name="MyService"></service>
<!-- service配置结束-->
第三步:在activity中进行启动、绑定、解绑或者停止service。
(很多书上说,service与用户是不能交互的,其实这话很不正确,我们完全可以通过activity与service进行交互!我认为,确切的说法应该是service与用户不能进行直接的交互)。
-----------------------------
一、bindService简介
bindService是绑定Service服务,执行service服务中的逻辑流程。
service通过Context.startService()方法开始,通过Context.stopService()方法停止;也可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己。只要调用一次stopService()方法便可以停止服务,无论之前它被调用了多少次的启动服务方法。
客户端建立一个与Service的连接,并使用此连接与Service进行通话,通过Context.bindService()方法来绑定服务,Context.unbindService()方法来关闭服务。多个客户端可以绑定同一个服务,如果Service还未被启动,bindService()方法可以启动服务。
上面startService()和bindService()两种模式是完全独立的。你可以绑定一个已经通过startService()方法启动的服务。例如:一个后台播放音乐服务可以通过startService(intend)对象来播放音乐。可能用户在播放过程中要执行一些操作比如获取歌曲的一些信息,此时activity可以通过调用bindServices()方法与Service建立连接。这种情况下,stopServices()方法实际上不会停止服务,直到最后一次绑定关闭。
如果没有程序停止它或者它自己停止,service将一直运行。在这种模式下,service开始于调用Context.startService() ,停止于Context.stopService(). service可以通过调用Android Service 生命周期() 或 Service.stopSelfResult()停止自己。不管调用多少次startService() ,只需要调用一次 stopService() 就可以停止service。
可以通过接口被外部程序调用。外部程序建立到service的连接,通过连接来操作service。建立连接调开始于Context.bindService(), 结束于Context.unbindService(). 多个客户端可以绑定到同一个service,如果service没有启动, bindService() 可以选择启动它。
这2种模式不是完全分离的。你可以可以绑定到一个通过startService()启动的服务。如一个intent想要播放音乐,通过startService() 方法启动后台播放音乐的service。然后,也许用户想要操作播放器或者获取当前正在播放的乐曲的信息,一个activity就会通过bindService()建立一个到此service的连接. 这种情况下 stopService() 在全部的连接关闭后才会真正停止service。
二、bindService启动流程
context.bindService() ——> onCreate() ——> onBind() ——> Service running ——> onUnbind() ——> onDestroy() ——> Service stop
onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。
所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。
在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
三、bindService生命周期
像一个activity那样,一个service有些可以用来改变状态的生命周期方法,但是比activity的方法少,service生命周期方法只有三个public
void onCreate()
void onStart(Intent intent)
void onDestroy()
通过实现这三个生命周期方法,你可以监听service的两个嵌套循环的生命周期:
1、整个生命周期
service的整个生命周期是在onCreate()和onDestroy()方法之间。和activity一样,在onCreate()方法里初始化,在onDestroy()方法里释放资源。例如,一个背景音乐播放服务可以在onCreate()方法里播放,在onDestroy()方法里停止。
2、活动的生命周期
service的活动生命周期是在onStart()之后,这个方法会处理通过startServices()方法传递来的Intent对象。音乐service可以通过开打intent对象来找到要播放的音乐,然后开始后台播放。注: service停止时没有相应的回调方法,即没有onStop()方法,只有onDestroy()销毁方法。
onCreate()方法和onDestroy()方法是针对所有的services,无论它们是否启动,通过Context.startService()和Context.bindService()方法都可以访问执行。然而,只有通过startService()方法启动service服务时才会调用onStart()方法。
如果一个service允许别人绑定,那么需要实现以下额外的方法:
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
onBind()回调方法会继续传递通过bindService()传递来的intent对象
onUnbind()会处理传递给unbindService()的intent对象。如果service允许绑定,onBind()会返回客户端与服务互相联系的通信句柄(实例)。
如果建立了一个新的客户端与服务的连接,onUnbind()方法可以请求调用onRebind()方法。
记住: 任何服务无论它怎样建立,默认客户端都可以连接,所以任何service都能够接收onBind()和onUnbind()方法
转:
Android里Service的bindService()和startService()混合使用深入分析
1.先讲讲怎么使用bindService()绑定服务
应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder
绑定是异步的.bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传
给bindService().ServiceConnection包含一个回调方法,系统调用这个方法来传递要返回的IBinder.
注:只有activities,services,和contentproviders可以绑定到一个service—你不能从一个broadcastreceiver绑定到service.
所以,从你的客户端绑定到一个service,你必须:
1实现ServiceConnection.
你的实现必须重写两个回调方法:
onServiceConnected()
系统调用这个来传送在service的onBind()中返回的IBinder.
OnServiceDisconnected()
Android系统在同service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了.当客户端解除绑定时,这个方法不会被调用.
2调用bindService(),传给它ServiceConnection的实现.
3当系统调用你的onServiceConnected()方法时,你就可以使用接口定义的方法们开始调用service了.
4要与service断开连接,调用unbindService().
当你的客户端被销毁,它将从service解除绑定,但是你必须总是在你完成与service的交互时或当你的activity暂停于是service在不被使用时可以关闭此两种情况下解
除绑定.(下面会讨论更多在适当的时候绑定和解除绑定的问题.
使用这个ServiceConnection,客户端可以绑定到一个service,通过把它传给bindService().例如:
Intentintent = new Intent(this, LocalService.class);
bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
第一个bindService()的参数是一个明确指定了要绑定的service的Intent.
第二个参数是ServiceConnection对象.
第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可.。
下面是一些关于绑定到service的重要事项:
你总是需要捕获DeadObjectException异常.它会在连接被打断时抛出.这是被远程方法抛出的唯一异常.
对象引用计数是跨进程的作用的.
你应该在客户端的生命期内使绑定和解除绑定配对进行,例如:
如果你需要在你的activity可见时与service交互,你应该在onStart()绑定并在onStop()中解除绑定.
如果你想让你的activity即使在它停止时也能接收回应,那么你可以在onCreate()中绑定并在onDestroy()中解除绑定.注意这意味着你的activity需要使用在自己整
个运行期间使用service(即使位于后台),所以如果service在另一个进程中,那么你增加了这个进程的负担而使它变得更容易被系统杀掉.
注:你一般不应该在你的activity的onResume()和onPause()中绑定和解除绑定到service,因为这些回调方法,出现在每个生命期变化中,并且你需要使发生在这
些变化中的处理最小化.还有,如果你应用中的多个activity绑定到同一个service,并且有一个变化发生在其中两个activity之间,service可能在当前activity解除绑
定(pause中)和下一个绑定前(rusume中)被销毁又重建.
当一个service的所有客户端都解除绑定,Android系统就销毁它(除非它是从onStartCommand()启动).如果你的service是一个纯boundservice,你不需管理它的生命
期—Android系统会为你管理它.。
然而,如果你选择了实现onStartCommand()回调方法,那么你必须明确地停止service,因为service现在被认为是"开始的".在此情况下,service会一直运行,直
到service使用stopSelf()停止它自己或另外的组件调用了stopService()停止了它,不管是否有客户端绑定了它.
另外,如果你的service已经启动并且接受绑定,那么当系统调用你的onUnbind()方法,你可以选择返回true表示你想在客户端下一次绑定到service时接受一个
对onRebind()的调用(而不是一个对onBind()的调用).onRebind()返回void,但是客户端依然会在它的onServiceConnected()回调中接收到IBinder.下图演示了这种生命其的
逻辑:
3。bindService和startService混合使用时
1.如果先bindService,再startService:
在bind的Activity退出的时候,Service会执行unBind方法而不执行onDestory方法,因为有startService方法调用过,所以Activity与Service解除绑定后会有一个与调用者没有关连的Service存在
2.如果先bindService,再startService,再调用Context.stopService
Service的onDestory方法不会立刻执行,因为有一个与Service绑定的Activity,但是在Activity退出的时候,会执行onDestory,如果要立刻执行stopService,就得先解除绑定
---------------------------
把上面的"如果先bindService,再startService"换成"如果先startService,再bindService",结果是一样的
问题:
如果在一个Activity的onCreate方法中,
先
bindService(serviceIntent, conn, Context.BIND_AUTO_CREATE);
再startService(serviceIntent);
退出这个Activity时,会执行onUnBind
但是再次进入这个Activity的时候,为什么不执行onBind方法了?只有在这个Service销毁后(执行onDestory),再进这个Activity才会执行onBind,还有就是当有两个客户端时,在第一个客户端startServie启动服务再bindService绑定服务,这时跳到第二个客户端里(启动时会调用onBind()),再客户端startServie启动服务再bindService绑定服务,启动时不会调用用onBind()了(因为之前客户端已经启动后没有onDestory()销毁Service,所以再客户端第二次绑定服务时,只会返回IBinder对象给onServiceConnected()),而且要注意的是当,当第一个服务启动并绑定一个服务时,再跳去第二个服务端启动并绑定这个服务时,第二个服务端再解绑时,不会调用onUnbind(),只有回到第一个客户端时,解绑这是才会调用onUnbind(),顺序反过来结果是一样的。得出一个结论是:当一个服务没被onDestory()销毁之前,只有第一个启动它的客户端能调用它的onBind()和onUnbind()。
更多文章,可以自行搜索;
标签:
原文地址:http://blog.csdn.net/chinabinlang/article/details/51726902