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,如需转载请自行联系原作者
目录
相关文章
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
1395 4
|
5月前
|
存储 消息中间件 人工智能
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
425 10
【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡
|
10月前
|
存储 Android开发 数据安全/隐私保护
如何在Android设备上撤销Flutter应用程序的所有权限?
如何在Android设备上撤销Flutter应用程序的所有权限?
665 64
|
10月前
|
缓存 Android开发 开发者
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
1957 62
|
10月前
|
开发工具 Android开发 开发者
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
728 61
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
929 21
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
248 8
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
408 0
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。

热门文章

最新文章