我正在尝试访问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来实现。我们正在寻找具有ContentProviderREAD_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();
...


希望我能为您提供帮助,如果您还有其他疑问,请随时提出!

10-06 03:30