Step 17. ActivityThread.installProvider
这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
-
public final class ActivityThread {
-
......
-
-
private final IContentProvider installProvider(Context context,
-
IContentProvider provider, ProviderInfo info, boolean noisy) {
-
ContentProvider localProvider = null;
-
if (provider == null) {
-
......
-
-
Context c = null;
-
ApplicationInfo ai = info.applicationInfo;
-
if (context.getPackageName().equals(ai.packageName)) {
-
c = context;
-
} else if (mInitialApplication != null &&
-
mInitialApplication.getPackageName().equals(ai.packageName)) {
-
c = mInitialApplication;
-
} else {
-
try {
-
c = context.createPackageContext(ai.packageName,
-
Context.CONTEXT_INCLUDE_CODE);
-
} catch (PackageManager.NameNotFoundException e) {
-
}
-
}
-
-
......
-
-
try {
-
final java.lang.ClassLoader cl = c.getClassLoader();
-
localProvider = (ContentProvider)cl.
-
loadClass(info.name).newInstance();
-
provider = localProvider.getIContentProvider();
-
......
-
-
// XXX Need to create the correct context for this provider.
-
localProvider.attachInfo(c, info);
-
} catch (java.lang.Exception e) {
-
......
-
}
-
-
} else if (localLOGV) {
-
......
-
}
-
-
synchronized (mProviderMap) {
-
// Cache the pointer for the remote provider.
-
String names[] = PATTERN_SEMICOLON.split(info.authority);
-
for (int i=0; i<names.length; i++) {
-
ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,
-
localProvider);
-
try {
-
provider.asBinder().linkToDeath(pr, 0);
-
mProviderMap.put(names[i], pr);
-
} catch (RemoteException e) {
-
return null;
-
}
-
}
-
if (localProvider != null) {
-
mLocalProviders.put(provider.asBinder(),
-
new ProviderClientRecord(null, provider, localProvider));
-
}
-
}
-
-
return provider;
-
}
-
-
......
-
}
这个函数的作用主要就是在应用程序进程中把相应的Content Provider类加载进来了,在我们这个种情景中,就是要在ArticlesProvider这个应用程序中把ArticlesProvider这个Content Provider类加载到内存中来了:
-
final java.lang.ClassLoader cl = c.getClassLoader();
-
localProvider = (ContentProvider)cl.
-
loadClass(info.name).newInstance();
接着通过调用localProvider的getIContentProvider函数来获得一个Binder对象,这个Binder对象返回给installContentProviders函数之后,就会传到ActivityManagerService中去,后续其它应用程序就是通过获得这个Binder对象来和相应的Content Provider进行通信的了。我们先看一下这个函数的实现,然后再回到installProvider函数中继续分析。
Step 18. ContentProvider.getIContentProvider
这个函数定义在frameworks/base/core/java/android/content/ContentProvider.java文件中:
-
public abstract class ContentProvider implements ComponentCallbacks {
-
......
-
-
private Transport mTransport = new Transport();
-
-
......
-
-
class Transport extends ContentProviderNative {
-
......
-
}
-
-
public IContentProvider getIContentProvider() {
-
return mTransport;
-
}
-
-
......
-
}
从这里我们可以看出,ContentProvider类和Transport类的关系就类似于ActivityThread和ApplicationThread的关系,其它应用程序不是直接调用ContentProvider接口来访问它的数据,而是通过调用它的内部对象mTransport来间接调用ContentProvider的接口,这一点我们在下一篇文章中分析调用Content Provider接口来获取共享数据时将会看到。
回到前面的installProvider函数中,它接下来调用下面接口来初始化刚刚加载好的Content Provider:
回到前面的installProvider函数中,它接下来调用下面接口来初始化刚刚加载好的Content Provider:
-
// XXX Need to create the correct context for this provider.
-
localProvider.attachInfo(c, info);
同样,我们先进入到ContentProvider类的attachInfo函数去看看它的实现,然后再回到installProvider函数来。
Step 19. ContentProvider.attachInfo
这个函数定义在frameworks/base/core/java/android/content/ContentProvider.java文件中:
-
public abstract class ContentProvider implements ComponentCallbacks {
-
......
-
-
public void attachInfo(Context context, ProviderInfo info) {
-
/*
-
* Only allow it to be set once, so after the content service gives
-
* this to us clients can't change it.
-
*/
-
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();
-
}
-
}
-
-
......
-
}
这个函数很简单,主要就是根据这个Content Provider的信息info来设置相应的读写权限,然后调用它的子类的onCreate函数来让子类执行一些初始化的工作。在我们这个情景中,这个子类就是ArticlesProvide应用程序中的ArticlesProvider类了。
Step 20. ArticlesProvider.onCreate
这个函数定义在前面一篇文章Android应用程序组件Content Provider应用实例介绍的应用程序ArtilcesProvider源代码工程目录下,在文件为packages/experimental/ArticlesProvider/src/shy/luo/providers/articles/ArticlesProvider.java中:
-
public class ArticlesProvider extends ContentProvider {
-
......
-
-
@Override
-
public boolean onCreate() {
-
Context context = getContext();
-
resolver = context.getContentResolver();
-
dbHelper = new DBHelper(context, DB_NAME, null, DB_VERSION);
-
-
return true;
-
}
-
-
......
-
}
这个函数主要执行一些简单的工作,例如,获得应用程序上下文的ContentResolver接口和创建数据库操作辅助对象,具体可以参考前面一篇文章Android应用程序组件Content Provider应用实例。
回到前面Step 17中的installProvider函数中,它接下来就是把这些在本地中加载的Content Provider信息保存下来了,以方便后面查询和使用:
-
synchronized (mProviderMap) {
-
// Cache the pointer for the remote provider.
-
String names[] = PATTERN_SEMICOLON.split(info.authority);
-
for (int i=0; i<names.length; i++) {
-
ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,
-
localProvider);
-
try {
-
provider.asBinder().linkToDeath(pr, 0);
-
mProviderMap.put(names[i], pr);
-
} catch (RemoteException e) {
-
return null;
-
}
-
}
-
if (localProvider != null) {
-
mLocalProviders.put(provider.asBinder(),
-
new ProviderClientRecord(null, provider, localProvider));
-
}
-
}
和ActivityMangerService类似,在ActivityThread中,以Content Provider的authority为键值来把这个Content Provider的信息保存在mProviderMap成员变量中,因为一个Content Provider可以对应多个authority,因此这里用一个for循环来处理,同时又以这个Content Provider对应的Binder对象provider来键值来把这个Content Provider的信息保存在mLocalProviders成员变量中,表明这是一个在本地加载的Content Provider。
本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966989,如需转载请自行联系原作者