Android应用程序组件Content Provider的启动过程源代码分析(6)
16lz
2021-01-23
Step 17.ActivityThread.installProvider 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
回到前面的installProvider函数中,它接下来调用下面接口来初始化刚刚加载好的Content Provider:
这个函数的作用主要就是在应用程序进程中把相应的Content Provider类加载进来了,在我们这个种情景中,就是要在ArticlesProvider这个应用程序中把ArticlesProvider这个Content Provider类加载到内存中来了:
- publicfinalclassActivityThread{
- ......
- privatefinalIContentProviderinstallProvider(Contextcontext,
- IContentProviderprovider,ProviderInfoinfo,booleannoisy){
- ContentProviderlocalProvider=null;
- if(provider==null){
- ......
- Contextc=null;
- ApplicationInfoai=info.applicationInfo;
- if(context.getPackageName().equals(ai.packageName)){
- c=context;
- }elseif(mInitialApplication!=null&&
- mInitialApplication.getPackageName().equals(ai.packageName)){
- c=mInitialApplication;
- }else{
- try{
- c=context.createPackageContext(ai.packageName,
- Context.CONTEXT_INCLUDE_CODE);
- }catch(PackageManager.NameNotFoundExceptione){
- }
- }
- ......
- try{
- finaljava.lang.ClassLoadercl=c.getClassLoader();
- localProvider=(ContentProvider)cl.
- loadClass(info.name).newInstance();
- provider=localProvider.getIContentProvider();
- ......
- //XXXNeedtocreatethecorrectcontextforthisprovider.
- localProvider.attachInfo(c,info);
- }catch(java.lang.Exceptione){
- ......
- }
- }elseif(localLOGV){
- ......
- }
- synchronized(mProviderMap){
- //Cachethepointerfortheremoteprovider.
- Stringnames[]=PATTERN_SEMICOLON.split(info.authority);
- for(inti=0;i<names.length;i++){
- ProviderClientRecordpr=newProviderClientRecord(names[i],provider,
- localProvider);
- try{
- provider.asBinder().linkToDeath(pr,0);
- mProviderMap.put(names[i],pr);
- }catch(RemoteExceptione){
- returnnull;
- }
- }
- if(localProvider!=null){
- mLocalProviders.put(provider.asBinder(),
- newProviderClientRecord(null,provider,localProvider));
- }
- }
- returnprovider;
- }
- ......
- }
接着通过调用localProvider的getIContentProvider函数来获得一个Binder对象,这个Binder对象返回给installContentProviders函数之后,就会传到ActivityManagerService中去,后续其它应用程序就是通过获得这个Binder对象来和相应的Content Provider进行通信的了。我们先看一下这个函数的实现,然后再回到installProvider函数中继续分析。
- finaljava.lang.ClassLoadercl=c.getClassLoader();
- localProvider=(ContentProvider)cl.
- loadClass(info.name).newInstance();
Step 18. ContentProvider.getIContentProvider 这个函数定义在frameworks/base/core/java/android/content/ContentProvider.java文件中:
从这里我们可以看出,ContentProvider类和Transport类的关系就类似于ActivityThread和ApplicationThread的关系,其它应用程序不是直接调用ContentProvider接口来访问它的数据,而是通过调用它的内部对象mTransport来间接调用ContentProvider的接口,这一点我们在下一篇文章中分析调用Content Provider接口来获取共享数据时将会看到。
- publicabstractclassContentProviderimplementsComponentCallbacks{
- ......
- privateTransportmTransport=newTransport();
- ......
- classTransportextendsContentProviderNative{
- ......
- }
- publicIContentProvidergetIContentProvider(){
- returnmTransport;
- }
- ......
- }
回到前面的installProvider函数中,它接下来调用下面接口来初始化刚刚加载好的Content Provider:
- //XXXNeedtocreatethecorrectcontextforthisprovider.
- localProvider.attachInfo(c,info);
这个函数很简单,主要就是根据这个Content Provider的信息info来设置相应的读写权限,然后调用它的子类的onCreate函数来让子类执行一些初始化的工作。在我们这个情景中,这个子类就是ArticlesProvide应用程序中的ArticlesProvider类了。
- publicabstractclassContentProviderimplementsComponentCallbacks{
- ......
- publicvoidattachInfo(Contextcontext,ProviderInfoinfo){
- /*
- *Onlyallowittobesetonce,soafterthecontentservicegives
- *thistousclientscan'tchangeit.
- */
- if(mContext==null){
- mContext=context;
- mMyUid=Process.myUid();
- if(info!=null){
- setReadPermission(info.readPermission);
- setWritePermission(info.writePermission);
- setPathPermissions(info.pathPermissions);
- mExported=info.exported;
- }
- ContentProvider.this.onCreate();
- }
- }
- ......
- }
Step 20. ArticlesProvider.onCreate 这个函数定义在前面一篇文章 Android应用程序组件Content Provider应用实例 介绍的应用程序ArtilcesProvider源代码工程目录下,在文件为packages/experimental/ArticlesProvider/src/shy/luo/providers/articles/ArticlesProvider.java中:
- publicclassArticlesProviderextendsContentProvider{
- ......
- @Override
- publicbooleanonCreate(){
- Contextcontext=getContext();
- resolver=context.getContentResolver();
- dbHelper=newDBHelper(context,DB_NAME,null,DB_VERSION);
- returntrue;
- }
- ......
- }
回到前面Step 17中的installProvider函数中,它接下来就是把这些在本地中加载的Content Provider信息保存下来了,以方便后面查询和使用:
- synchronized(mProviderMap){
- //Cachethepointerfortheremoteprovider.
- Stringnames[]=PATTERN_SEMICOLON.split(info.authority);
- for(inti=0;i<names.length;i++){
- ProviderClientRecordpr=newProviderClientRecord(names[i],provider,
- localProvider);
- try{
- provider.asBinder().linkToDeath(pr,0);
- mProviderMap.put(names[i],pr);
- }catch(RemoteExceptione){
- returnnull;
- }
- }
- if(localProvider!=null){
- mLocalProviders.put(provider.asBinder(),
- newProviderClientRecord(null,provider,localProvider));
- }
- }
更多相关文章
- C语言函数以及函数的使用
- [Android Studio] Android Studio如何提示函数用法
- Android 驱动之旅 第四章:在Android 系统中编写JNI 方法在应用程
- Android Wear应用程序开发的简要说明,对每个初学者和中级android
- (一)Android应用程序及组件简介
- Android应用程序资源管理器(Asset Manager)的创建过程分析
- Hierarchy Viewer 帮你分析应用程序UI布局
- Android应用程序的数据存放目录 路径
- 如何使Android应用程序获取系统权限