ContentService源码分析
来源:互联网 发布:手机桌面图标软件 编辑:程序博客网 时间:2024/06/08 18:39
简单介绍
ContentProvider按照一定规则暴露自己的接口给其它应用来访问自己应用的数据(其实就是自定义增删改查接口并暴露出去,让别的应用访问自己的数据)。当其他应用需要用到该应用的数据时,可以使用ContentResolver,而通过ContentResolver我们可以完成两大功能:
1 通过其对ContentProvider中的数据进行添加、删除、修改和查询操作
2 通过其来监听ContentProvider中数据的变化
那ContentResolver是如何实现这些功能的呢?其实,它内部主要就是调用了ContentService的相应方法,这就说明数据的更新等操作主要由ContentService来完成的。
接下来,我们就结合ContentResolver的使用来分析ContentService
从调用开始分析
在SystemServer的startOtherServices方法中,有这么一段代码
contentService = ContentService.main(context,mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);............// 省略部分代码try { if (contentService != null) contentService.systemReady();} catch (Throwable e) { reportWtf("making Content Service ready", e);}
在这里调用ContentService的main方法创建了一个ContentService实例,并调用了它的systemReady()方法。我们分开两步分析:
1. ContentService.main()分析
public static ContentService main(Context context, boolean factoryTest) { ContentService service = new ContentService(context, factoryTest); ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service); return service;}
这里主要就是创建了一个ContentService,并将其添加到ServiceManager中。我们进去看下它的构造函数
/*package*/ ContentService(Context context, boolean factoryTest) { mContext = context; mFactoryTest = factoryTest;}
这里只是简单的保存了两个变量的引用在本地
2. contentService.systemReady()
public void systemReady() { getSyncManager();}private SyncManager getSyncManager() { if (SystemProperties.getBoolean("config.disable_network", false)) { return null; } synchronized(mSyncManagerLock) { try { // Try to create the SyncManager, return null if it fails (e.g. the disk is full). if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest); } catch (SQLiteException e) { Log.e(TAG, "Can't create SyncManager", e); } return mSyncManager; }}
假如网络被禁止,则不获取SyncManager服务。SyncManager是数据同步的主要类
ContentService的registerContentObserver()方法分析
我们从ContentResolver入手:
/** * Register an observer class that gets callbacks when data identified by a * given content URI changes. * * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI * for a whole class of content. * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code> * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI * specified by <em>uri</em> will cause notifications to be sent. If <code>true</code>, any URI values * at or below the specified URI will also trigger a match. * @param observer The object that receives callbacks when changes occur. * @see #unregisterContentObserver */public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer){ registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());}/** @hide - designated user version */public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer, int userHandle){ try { getContentService().registerContentObserver(uri, notifyForDescendents, observer.getContentObserver(), userHandle); } catch (RemoteException e) { }}
从上边的函数可以看到,ContentResolver的registerContentObserver()方法内部其实是调用了ContentService的registerContentObserver方法,我们进入查看
public void registerContentObserver(Uri uri, boolean notifyForDescendants, IContentObserver observer) { registerContentObserver(uri, notifyForDescendants, observer, UserHandle.getCallingUserId());}/** * Register a content observer tied to a specific user's view of the provider. * @param userHandle the user whose view of the provider is to be observed. May be * the calling user without requiring any permission, otherwise the caller needs to * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and * USER_CURRENT are properly handled; all other pseudousers are forbidden. */@Overridepublic void registerContentObserver(Uri uri, boolean notifyForDescendants, IContentObserver observer, int userHandle) { if (observer == null || uri == null) { throw new IllegalArgumentException("You must pass a valid uri and observer"); } enforceCrossUserPermission(userHandle, "no permission to observe other users' provider view"); if (userHandle < 0) { if (userHandle == UserHandle.USER_CURRENT) { userHandle = ActivityManager.getCurrentUser(); } else if (userHandle != UserHandle.USER_ALL) { throw new InvalidParameterException("Bad user handle for registerContentObserver: " + userHandle); } } synchronized (mRootNode) { mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode, Binder.getCallingUid(), Binder.getCallingPid(), userHandle); if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + " with notifyForDescendants " + notifyForDescendants); }}
ContentService的registerContentObserver方法内部实现很简单:就是将uri和observer的对应关系保存到mRootNode变量中
ContentService的nitofyChange()分析
我们从ContentResolver入手:
public void notifyChange(Uri uri, ContentObserver observer) { notifyChange(uri, observer, true /* sync to network */);}public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());}public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork, int userHandle) { try { getContentService().notifyChange( uri, observer == null ? null : observer.getContentObserver(), observer != null && observer.deliverSelfNotifications(), syncToNetwork, userHandle); } catch (RemoteException e) { }}
从上边的函数可以看到,ContentResolver的notifyChange()方法内部其实是调用了ContentService的notifyChange方法,我们进入查看
try { ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); synchronized (mRootNode) { mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, userHandle, calls); } final int numCalls = calls.size(); for (int i=0; i<numCalls; i++) { ObserverCall oc = calls.get(i); try { oc.mObserver.onChange(oc.mSelfChange, uri, userHandle); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); } } catch (RemoteException ex) { synchronized (mRootNode) { Log.w(TAG, "Found dead observer, removing"); IBinder binder = oc.mObserver.asBinder(); final ArrayList<ObserverNode.ObserverEntry> list = oc.mNode.mObservers; int numList = list.size(); for (int j=0; j<numList; j++) { ObserverNode.ObserverEntry oe = list.get(j); if (oe.observer.asBinder() == binder) { list.remove(j); j--; numList--; } } } } } if (syncToNetwork) { SyncManager syncManager = getSyncManager(); if (syncManager != null) { syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid, uri.getAuthority()); }} finally { restoreCallingIdentity(identityToken);}
上边主要有两大操作:
- 从mRootNode中获取所有匹配的ContentObserver并保存在变量calls中,遍历calls,调用每个ContentObserver的onChange()方法。假如出现异常:”Found dead observer, removing”
- 假如syncToNetwork为true,则调用syncManager.scheduleLocalSync()进行同步
- ContentService源码分析
- 基于N源码的ContentService数据通知机制
- ContentService简单浅析
- ContentService注册和更新机制
- Android 系统服务之 ContentService
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析:SparseArray分析
- Android System Server大纲之ContentService和ContentProvider原理剖析
- 源码- Spark Broadcast源码分析
- Android源码/框架源码分析
- 【Android应用源码分析】HandlerThread 源码分析
- Chrome 控制台console的用法
- HDU 5979 Convex(数学)
- 34. Search for a Range
- CSS3 基础(009_按钮)
- NSNumber的大小比较
- ContentService源码分析
- bit,byte,编码、解码、字符集的总结
- jquery mobile界面数据刷新
- Spark快速安装与简单入门_Ubuntu14.04 64bitx
- 报错:java.util.Map is an interface, and JAXB can't handle interfaces.
- ELF Linker学习篇(四)——初始化
- js跨域的几种解决方案
- 《OpenCV》Part1 OpenCV3.1.0安装配置与Qt5.5测试
- 每日一个js实例10--回车键