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,如需转载请自行联系原作者
目录
相关文章
|
16天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
17天前
|
数据库 Android开发 开发者
构建高效Android应用:Kotlin协程的实践指南
【4月更文挑战第2天】随着移动应用开发的不断进步,开发者们寻求更流畅、高效的用户体验。在Android平台上,Kotlin语言凭借其简洁性和功能性赢得了开发社区的广泛支持。特别是Kotlin协程,作为一种轻量级的并发处理方案,使得异步编程变得更加简单和直观。本文将深入探讨Kotlin协程的核心概念、使用场景以及如何将其应用于Android开发中,以提高应用性能和响应能力。通过实际案例分析,我们将展示协程如何简化复杂任务,优化资源管理,并为最终用户提供更加流畅的体验。
|
17天前
|
开发框架 安全 Android开发
探索安卓系统的新趋势:智能家居应用的蓬勃发展
随着智能家居概念的兴起,安卓系统在智能家居应用领域的应用日益广泛。本文将探讨安卓系统在智能家居应用开发方面的最新趋势和创新,以及其对用户生活的影响。
13 2
|
1天前
|
缓存 移动开发 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【4月更文挑战第18天】 在移动开发的世界中,打造一个既快速又流畅的Android应用并非易事。本文深入探讨了如何通过一系列创新的技术策略来提升应用性能和用户体验。我们将从用户界面(UI)设计的简约性原则出发,探索响应式布局和Material Design的实践,再深入剖析后台任务处理、内存管理和电池寿命优化的技巧。此外,文中还将讨论最新的Android Jetpack组件如何帮助开发者更高效地构建高质量的应用。此内容不仅适合经验丰富的开发者深化理解,也适合初学者构建起对Android高效开发的基础认识。
2 0
|
1天前
|
移动开发 Android开发 开发者
构建高效Android应用:采用Kotlin进行内存优化的策略
【4月更文挑战第18天】 在移动开发领域,性能优化一直是开发者关注的焦点。特别是对于Android应用而言,由于设备和版本的多样性,确保应用流畅运行且占用资源少是一大挑战。本文将探讨使用Kotlin语言开发Android应用时,如何通过内存优化来提升应用性能。我们将从减少不必要的对象创建、合理使用数据结构、避免内存泄漏等方面入手,提供实用的代码示例和最佳实践,帮助开发者构建更加高效的Android应用。
5 0
|
3天前
|
缓存 移动开发 Java
构建高效的Android应用:内存优化策略
【4月更文挑战第16天】 在移动开发领域,尤其是针对资源有限的Android设备,内存优化是提升应用性能和用户体验的关键因素。本文将深入探讨Android应用的内存管理机制,分析常见的内存泄漏问题,并提出一系列实用的内存优化技巧。通过这些策略的实施,开发者可以显著减少应用的内存占用,避免不必要的后台服务,以及提高垃圾回收效率,从而延长设备的电池寿命并确保应用的流畅运行。
|
5天前
|
搜索推荐 开发工具 Android开发
安卓即时应用(Instant Apps)开发指南
【4月更文挑战第14天】Android Instant Apps让用户体验部分应用功能而无需完整下载。开发者需将应用拆分成模块,基于已上线的基础应用构建。使用Android Studio的Instant Apps Feature Library定义模块特性,优化代码与资源以减小模块大小,同步管理即时应用和基础应用的版本。经过测试,可发布至Google Play Console,提升用户便利性,创造新获客机会。
|
6天前
|
Java API 调度
安卓多线程和并发处理:提高应用效率
【4月更文挑战第13天】本文探讨了安卓应用中多线程和并发处理的优化方法,包括使用Thread、AsyncTask、Loader、IntentService、JobScheduler、WorkManager以及线程池。此外,还介绍了RxJava和Kotlin协程作为异步编程工具。理解并恰当运用这些技术能提升应用效率,避免UI卡顿,确保良好用户体验。随着安卓技术发展,更高级的异步处理工具将助力开发者构建高性能应用。
|
6天前
|
编解码 人工智能 测试技术
安卓适配性策略:确保应用在不同设备上的兼容性
【4月更文挑战第13天】本文探讨了提升安卓应用兼容性的策略,包括理解平台碎片化、设计响应式UI(使用dp单位,考虑横竖屏)、利用Android SDK的兼容工具(支持库、资源限定符)、编写兼容性代码(运行时权限、设备特性检查)以及优化性能以适应低端设备。适配性是安卓开发的关键,通过这些方法可确保应用在多样化设备上提供一致体验。未来,自动化测试和AI将助力应对设备碎片化挑战。
|
12天前
|
移动开发 API Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第7天】 在移动开发领域,性能优化和应用响应性的提升一直是开发者追求的目标。近年来,Kotlin语言因其简洁性和功能性在Android社区中受到青睐,特别是其对协程(Coroutines)的支持,为编写异步代码和处理并发任务提供了一种更加优雅的解决方案。本文将探讨Kotlin协程在Android开发中的应用,揭示其在提高应用性能和简化代码结构方面的潜在优势,并展示如何在实际项目中实现和优化协程。