FileProvider的使用和注意

FileProvider使用注意:


<manifest>

 <application>

  <provider

android:name="android.support.v4.content.FileProvider"  //引用的FileProvider,if复写注意路径

android:authorities="applicationId .fileprovider"    

            android:exported="false"

            android:grantUriPermissions="true">

<meta-data

    android:name="android.support.FILE_PROVIDER_PATHS"

    android:resource="@xml/file_paths"/>

  </provider>

</application>

</manifest>

1.在java代码中传getUriForFile(Context context, String authority, File file)方法时,authority与清单文件的authorities名字一致

2.exported="false",grantUriPermissions="true"

3.file_paths 文件:

<resources>

   <paths xmlns:android="http://schemas.android.com/apk/res/android">

<external-path name="external"    path="" />
 这里可以创建很多个paths,但是每个paths的name不能一样

</resources>

适配:
安卓 8.0及以上: 需要声明权限


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

安卓7.0以下: if (Build.VERSION.SDK_INT< Build.VERSION_CODES.N)

Uri.fromFile(File);

安卓7.0以上: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

FileProvider.getUriForFile(context, applicationId + ".provider",File); //注意清单文件的authorities一样

path 说明:


  <files-path name="*name*" path="*path*" />   对应的是:Context.getFileDir()的路径地址

     对应路径:Context.getFileDir()+"/${path}/"
     得到路径:content://${applicationId}/&{name}/

     <cache-path name="*name*" path="*path*" />  
     对应路径:Context.getCacheFir()+"/${path}/"
     得到路径:content://${applicationId}/&{name}/


     <external-path name="*name*" path="*path*" />  
     对应路径:Environment.getExternalStorageDirectory()+"/${path}/"
     得到路径:content://${applicationId}/&{name}/

     <external-files-path name="*name*" path="*path*" />  
     对应路径:Context.getExternalStorageDirectory()+"/${path}/"
     得到路径:content://${applicationId}/&{name}/

     <external-cache-path name="*name*" path="*path*" />   
     对应路径: Context.getExternalCacheDir()+"/${path}/"
     得到路径:content://${applicationId}/&{name}/

eg:
path做如下声明


<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_images" path="images/"/>
</paths>

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);

contentUri值为:content://com.mydomain.fileprovider/my_images/default_image.jpg

分析:
ava.lang.SecurityException: Permission Denial:
opening provider android.support.v4.content.FileProvider from ProcessRecord{cc3ad2316425:
com.android.packageinstaller/u0a21} (pid=16425, uid=10021) that is not exported from uid 10340

安装Apk的service处于休眠或者不可用的状态,导致intent.addflags方式赋予的临时权限失效了。改进后的代码


public static void installApk(Context context,File apkFile){
        try {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            Uri apkUri = null;
            //判断版本是否是 7.0 及 7.0 以上
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                apkUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile);
                //添加对目标应用临时授权该Uri所代表的文件
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            } else {
                apkUri = Uri.fromFile(apkFile);
            }
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(apkUri,
                    "application/vnd.android.package-archive");
            //查询所有符合 intent 跳转目标应用类型的应用,注意此方法必须放置setDataAndType的方法之后
                    List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                    //然后全部授权
                    for (ResolveInfo resolveInfo : resInfoList) {
                        String packageName = resolveInfo.activityInfo.packageName;
                        context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    }        
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容