android.content.res.XmlResourceParser错误

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Maiduoudo/article/details/82621554

项目中配置FileProvider,运行报错android.content.res.XmlResourceParser错误。

详细错误信息:

Attempt to invoke virtual method 'android.content.res.XmlResourceParser 
android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager,java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:583)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:557)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:399)

Debug调试

根据报错的代码,最后锁定在FileProvider#parsePathStrategy()中,其源码如下:

private static PathStrategy parsePathStrategy(Context context, String authority)throws IOException, XmlPullParserException {
    final SimplePathStrategy strat = new SimplePathStrategy(authority);
    final ProviderInfo info = context.getPackageManager().resolveContentProvider(authority, PackageManager.GET_META_DATA);
    final XmlResourceParser in = info.loadXmlMetaData(context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS);
    if (in == null) {
        throw new IllegalArgumentException("Missing " + META_DATA_FILE_PROVIDER_PATHS + " meta-data");
    }

// ............

return strat;

}

debug调试发现,源码中的info对象为空,因此推断出authority有问题,没有找到。既然authority不存在,肯定是配置有问题。

查找配置

先查看AndroidManifest.xml中FileProvider配置:

<!-- FileProvider配置访问路径,适配7.0及其以上 -->
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

在查看调用时候,在 FileProvider.getUriForFile()中传入的authorities:

 FileProvider.getUriForFile(context.getApplicationContext(), BuildConfig.APPLICATION_ID+".provider",new File(picturePath))

这就奇怪了,感觉没错呀。 这时候,很大可能就是导入BuildConfig错误了,查看导入包。

package xingencom.easypermissiondemo.utils;
import android.support.v4.BuildConfig;

果然如此,错误导入v4包下的BuildConfig。这导致配置的authority与传入的authority不一样,当然会报错的啦。

正确的做法

导入自己项目的包下的BuildConfig。

//导入自己项目的包

import com.xingen.easypermissiondemo.BuildConfig;
FileProvider.getUriForFile(context.getApplicationContext(), BuildConfig.APPLICATION_ID+".provider",new File(picturePath))

如果以上内容不能有效解决问题,在获取authority

uri = FileProvider.getUriForFile(activity, Constants.FileProviderName, takeImageFile);
/**
     * Return a content URI for a given {@link File}. Specific temporary
     * permissions for the content URI can be set with
     * {@link Context#grantUriPermission(String, Uri, int)}, or added
     * to an {@link Intent} by calling {@link Intent#setData(Uri) setData()} and then
     * {@link Intent#setFlags(int) setFlags()}; in both cases, the applicable flags are
     * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and
     * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}. A FileProvider can only return a
     * <code>content</code> {@link Uri} for file paths defined in their <code>&lt;paths&gt;</code>
     * meta-data element. See the Class Overview for more information.
     *
     * @param context A {@link Context} for the current component.
     * @param authority The authority of a {@link FileProvider} defined in a
     *            {@code <provider>} element in your app's manifest.
     * @param file A {@link File} pointing to the filename for which you want a
     * <code>content</code> {@link Uri}.
     * @return A content URI for the file.
     * @throws IllegalArgumentException When the given {@link File} is outside
     * the paths supported by the provider.
     */
    public static Uri getUriForFile(Context context, String authority, File file) {
        final PathStrategy strategy = getPathStrategy(context, authority);
        return strategy.getUriForFile(file);
    }

我们可以在全局文件中写成静态的文件:

public  static String FileProviderName = "${你自己的包名}$.provider";//provider

之前的做法是动态获取authority:

/**
 * 用于解决provider冲突的util
 */
public class ProviderUtil {
    public static String getFileProviderName(Context context){
        return context.getPackageName()+".provider";
    }
}

静态文件配置也可以解决冲突问题。

猜你喜欢

转载自blog.csdn.net/Maiduoudo/article/details/82621554