Service草稿

mac2025-04-29  7

AIDL

Google官方文档:https://developer.android.google.cn/guide/components/aidl?hl=zh_cn 其中一段注意如下: 注意:只有在需要不同应用的客户端通过 IPC 方式访问服务,并且希望在服务中进行多线程处理时,您才有必要使用 AIDL。如果您无需不同应用执行并发 IPC,则应通过实现 Binder 来创建接口;或者,如果您想执行 IPC,但不需要处理多线程,请使用 Messenger 来实现口。无论如何,在实现 AIDL 之前,请您务必理解绑定服务。 在使用时,如果不是不同应用客户端间通讯,使用以下方法实现客户端与服务间的联系。

问题1;如何Binder创建接口 问题2:如何Messanger实现接口 问题3:理解绑定服务 创建绑定服务时,必须提供Ibinder,进而提供编程接口,以便客户端使用此接口与服务进行交互。

@Override public IBinder onBind(Intent intent) { return mBinder; }

可以通过三种方式定义接口 扩展Binder类、使用Messenger、AIDL下面将分开进行介绍 给出官方示例https://developer.android.google.cn/guide/components/bound-services.html?hl=zh_cn

首先在Android studio中提供了新建AIDL文件的方法 生成文件如下,自带一个默认的方法

// IMusicAidlInterface.aidl package com.example.servicesourcecode; // Declare any non-default types here with import statements interface IMusicAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); }

在Service中定义AIDL接口

private final IMusicAidlInterface.Stub binder = new IMusicAidlInterface.Stub() { public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) { // Does nothing } };

重写onBind方法

@Override public IBinder onBind(Intent intent) { // Return the interface return binder; }

在Activity中定义AIDL并赋值

IMusicAidlInterface iMusicAidlInterface; private ServiceConnection mConnection = new ServiceConnection() { // Called when the connection with the service is established public void onServiceConnected(ComponentName className, IBinder service) { // Following the example above for an AIDL interface, // this gets an instance of the IRemoteInterface, which we can use to call on the service iMusicAidlInterface = IMusicAidlInterface.Stub.asInterface(service); } // Called when the connection with the service disconnects unexpectedly public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "Service has unexpectedly disconnected"); iMusicAidlInterface = null; } };

在onStart()中绑定服务,在onStop()中取消绑定

@Override protected void onStart() { super.onStart(); // Bind to LocalService Intent intent = new Intent(this, MediaService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); unbindService(mConnection); }

服务端和客户端间就建立了联系,三种实现方式的很类似。 使用IPC传递类采用的是 Parcelable(序列化)

public class Picture extends Parcelable { private int mData; public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { //Flatten(变平) this object in to a Parcel. out.writeInt(mData); } public static final Parcelable.Creator<Picture> CREATOR = new Parcelable.Creator<Picture>() { public Picture createFromParcel(Parcel in) { return new Picture(in); } public Picture[] newArray(int size) { return new Picture[size]; } }; private Picture(Parcel in) { mData = in.readInt(); } }

新建一个Parcelable类 Container(容器) for a message (data and object references) that can be sent through an IBinder. Parcel 包装数据在Binder中传输,将数据写入其中。

Parcel parcel=Parcel.obtain(); // Retrieve a new Parcel object from the pool. parcel.writeString("A"); parcel.marshall();//Returns the raw bytes of the parcel. parcel.setDataPosition(0);//Move the current read/write position in the parcel. parcel.recycle();//Put a Parcel object back into the pool. public abstract class Service extends ContextWrapper implements ComponentCallbacks2

ContextWrapper是Context的包装类

/** * Proxying implementation of Context that simply delegates all of its calls to * another Context. Can be subclassed to modify behavior without changing * the original Context. */ public class ContextWrapper extends Context

关于Context在后续的文章再系统介绍,ComponentCallbacks2 接口继承ComponentCallbacks接口 代码如下

public interface ComponentCallbacks { void onConfigurationChanged(Configuration newConfig); void onLowMemory(); }

ComponentCallbacks2 只继承了onLowMemory()方法用于内存需求级别,当内存不足的时候,尽可能保证后台服务不被杀死

service的启动通过调用Context.startService(Intent intent)接下来一步一步分析,后续补上时序图。

Context.java

public abstract ComponentName startService(Intent service);

ContextImpl.java

@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, mUser); } private ComponentName startServiceCommon(Intent service, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); ... } catch (RemoteException e) { return null; } }

接着调用ActivityManagerService的startService

@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException { ... synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }

ActiveServices的startServiceLocked

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);//↓ return cmp; } ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);//↓ if (error != null) { return new ComponentName("!!", error); } ... } private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) { ... if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app); if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg);//↓ return null; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); } ... } private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... final boolean newService = app.services.add(r); bumpServiceExecutingLocked(r, execInFg, "create"); mAm.updateLruProcessLocked(app, false, null); updateServiceForegroundLocked(r.app, /* oomAdj= */ false); mAm.updateOomAdjLocked(); boolean created = false; try { if (LOG_SERVICE_START_STOP) { String nameTerm; int lastPeriod = r.shortName.lastIndexOf('.'); nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName; EventLogTags.writeAmCreateService( r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid); } synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_SERVICE); app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true; } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app); throw e; } finally { if (!created) { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); // Cleanup. if (newService) { app.services.remove(r); r.app = null; } // Retry. if (!inDestroying) { scheduleServiceRestartLocked(r, false); } } } if (r.whitelistManager) { app.whitelistManager = true; } requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); // If the service is in the started state, and there are no // pending arguments, then fake up one so its onStartCommand() will // be called. if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null, 0)); } sendServiceArgsLocked(r, execInFg, true); ... }

ActivityService中的方法继续梳理

最新回复(0)