我正在尝试访问LauncherProvider
。您可以找到其源代码here
我试图这样查询ContentProvider
:
Uri uri = new Uri.Builder().scheme("content").authority("com.android.launcher.settings").appendPath("favorites").build();
String[] projection = new String[]{
"_id", "title", "intent", "container", "screen", "cellX", "cellY",
"spanX", "spanY", "itemType", "appWidgetId", "isShortcut", "iconType",
"iconPackage", "iconResource", "icon", "uri", "displayMode"
};
String selection = null;
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor query = getActivity().getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
if (query != null) {
while (query.moveToNext()) {
Log.d(TAG, query.getString(2));
}
}
if (query != null) {
query.close();
}
但是我得到的
Cursor
总是null
!这是我在logcat中得到的错误:07-31 15:55:14.703 24773-24773/x.y.z.testE/ActivityThread﹕ Failed to find provider info for com.android.launcher.settings
有人可以告诉我我在做什么错吗?
最佳答案
问题说明
您正在尝试访问LauncherProvider
,但这可能并不容易。主要有两个问题:
LauncherProvider具有两个权限:com.android.launcher.permission.READ_SETTINGS
从中读取。com.android.launcher.permission.WRITE_SETTINGS
写入。
不同的OEM会编写自己的LauncherProvider
版本,其权限可能有所不同!在不同版本的Android上,权限也可能不同。例如,在我的Nexus 5上,正确提供商的权限为com.android.launcher3.settings
。
声明权限当然不是问题,但是找到正确的ContentProvider
可能会很困难,幸运的是,有解决方案!
解
您首先必须在清单中声明所有必需的权限,如下所示:
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
之后,我们需要找到正确的提供者!您可以通过读取所有已安装应用程序的
PackageInfo
并循环浏览每个应用程序的所有ContentProviders
来实现。我们正在寻找具有ContentProvider
和READ_SETTINGS
作为读和写权限的WRITE_SETTINGS
。但是,由于权限通常基于程序包名称,因此我们需要更复杂的逻辑来找到正确的逻辑。public static String findLauncherProviderAuthority(Context context) {
// Gets PackageInfo about all installed apps
final List<PackageInfo> packs = context.getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS);
if (packs == null) {
return null;
}
for (PackageInfo pack : packs) {
// This gets the ProviderInfo of every ContentProvider in that app
final ProviderInfo[] providers = pack.providers;
if (providers == null) {
continue;
}
// This loops through the ContentProviders
for (ProviderInfo provider : providers) {
// And finally we look for the one with the correct permissions
// We use `startsWith()` and `endsWith()` since only the middle
// part might change
final String readPermission = provider.readPermission;
final String writePermission = provider.writePermission;
if(readPermission != null && writePermission != null) {
final boolean readPermissionMatches = readPermission.startsWith("com.android.") && readPermission.endsWith(".permission.READ_SETTINGS");
final boolean writePermissionMatches = writePermission.startsWith("com.android.") && writePermission.endsWith(".permission.WRITE_SETTINGS");
if(readPermissionMatches && writePermissionMatches) {
// And if we found the right one we return the authority
return provider.authority;
}
}
}
}
return null;
}
因此,这应该非常可靠地返回正确的
ContentProvider
!如果您在某些设备上遇到问题,则可能需要稍微调整一下,但是在所有我可以测试的设备(以及很多设备)上,它都可以正常工作。您可以这样使用上面的方法:final String authority = findLauncherProviderAuthority(getActivity());
final Uri uri = new Uri.Builder().scheme(CONTENT).authority(authority).appendPath(PATH).build();
...
希望我能为您提供帮助,如果您还有其他疑问,请随时提出!