Android应用程序组件Content Provider的启动过程源代码分析(3)

简介:
 Step 7. ActivityManagerService.getContentProviderImpl
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
 
 
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     private final ContentProviderHolder getContentProviderImpl(   
  6.             IApplicationThread caller, String name) {   
  7.         ContentProviderRecord cpr;   
  8.         ProviderInfo cpi = null;   
  9.    
  10.         synchronized(this) {   
  11.             ProcessRecord r = null;   
  12.             if (caller != null) {   
  13.                 r = getRecordForAppLocked(caller);   
  14.                 ......   
  15.             }   
  16.    
  17.             // First check if this content provider has been published...   
  18.             cpr = mProvidersByName.get(name);   
  19.             if (cpr != null) {   
  20.                 ......   
  21.             } else {   
  22.                 try {   
  23.                     cpi = AppGlobals.getPackageManager().   
  24.                         resolveContentProvider(name,   
  25.                         STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);   
  26.                 } catch (RemoteException ex) {   
  27.                 }   
  28.                 ......   
  29.             }   
  30.    
  31.             cpr = mProvidersByClass.get(cpi.name);   
  32.             final boolean firstClass = cpr == null;   
  33.             if (firstClass) {   
  34.                 try {   
  35.                     ApplicationInfo ai =   
  36.                         AppGlobals.getPackageManager().   
  37.                         getApplicationInfo(   
  38.                         cpi.applicationInfo.packageName,   
  39.                         STOCK_PM_FLAGS);   
  40.                     ......   
  41.                     cpr = new ContentProviderRecord(cpi, ai);   
  42.                 } catch (RemoteException ex) {   
  43.                     // pm is in same process, this will never happen.   
  44.                 }   
  45.             }   
  46.    
  47.             if (r != null && cpr.canRunHere(r)) {   
  48.                 // If this is a multiprocess provider, then just return its   
  49.                 // info and allow the caller to instantiate it.  Only do   
  50.                 // this if the provider is the same user as the caller's   
  51.                 // process, or can run as root (so can be in any process).   
  52.                 return cpr;   
  53.             }   
  54.    
  55.             ......   
  56.    
  57.             // This is single process, and our app is now connecting to it.   
  58.             // See if we are already in the process of launching this   
  59.             // provider.   
  60.             final int N = mLaunchingProviders.size();   
  61.             int i;   
  62.             for (i=0; i<N; i++) {   
  63.                 if (mLaunchingProviders.get(i) == cpr) {   
  64.                     break;   
  65.                 }   
  66.             }   
  67.    
  68.             // If the provider is not already being launched, then get it   
  69.             // started.   
  70.             if (i >= N) {   
  71.                 final long origId = Binder.clearCallingIdentity();   
  72.                 ProcessRecord proc = startProcessLocked(cpi.processName,   
  73.                     cpr.appInfo, false0"content provider",   
  74.                     new ComponentName(cpi.applicationInfo.packageName,   
  75.                     cpi.name), false);   
  76.                 ......   
  77.                 mLaunchingProviders.add(cpr);   
  78.                 ......   
  79.             }   
  80.    
  81.             // Make sure the provider is published (the same provider class   
  82.             // may be published under multiple names).   
  83.             if (firstClass) {   
  84.                 mProvidersByClass.put(cpi.name, cpr);   
  85.             }   
  86.             cpr.launchingApp = proc;   
  87.             mProvidersByName.put(name, cpr);   
  88.    
  89.             ......   
  90.         }   
  91.    
  92.         // Wait for the provider to be published...   
  93.         synchronized (cpr) {   
  94.             while (cpr.provider == null) {   
  95.                 ......   
  96.                 try {   
  97.                     cpr.wait();   
  98.                 } catch (InterruptedException ex) {   
  99.                 }   
  100.             }   
  101.         }   
  102.    
  103.         return cpr;   
  104.     }   
  105.        
  106.     ......   
  107. }   
    这个函数比较长,我们一步一步地分析。
        函数首先是获取调用者的进程记录块信息:
  1. ProcessRecord r = null;  
  2. if (caller != null) {  
  3.     r = getRecordForAppLocked(caller);  
  4.     ......  
  5. }  
        在我们这个情景中,要获取的就是应用程序Article的进程记录块信息了,后面会用到。
 
        在ActivityManagerService中,有两个成员变量是用来保存系统中的Content Provider信息的,一个是mProvidersByName,一个是mProvidersByClass,前者是以Content Provider的authoriry值为键值来保存的,后者是以Content Provider的类名为键值来保存的。一个Content Provider可以有多个authority,而只有一个类来和它对应,因此,这里要用两个Map来保存,这里为了方便根据不同条件来快速查找而设计的。下面的代码就是用来检查要获取的Content Provider是否已经加存在的了:
 
 
  1. // First check if this content provider has been published...   
  2. cpr = mProvidersByName.get(name);   
  3. if (cpr != null) {   
  4.     ......   
  5. else {   
  6.     try {   
  7.         cpi = AppGlobals.getPackageManager().   
  8.             resolveContentProvider(name,   
  9.             STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);   
  10.     } catch (RemoteException ex) {   
  11.     }   
  12.     ......   
  13. }   
  14.    
  15. cpr = mProvidersByClass.get(cpi.name);   
  16. final boolean firstClass = cpr == null;   
  17. if (firstClass) {   
  18.     try {   
  19.         ApplicationInfo ai =   
  20.             AppGlobals.getPackageManager().   
  21.             getApplicationInfo(   
  22.             cpi.applicationInfo.packageName,   
  23.             STOCK_PM_FLAGS);   
  24.         ......   
  25.         cpr = new ContentProviderRecord(cpi, ai);   
  26.     } catch (RemoteException ex) {   
  27.         // pm is in same process, this will never happen.   
  28.     }   
  29. }   
      在我们这个情景中,由于是第一次调用ArticlesProvider接口,因此,在mProvidersByName和mProvidersByClass两个Map中都不存在ArticlesProvider的相关信息,因此,这里会通过AppGlobals.getPackageManager函数来获得PackageManagerService服务接口,然后分别通过它的resolveContentProvider和getApplicationInfo函数来分别获取ArticlesProvider应用程序的相关信息,分别保存在cpi和cpr这两个本地变量中。这些信息都是在安装应用程序的过程中保存下来的,具体可以参考 Android应用程序安装过程源代码分析 一文。




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966983,如需转载请自行联系原作者
目录
相关文章
|
21天前
|
存储 设计模式 数据库
构建高效的安卓应用:探究Android Jetpack架构组件
【4月更文挑战第20天】 在移动开发的世界中,构建一个既高效又可维护的安卓应用是每个开发者追求的目标。随着Android Jetpack的推出,Google为开发者提供了一套高质量的库、工具和指南,以简化应用程序开发流程。本文将深入探讨Jetpack的核心组件之一——架构组件,并展示如何将其应用于实际项目中,以提升应用的响应性和稳定性。我们将通过分析这些组件的设计原则,以及它们如何协同工作,来揭示它们对于构建现代化安卓应用的重要性。
|
2天前
|
Java 开发工具 Android开发
如何在Eclipse中查看Android源码或者第三方组件包源码(转)
如何在Eclipse中查看Android源码或者第三方组件包源码(转)
12 4
|
19天前
|
Android开发
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
18 0
|
19天前
|
Java Android开发 C++
Android源代码定制:MK文件执行顺序|属性覆盖
Android源代码定制:MK文件执行顺序|属性覆盖
18 2
Android源代码定制:MK文件执行顺序|属性覆盖
|
19天前
|
Android开发 芯片
Android源代码定制:移除无用lunch|新建lunch|自定义customize.mk
Android源代码定制:移除无用lunch|新建lunch|自定义customize.mk
26 3
|
19天前
|
Android开发
Android源代码定制:添加customize.mk文件进行分项目和分客户的定制
Android源代码定制:添加customize.mk文件进行分项目和分客户的定制
5 0
|
21天前
|
设计模式 前端开发 数据库
构建高效Android应用:使用Jetpack架构组件实现MVVM模式
【4月更文挑战第21天】 在移动开发领域,构建一个既健壮又易于维护的Android应用是每个开发者的目标。随着项目复杂度的增加,传统的MVP或MVC架构往往难以应对快速变化的市场需求和复杂的业务逻辑。本文将探讨如何利用Android Jetpack中的架构组件来实施MVVM(Model-View-ViewModel)设计模式,旨在提供一个更加模块化、可测试且易于管理的代码结构。通过具体案例分析,我们将展示如何使用LiveData, ViewModel, 和Repository来实现界面与业务逻辑的分离,以及如何利用Room数据库进行持久化存储。最终,你将获得一个响应迅速、可扩展且符合现代软件工
24 0
|
25天前
|
Android开发 开发者
什么是Android Jetpack,它包括哪些组件?
【4月更文挑战第17天】Android Jetpack是Google提供的一套工具集,助力开发者高效、稳定地开发Android应用。它包含架构、UI、行为和基础组件,简化了后台任务、导航和生命周期管理,使开发者能专注于创新。随着不断更新,如CameraX的推出,掌握Jetpack对开发者面试和工作至关重要。
22 0
|
27天前
|
存储 数据库 Android开发
使用Android Jetpack组件加速开发流程
【4月更文挑战第14天】Android Jetpack是为提升开发速度和代码质量而生的组件集合,包括`ViewModel`、`LiveData`、`RecyclerView`、`Room`、`WorkManager`等,它们遵循最新设计原则和最佳实践。例如,`RecyclerView`优化列表显示,`Room`简化数据库操作,`WorkManager`处理后台任务,`ViewModel`和`LiveData`分离业务和UI逻辑。此外,`Navigation`和`Paging`分别优化用户导航和数据加载。通过这些组件,开发者能更高效地构建高性能应用,值得学习和使用。
|
1月前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。