解决Couldn‘t find meta-data for provider with authority

今天在复用之前写的安装APK的相关代码时发生了报错,那是因为安卓高版本需要新增FileProvider

新增file_paths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--    <root-path
            name="root"
            path="" />-->
    <files-path
        name="files"
        path="files" />
    <cache-path
        name="cache"
        path="files" />
<!--    <external-path
        name="external"
        path="files" />-->
    <external-files-path
        name="externalfiles"
        path="files" />
    <!-- 此标签需要 support 25.0.0以上才可以使用-->
    <external-cache-path
        name="externalcache"
        path="files" />
    <external-path
        name="external_storage_root"
        path="." />

</paths>

其他写法

    <root-path name="root" path="."/>
    <files-path name="files" path="." />
    <cache-path name="cache" path="." />
    <external-path name="external" path="." />
    <external-files-path name="name" path="path" />
    <external-cache-path name="name" path="path" />

标签对应的地址

<files-path name="name" path="path" />             物理路径相当于Context.getFilesDir() + /path/
<cache-path name="name" path="path" />             物理路径相当于Context.getCacheDir() + /path/
<external-path name="name" path="path"/>          

物理路径相当于Environment.getExternalStorageDirectory() + /path/
<external-files-path name="name" path="path" />    

物理路径相当于**Context.getExternalFilesDir(String) **+ /path/
<external-cache-path name="name" path="path" />  

 物理路径相当于Context.getExternalCacheDir() + /path/
<root-path name="name" path="path" />              物理路径相当于/path/
举例:


<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!-- /storage/emulated/0/Android/data/com.test.dust/files/resources/map/tiles/1.0.8.rar  
	===>     content://com.test.dust.provider/map_tiles/1.0.8.rar-->
    <external-files-path
        name="map_tiles"
        path="resources/map/tiles" />
</paths>

external-files-path对应的文件路径为/storage/emulated/0/Android/data/[packageName]/files
整个external-files-path标签的作用相当于把绝对路径/storage/emulated/0/Android/data/[packageName]/files/[path]/filename格式化为content://[authorities]/[name]/filename的形式。
 

新增provider
在Manifest.xml的<application>中新增如下代码

    <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.utilcode.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

引用

APK安装

    public static  void installApk(Context context,String downloadApk) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        File file = new File(downloadApk);
        //L.i("安装路径=="+downloadApk);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Uri apkUri = FileProvider.getUriForFile
(Objects.requireNonNull(context), BuildConfig.APPLICATION_ID + 
BuildConfig.APPLICATION_ID + ".utilcode.fileProvider", file);//这句很重要
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            Uri uri = Uri.fromFile(file);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        }
        context.startActivity(intent);

    }

适配

    private void installApp() {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        File file = new File(FileUtils.mkdirs(DirKeys.DIR_APP_UPDATE) + "/test.apk");
        Uri apkUri = FileProvider.getUriForFile(this,
                BuildConfig.APPLICATION_ID + ".utilcode.fileProvider", file);//这句很重要
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            LogUtils.e("lcb", "sdk:" + Build.VERSION.SDK_INT + "走了这");
            intent.setAction(Intent.ACTION_INSTALL_PACKAGE);
            intent.setData(apkUri);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
            intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
            intent.putExtra(Intent.EXTRA_ALLOW_REPLACE, true);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            Uri uri = Uri.fromFile(file);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        }
        startActivity(intent);
    }

android11调用相机

项目中需要使用到相机代码如下:

public static void startCarmera(Fragment fragment) {
    Uri uri;
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        uri = FileProvider.getUriForFile(fragment.getActivity(), 
BuildConfig.APPLICATION_ID + ".utilcode.fileProvider", getFile());
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    } else {
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getFile()));
    }
    fragment.startActivityForResult(intent, RESULT_CAMERA);
}

    File newFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
            + "/images/" + System.currentTimeMillis() + ".jpg");
    if (!newFile.exists()) {
        newFile.getParentFile().mkdirs();
    }
    mCurrentPhotoPath = newFile.getAbsolutePath();
    return newFile;
}

项目中需要使用到相册代码如下:

public static void startGallery(Activity activity) {
    Intent intentGallery = new Intent(Intent.ACTION_PICK, 
	android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    activity.startActivityForResult(intentGallery, RESULT_GALLERY);
}

onActivityResult()中处理接收返回的图片:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
       if (requestCode == RESULT_CAMERA) {
            upload(CarmeraUtil.mCurrentPhotoPath);
        } else if (requestCode == RESULT_GALLERY && data != null) {
            //处理来自图库的照片
            Uri selectedImage = data.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String picturePath = cursor.getString(columnIndex);
            cursor.close();
            upload(picturePath);
        }
    }
}

切记添加安装权限

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值