Android ContentProvider Unknown authority 问题

1
java.lang.IllegalArgumentException: Unknown authority com.example.myprovider

从字面意思理解是没有找到特定的 ContentProvider。

一般定义 ContentProvider 如下:

1
2
3
4
<provider
android:name=".MyProvider"
android:authorities="com.example.myprovider"
android:exported="true" />

当调用如下代码时出错:

1
2
3
4
private fun callMethodInstaller(context: Context, extras: Bundle?): Bundle? {
val uri = Uri.parse("content://com.example.provider")
return context.contentResolver.call(uri, "myMethod", null, extras)
}

源码分析,以 Android 11.0(R/api-30) 为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public final Bundle call(String authority, String method,
String arg, Bundle extras) {
IContentProvider provider = acquireProvider(authority);
if (provider == null) {
throw new IllegalArgumentException("Unknown authority " + authority);
}
try {
final Bundle res = provider.call(mPackageName, authority, ...);
Bundle.setDefusable(res, true);
return res;
} catch (RemoteException e) {
return null;
} finally {
releaseProvider(provider);
}
}
  1. 如果获取不到 provider 就会抛出异常;
  2. 调用 provider 的方法,返回结果;
  3. 最后释放 provider;

acquireProvider 会调用到 ContextImpl.ApplicationContentResolver#acquireProvider() 方法:

1
2
3
4
5
protected IContentProvider acquireProvider(Context context, String auth) {
return mMainThread.acquireProvider(context,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), true);
}

再调用 ActivityThread#acquireProvider() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
if (provider != null) {
return provider;
}

// There is a possible race here.
ContentProviderHolder holder = null;
try {
synchronized (getGetProviderLock(auth, userId)) {
holder = ActivityManager.getService().getContentProvider(
getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
if (holder == null) {
if (UserManager.get(c).isUserUnlocked(userId)) {
Slog.e(TAG, "Failed to find provider info for " + auth);
} else {
Slog.w(TAG, "Failed to find provider info for " + auth + " (user not unlocked)");
}
return null;
}

// Install provider will increment the reference count for us, and break
// any ties in the race.
holder = installProvider(c, holder, holder.info,...);
return holder.provider;
}

public final IContentProvider acquireExistingProvider(
Context c, String auth,...) {
synchronized (mProviderMap) {
final ProviderKey key = new ProviderKey(auth, userId);
final ProviderClientRecord pr = mProviderMap.get(key);
if (pr == null) {
return null;
}

// ...

ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
incProviderRefLocked(prc, stable);
}
return provider;
}
}
  1. 查找 provider 是否存在,如果已存在直接返回;
  2. 如果不存在,则通过 AMS 查找符合条件的 provider;
  3. AMS 没找到返回 null;否则安装 provider;