美文网首页
Android FileProvider之应用安装

Android FileProvider之应用安装

作者: eagerabu | 来源:发表于2020-07-17 09:34 被阅读0次

    应用安装(FileProvider)

    应用内安装apk时涉及到通过Intent在两个应用间共享资源,Android 从 N 开始不允许以 file:// 的方式通过 Intent 在两个 App 之间分享文件,取而代之的是通过 FileProvider 生成 content://Uri,否则直接使用会抛出异常导致奔溃所以首先我们来了解一下FileProvider相关的知识。

    首先给出FileProvider的官方介绍https://developer.android.google.cn/reference/androidx/core/content/FileProvider

    FileProvider 是一个特殊的 ContentProvider 子类,通过 content://Uri 代替 file://Uri 实现不同 App 间的文件安全共享。当通过包含 Content URI 的 Intent 共享文件时,需要申请临时的读写权限,可以通过 Intent.setFlags() 方法实现。而 file://Uri 方式需要申请长期有效的文件读写权限,直到这个权限被手动改变为止,这是极其不安全的做法。因此 Android 从 N 版本开始禁止通过 file://Uri 在不同 App 之间共享文件。

    FileProvider的使用步骤:

    1,定义一个FileProvider
    2,指定可用的文件
    3,生成文件的Content URI
    4,给此URI授予临时权限
    5,将此Content URI通过Intent传递给另一个App

    接下来详细介绍
    1,定义FileProvider

       <provider
             android:name="android.support.v4.content.FileProvider"
             android:authorities="${applicationId}.fileprovider"
             android:exported="false"
             android:grantUriPermissions="true">
             <meta-data
                 android:name="android.support.FILE_PROVIDER_PATHS"
                 android:resource="@xml/provider_paths" />
         </provider>
        
         android:authorities:applicationId+fileProvider
    
         applicationId:这里写成动态获取应用包名,如果写死在项目包含多个moudle时出现不一致的情况
    
         android:exported="false":表示此provider是私有的不对其他应用公开
    
         android:grantUriPermissions="true":表示授予临时权限
    
         provider_paths:指定用来配置文件目录的xml文件,此处指定为provider_paths,名称可以自定义
    

    2,指定可用的文件provider_paths.xml

            <paths xmlns:android="http://schemas.android.com/apk/res/android">
                <!--相当于Context.getFilesDir()-->
                <files-path name="name" path="path" />
    
                <!--相当于Context. getCacheDir()-->
                <cache-path name="name" path="path" />
    
                <!--相当于Environment.getExternalStorageDirectory()-->
                <external-path name="name" path="path" />
    
                
                <!--相当于Context.getExternalFilesDir(String) Context.getExternalFilesDir(null).-->
                <external-files-path name="name" path="path" />
                
                <!--相当于Context.getExternalCacheDir()-->
                <external-cache-path name="name" path="path" />
    
                <!--相当于Context.getExternalMediaDirs()-->
                <external-media-path name="name" path="path" />
                ...
            </paths>
    

    注意:这里只需配置自己文件所保存的path即可,name为别名影藏实际名称,path为实际的文件路径如果对Android文件存储这块知识不太了解可以看一下另一篇介绍:https://www.jianshu.com/p/88dbdd8613db

    3,生成文件的Content URI

    完成了前两步的配置,接下来通过官方提供的getUriForFile(File file) 方法生成能够被其他应用访问的Content URI加入有一个apk文件路径为磁盘根目录则相应文件对象为

    File file = new File("/sdcard/app.apk");
    

    此文件对应的可通过如下方式获得uri

           Uri uri=FileProvider.getUriForFile(FaceTempratureActivity.this, BuildConfig.APPLICATION_ID + ".provider", file); 
    

    获取到Uri后我们将通过Intent将此Uri传递给另一个应用,此处定义一个Intent

           Intent intent = new Intent(Intent.ACTION_VIEW);
           intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
           intent.setDataAndType(uri,"application/vnd.android.package-archive");
    

    4,给此URI授予临时权限
    有了可访问的Uri路径我们还得申请临时读写文件权限,这里可以直接通过Intent.setFlags()方法设置

    intent.addFlags(
    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    

    5,将此Content URI通过Intent传递给另一个App

    statActivity(intent);
    

    最后给出一个应用安装的示例:

       private void installApp(Content content) {
           File fileS = new File("/sdcard/temp.apk");
           Uri data;
           Intent intent = new Intent(Intent.ACTION_VIEW);
           intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
           if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
               // 给目标应用一个临时授权
               intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
               data = FileProvider.getUriForFile(content, BuildConfig.APPLICATION_ID + ".provider", fileS);
           } else {
               data = Uri.fromFile(fileS);
           }
           intent.setDataAndType(data, "application/vnd.android.package-archive");
           startActivity(intent);
       }
    

    相关文章

      网友评论

          本文标题:Android FileProvider之应用安装

          本文链接:https://www.haomeiwen.com/subject/lfmwhktx.html