Service--服务
参考Android 8.0 源码
Service和Activity一样都是Context的子类,只不过Service没有UI界面,是在后台运行的组件。
服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序 ,服务仍然能够保持正常运行。
服务并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程(除非我们在AndroidManifest.xml清单文件中为Service设置进程)。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。
服务并不会自动开启线程,所有的代码都是默认运行在主线程中的。也就是说,如果我们要做耗时操作,需要在服务的内部手动创建子线程,来实现具体的业务逻辑,否则就有可能出现主线程被阻塞住的情况。
服务的种类
按运行地点分类
类别 | 区别 | 优点 | 缺点 | 应用 |
---|---|---|---|---|
本地服务(Local Service) | 该服务依附在主进程上 | 服务依附在主进程上而不是福利的进程,这样在一定程度上节约了资源,另外,Local Service因为是在同一进程,因此不需要IPC,也不需要AIDL。相比bindService()方法会方便很多 | 主进程被kill掉以后,服务就会终止 | 如:音乐播放器播放等不需要常驻的服务 |
远程服务(Remote Service) | 该服务是独立的进程 | 服务为独立的进程,对应进程名格式为所在包名加上在AndroidManifest.xml文件中指定的android:process属性的值。由于是独立进程,因此在Activity所在进程被kill掉以后,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务,具有较高的灵活性 | 该服务是独立的进程,会占用一定的资源,并且使用AIDL进行IPC稍微麻烦一点 | 如:一些提供系统服务的Service,这种Service是常驻的 |
按运行类型分类
类别 | 区别 | 应用 |
---|---|---|
前台服务 | 会在通知栏显示onGoing的Notification | 当服务被终止的时候,通知一栏的Notification也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务 |
后台服务 | 默认的服务即为后台服务,即不会在通知一栏显示onGoing的Notification | 当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新、日期同步、邮件同步等服务 |
按使用方式分类
类别 | 区别 |
---|---|
startService()方法启动的服务 | 主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService()方法 |
bingService()方法启动的服务 | 使用该方法启动的服务要进行通信。停止服务使用unbindService()方法 |
同时使用startService()和bindService()启动的服务 | 停止服务需要同时使用stopService()和unbindService()方法 |
服务的基本用法
简单的Service实现,代码如下:
public class MyService extends Service {
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
首先需要知道调起Service的方式有两种,一种是使用startService()方法,另一种是使用bindService()方法,这两种方法分别会执行不同的生命周期。
使用startService()方法:
使用这个方法的Service生命周期是onCreate()-->onStartCommand()-->onDestroy();使用bindService()方法:
使用这个方法的Service生命周期是onCreate()-->onBind()-->onUnind()-->onDestroy();
onCreate()方法会在服务创建的时候调用,onStartCommand()方法会在每次服务启动的时候调用,onDestroy()方法会在服务销毁的时候调用。onCreate()方法是在服务第一次创建的时候调用的,而onStartCommand()方法则在每次启动服务的时候都会调用。
通常情况下,如果我们希望服务一旦启动就立刻去执行某个动作,就可以讲逻辑写在onStartCommand()方法里。而当服务销毁时,我们应该在onDestroy()方法中去回收那些不再使用的资源。另外,每一个服务都需要在AndroidManifest.xml文件中进行注册才能生效。
服务的生命周期
一旦在项目的任何位置调用了Context的startService()方法,相应的服务就会启动起来,并回调onStartCommand()方法。如果这个服务之前还没有创建过,onCreate()方法会先于onStartCommand()方法执行。如果这个服务已经起来了,就不会调用onCreate()方法。服务启动了之后会一直保持运行状态,直到stopService()或stopSelf()方法被调用。注意,虽然每调用一次startService()方法,onStartCommand()就会执行一次,但实际上每个服务都只会存在一个实例。所以不管你调用了多少次startService()方法,只需要调用一次stopService()或stopSelf()方法,服务就会停止下来了。
另外,还可以调用Context的bindService()来获取一个服务的持久连接,这时就会回调服务中的onBind()方法。类似地,如果这个服务之前还没有创建过,onCreate()方法会先于onBind()方法执行。如果这个服务已经起来了,就不会调用onCreate()方法。之后,调用方可以获取到onBind()方法里返回的IBinder对象的实例,这样就能自由和服务进行通信了。在我们的实现中,必须提供一个返回一个IBinde,让客户端能够使用IBinder与Service进行通讯。如果不需要绑定,只需要返回null就可以了。只要调用方可以获取到onBind()方法里返回的IBinder对象的实例,这样就能自由地和服务进行通信了。只要调用方和服务之间的连接没有断开,服务就会一直保持运行状态。当想要解除与Service的绑定时,调用unbindService()方法。一旦调用了unbindService()方法,下次再调用该方法就会抛出异常报错。
当调用了startService()方法后,又去调用stopService()方法,这时服务中的onDestroy()方法就会执行,表示服务已经销毁了。类似地,当调用了bindService()方法后,又去调用unbindService()方法,onDestroy()方法也会执行,这两种情况都很好理解。但是需要注意的是,我们完全有可能对一个服务既调用了startService()方法,又调用了bindService()方法的,根据Android系统的机制,一个服务只要被启动或者被绑定了之后,就会一直处于运行状态,必须要让以上两种条件同时不满足,服务才能被销毁。所以,这种情况下要同时调用stopService()和unbindService()方法,onDestroy()方法才会执行。
使用startService()与stopService()方法
生命周期顺序:onCreate()-->onStartCommand()-->onDestroy()
如果一个Service在某个Activity中被调用Context.startService()方法启动,那么不管是否有Activity使用bindService()方法绑定或者使用unbindService()方法解除绑定到该Service,那么该Service都会在后台运行,知道被调用stopService()或者调用自身的stopSelf()方法。当然,如果系统资源不足,Android系统也可能结束该服务。还有另外一种方法可以关闭该服务,就是在Android系统设置中,通过应用-->我们的应用-->停止该服务。
注意事项:
1 . 第一次startService()会触发onCreate()和onStartCommand()方法,以后在服务运行过程中,每次startService()都只会触发onStartCommand()方法;
2 . 不论调用startService()方法多少次,使用stopService()或者stopSelf()一次,就会停止该服务;
使用bindService()与unbindService()方法
生命周期顺序:onCreate()-->onBind()-->onUnbind()-->onDestroy()
如果一个Service在某个Activity中被调用bindService()方法启动,不论bindService()方法被调用几次,Service的onCreate()方法只会执行一次,同时onStartCommand()方法始终都不会被调用。
当建立连接以后,Service会一直运行,除非调用unbindService()方法来解除绑定断开链接。或者调用该Service的Context不存在了(如Activity被finish()掉了--即通过bindService()方法启动的Service的生命周期依附于启动它的Context),系统在这时会自动停止该Service。
注意事项:
1 . 第一次调用bindService()方法会触发onCreate()和onBind()方法,以后在服务运行过程中,每次调用bindService()方法都不会触发任何回调;
混合使用以上两种方法
当一个Service被使用startService()方法启动,同时又使用bindService()方法绑定,该Service会一直在后台运行,并且不管调用几次,onCreate()方法始终只会调用一次,onStartCommand()的调用次数与startService()调用的次数一致(使用bindService()方法不会调用onStartCommand()方法)。需要使用unbindService()和stopService()/stopSelf()方法才会停止服务。
服务的使用情况
1 . 如果你只是想要启动一个后台服务长期进行某项任务的执行,那么使用startService()方法即可;
2 . 如果你是想要与正在运行的Service取得联系进行通讯,那么有两种方法:一种是使用BroadcastRecevier,另外一种是使用bindService()方法。BroadcastRecevier本身执行代码的时间是很短的(也许执行到一半,后面的代码就不会执行了),使用bindService()方法则不会有这种情况,因此我们使用bindService()方法。在这个时候,
3 . 如果你的服务只是公开一个远程接口,使连接上的客户端远程调用执行方法,那么这个时候你可以不让服务一开始就运行,而只是使用bindService()方法,这样在第一次bindService()的时候才会创建服务的实例运行它,这回节约很多系统资源,特别是如果你的服务是Remote Service,那么该效果会越明显(当然,在Service创建的时候会花去一定时间)。
服务的更多技巧
前台服务
服务几乎都是在后台运行的,一直以来都是默默地做着辛苦的工作。但是服务的系统优先级还是比较低的,当系统出现内存不足的情况时,就有可能会回收掉正在后台运行的服务。如果你希望服务可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台服务。前台服务和普通服务最大的区别在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏可以看到更加详细的信息,非常类似于通知的效果当然有时候你也可能不仅仅是为了防止服务被回收掉才使用前台服务的。有些项目由于特殊的需求会要求必须使用前台服务,比如说天气预报应用,它的服务在后台更新天气数据的同时,还会在系统状态栏一直显示当前的天气信息。
public class ForegroundService2 extends Service {
private final String TAG = ForegroundService2.class.getSimpleName();
public ForegroundService2() {
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate...");
Intent intent = new Intent(this, ServiceActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("this is content title")
.setContentText("this is content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
IntentService
服务中的代码都是默认运行在主线程中的,如果直接在服务里去处理一些耗时的业务,就很容易出现ANR的情况。所以,我们应该在服务里开启一个子线程,然后在那里去处理耗时的逻辑。可是这种服务一旦启动起来,就会一直处于运行状态,必须调用stopService()或者stopSelf()方法才能让服务停止下来。代码如下:
public class MyService extends Service {
//·····
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"onStartCommand...");
new Thread(new Runnable() {
@Override
public void run() {
//在这里处理具体的业务逻辑;
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
//····
}
Android专门提供一个IntentService类,这个类就很好地解决了前面所提到的问题,做到了集开启线程和自动停止于一身。
Service的启动流程
Service是通过AMS(ActivityManagerService)去管理创建流程的。
使用startService()启动
一个应用进程通过startService()调用AMS,然后AMS再判断这个Service是否已经启动,若未启动则通知应用去启动Service,若已经启动则直接通知客户端回调onStartCommand()方法。
启动流程图如下:
启动流程的代码顺序如下:
Context.java类中:
startService(Intent service);
(说明:Context.java是一个抽象类,其实现类是ContextImpl.java)
ContextImpl.java类中:
startService(Intent service);
startServiceCommon(Intent service,boolean requireForeground,UserHandle user);
ActivityManager.getService().startService();
(说明:ActivityManager.getService()得到的是IActivityManager对象,IActivityManager是一个aidl文件,ActivityManagerService继承了IActivityManager.Stub,所以ActivityManager.getService().startService()是在ActivityManagerService类中实现的。)
ActivityManagerService.java类中:
startService(IApplicationThread caller, Intent service,String resolvedType, boolean requireForeground, String callingPackage, int userId);
ActiveServices.java类中:
startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId);
startServiceInnerLocked();
bringUpServiceLocked();
我们侧重看一下startServiceLocked()和bringUpServiceLocked()方法:
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid,boolean fgRequired, String callingPackage, final int userId)throws TransactionTooLargeException {
//---;
//根据Intent获取ServiceRecord对象。每个Service在AMS中都要对应有一个ServiceRecord;
ServiceLookupResult res = retrieveServiceLocked(service,resolvedType,callingPackage,callingPid,callingUid,userId,true,callerFg,false);
ServiceRecord r = res.record;
r.pendingStarts.add(new ServiceRecord.StartItem(r,false,r.makeNextStartId(),service,neededGrants,callingUid));
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,boolean whileRestarting, boolean permissionsReviewRequired)throws TransactionTooLargeException {
//r.app就是表示Service所在的进程,真正启动Service时会给它赋值。如果Service已经启动的话,这个进程非空,且已经就绪。如果该Service已经启动则直接调用Service的onStartCommand()方法;
if(r.app != null && r.app.thread != null){
//调用Service的onStartCommand()方法;
sendServiceArgsLocked(r,execInFg,false);
return null;
}
//找到Service对应的进程记录;
ProcessRecord app;
app = mAm.getProcessRecordLocked(proxName,r.appInfo.uid,false);
if(app != null && app.thread != null){
//进程就绪才真正去启动Service;创建Service;
realStartServiceLocked(r,app,execInFg);
return null;
}
if(app == null && !permissionReviewRequired){
//开启新的进程;
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,hostingType, r.name, false, isolated, false)) == null{
//进程创建失败后做的清除操作,如解绑Service,停止Service;
bringDownServiceLocked(r);
return msg;
}
}
if(!mPendingServices.contains(r)){
//记录,进程启动就绪后会再去启动Service;
mPendingServices.add(r);
}
}
AMS是通过其持有Service对应的ServiceRecord来判断Service是否已启动,同时进程是通过类似的ProcessRecord来判断是否已启动。
在bringUpServiceLocked()方法中有四个方法非常重要,如下:
1 . sendServiceArgsLocked():会调用Service的onStartCommand()方法,当Service已经存在时则直接调用onStartCommand(),不再重新创建Service;
2 . realStartServiceLocked():创建一个Service;
3 . startProcessLocked():开启一个新的进程;
4 . bringDownServiceLocked():主要是做解绑Service,停止Service的操作;
sendServiceArgsLocked()
我们开始分析sendServiceArgsLocked()方法:
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,boolean oomAdjusted) throws TransactionTooLargeException {
//当使用bindService()启动时,N == 0,所以bindService()不会调用onStartCommand()方法;
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
try{
r.app.thread.scheduleServiceArgs(r, slice);
}
}
r.app.thread.scheduleServiceArgs(r,slice)这个方法中,r是ServiceRecord对象,r.app是ProcessRecord对象,r.app.thread是IApplicationThread对象。IApplicationThread是一个aidl文件,由ActivityThread.java类中的内部类ApplicationThread继承实现,所以这一行代码最终是在ApplicationThread类中来执行的。
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
//---;
sendMessage(H.SERVICE_ARGS, s);
}
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
//---;
int res;
res = s.onStartCommand(data.args, data.flags, data.startId);
}
在handleServiceArgs()方法中,s是Service,可以看到,在这个方法中,系统调用了Service的onStartCommand()方法。
realStartServiceLocked()
我们开始分析realStartServiceLocked()方法:
private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {
try{
app.thread.scheduleCreateService(r,r.serviceInfo,mAm.conpatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),app.repProcState);
r.postNotification();
created = true;
}catch(DeadObjectException e){
//---;
}finally{
if(!created){
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r,inDestroying,inDestroying);
if(newService){
app.services.remove(r);
r.app = null;
}
if(!inDestroying){
scheduleServiceRestartLocked(r,false);
}
}
}
//调用Service的onBind()方法;
requestServiceBindingLocked(r,execInFg);
sendServiceArgsLocked(r,execInFg,true);
}
首先调用了ApplicationThread的scheduleCreateService()方法,
scheduleCreateService()方法中通过系统Handler来调用ActivityThread的handleCreateService()方法。
private void handleCreateService(CreateServiceData data) {
//---;
try{
//拿到ClassLoader;
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//通过反射创建Service;
service = (Service)cl.loadClass(data.info.name).newInstance();
}
try{
//创建一个Service对应的ContextImpl;
ContextImpl context = ContextImpl.createAppContext(this,packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false,mInstrumentation);
service.attach(context,this,data.info.name,data.token,app,ActivityManager.getService());
//调用Service的onCreate()方法;
service.onCreate();
}
}
startProcessLocked()
bringDownServiceLocked()
我们开始分析bringDownServiceLocked()方法:
private final void bringDownServiceLocked(ServiceRecord r) {
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
for (int i=0; i<c.size(); i++) {
ConnectionRecord cr = c.get(i);
//仍然存在与正在关闭的服务的连接,把它标记为已死;
cr.serviceDead = true;
try {
cr.conn.connected(r.name, null, true);
} catch (Exception e) {
}
}
}
//与Service解除绑定;
if (r.app != null && r.app.thread != null) {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (ibr.hasBound) {
try {
//调用Service的onUnbind()方法;
r.app.thread.scheduleUnbindService(r,
ibr.intent.getIntent());
} catch (Exception e) {
serviceProcessGoneLocked(r);
}
}
}
}
//检查Service是否在前台运行;
if (r.fgRequired) {
r.fgRequired = false;
r.fgWaiting = false;
mAm.mHandler.removeMessages(
ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
if (r.app != null) {
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
msg.obj = r.app;
mAm.mHandler.sendMessage(msg);
}
}
//当通过bringUpServiceLocked()调用此方法时,则表示找不到该服务;
if (found != null && found != r) {
smap.mServicesByName.put(r.name, found);
throw new IllegalStateException("Bringing down " + r + " but actually running "
+ found);
}
//开始清除Service的相关信息;
cancelForegroundNotificationLocked(r);
if(r.isForeground){
decActiveForegroundAppLocked(smap,r);
}
r.isForeground = false;
r.foregroundId = 0;
r.foregroundNoti = null;
r.clearDeliveredStartsLocked();
r.pendingStarts.clear();
if (r.app != null) {
synchronized (r.stats.getBatteryStats()) {
r.stats.stopLaunchedLocked();
}
r.app.services.remove(r);
if (r.whitelistManager) {
updateWhitelistManagerLocked(r.app);
}
if (r.app.thread != null) {
updateServiceForegroundLocked(r.app, false);
try {
bumpServiceExecutingLocked(r, false, "destroy");
mDestroyingServices.add(r);
r.destroying = true;
mAm.updateOomAdjLocked(r.app, true);
//销毁Service并调用Service的onDestroy()方法;
r.app.thread.scheduleStopService(r);
} catch (Exception e) {
serviceProcessGoneLocked(r);
}
} else {
//---;
}
} else {
//---;
}
//后面就是将一些信息置为null,方便回收;
if (r.bindings.size() > 0) {
r.bindings.clear();
}
if (r.restarter instanceof ServiceRestarter) {
((ServiceRestarter)r.restarter).setService(null);
}
int memFactor = mAm.mProcessStats.getMemFactorLocked();
long now = SystemClock.uptimeMillis();
if (r.tracker != null) {
r.tracker.setStarted(false, memFactor, now);
r.tracker.setBound(false, memFactor, now);
if (r.executeNesting == 0) {
r.tracker.clearCurrentOwner(r, false);
r.tracker = null;
}
}
smap.ensureNotStartingBackgroundLocked(r);
}
从上面代码可以看出,bringDownServiceLocked()方法主要就是销毁和解绑Service。
使用bindService()启动
启动流程的代码顺序如下:
Context.java类中:
bindService(@RequiresPermission Intent service,@NonNull ServiceConnection conn, @BindServiceFlags int flags)
ContextImpl.java类中:
bindService(Intent service, ServiceConnection conn,int flags)
bindServiceCommon(service,conn,flags,mMainThread.getHandler(),
Process.myUserHandle())
ActivityManagerService.java类中:
bindService(IApplicationThread caller, IBinder token, Intent service,String resolvedType, IServiceConnection connection, int flags, String callingPackage,int userId))
ActiveServices.java类中:
bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,String resolvedType, final IServiceConnection connection, int flags,String callingPackage, final int userId)
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
//调用AMS的bindService()方法;
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, getOpPackageName(), user.getIdentifier());
}
}
bindServiceCommon()方法中, mPackageInfo.getServiceDispatcher()方法获取的是LoadedApk.ServiceDispatcher对象的内部类InnerConnection对象。之所以不能直接使用ServiceConnection对象,是因为服务的绑定有可能是跨进程的,因此ServiceConnection必须借助于Binder才能让远程服务端回调自己的方法,而ServiceDispatcher的内部类InnerConnection刚好充当起Binder这个角色。在获取到InnerConnection对象以后,就调用AMS的bindService()方法。然后便是再次跳转到ActiveServices.java类中的bindServiceLocked()方法。
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,String resolvedType, final IServiceConnection connection, int flags,String callingPackage, final int userId) throws TransactionTooLargeException {
//---;
//判断是否进行权限检查;
if (mAm.mPermissionReviewRequired) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(s.packageName, s.userId)) {
RemoteCallback callback = new RemoteCallback(new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
synchronized(mAm) {
final long identity= Binder.clearCallingIdentity();
try {
if(!mPendingServices.contains(serviceRecord)) {
return;
}
if (!mAm.getPackageManagerInternalLocked()
.isPermissionsReviewRequired(serviceRecord.packageName,serviceRecord.userId)) {
try {
//创建Service;
bringUpServiceLocked(serviceRecord,
serviceIntent.getFlags(),
callerFg, false, false);
} catch (RemoteException e) {
}
} else {
unbindServiceLocked(connection);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
});
}
}
final long origId = Binder.clearCallingIdentity();
try{
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,permissionsReviewRequired) != null) {
return 0;
}
}
if(s.app != null && b.intent.received){
//如果Service已经在运行,直接调用ServiceConnection中的onServiceConnected()方法;
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
}
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
}
}
}
从上面代码中,可以知道bindServiceLocked()方法最终都是调用了bringUpServiceLocked()方法。下面讲解requestServiceBindingLocked()方法。
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) throws TransactionTooLargeException {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState);
}
}
}
在requestServiceBindingsLocked()方法中直接调用了返回值为boolean的requestServiceBindingsLocked()方法,在另一个方法中,调用了ApplicationThread的scheduleBindService()方法,然后再次调用ActivityThread的handleBindService()方法。
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
//---;
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
//调用ServiceConnection中的onServiceConnected()方法;
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
}
}
}
在上面代码中调用了Service的onBind()方法。原则上来说,Service的onBind()方法调用后,Service就处于绑定状态了,但是onBind()方法还是Service的方法,这个时候客户端并不知道已经成功连接Service了,所以还必须调用客户端的ServiceConnection中的onServiceConnected()方法,这个过程就是通过AMS的publishService()来完成的。
public void publishService(IBinder token, Intent intent, IBinder service) {
//---;
synchronized(this) {
//---;
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
再次右跳转到了ActiveServices中的mServices.publishServiceLocked()方法中了。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (r != null) {
if (b != null && !b.received) {
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
//---;
try{
c.conn.connected(r.name, service, false);
}
}
}
}
}
}
其中publishServiceLocked()方法核心就是c.conn.connected(r.name,service,false),其中的类型是ConnectionRecord,c.conn的类型是ServiceDispatcher.InnerConnection。
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
ServiceDispatcher.InnerConnection的connected()方法很简单,就是调用了LoadedApk.ServiceDispatcher的connected()方法。
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
}
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
mConnection就是ServiceDispatcher.InnerConnection。
使用服务的一些问题
1 . 在Service中开启了线程,如果把Service销毁了,但是线程还是会继续存活,所以,需要在Service的onDestroy()方法中把线程给销毁。(注意安全销毁线程的方法)
- 提高Service的优先级;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-----------------------last line for now------------------------