Android FileProvider之应用安装

应用安装(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文件存储这块知识不太了解可以看一下另一篇介绍:http://08643.cn/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);
   }
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351