APK自动安装——FileProvider

本文介绍如何使用Android FileProvider组件安全地在应用程序间共享文件。通过设置contentURL和临时权限,实现文件的安全传输。教程涵盖FileProvider配置及指定共享目录。

简介

app经常需要向其他应用提供一个或多个文件。例如,一个图片画廊可能要向图片编辑器提供文件,或者一个文件管理app需要允许使用者复制和粘贴文件到外部存储器中。一种方法是,发送端app可以通过接收端app的请求进行响应来共享一个文件。

在所有情况下,从你的app向其他app提供一个文件的唯一安全方式是,通过content URL 向接收端app发送这个文件,并且授权URL的临时访问权限。Content URLs 的临时 URL 访问权限是安全的,因为这个申请只对这个app接收 URL ,并且它会自动终止。Android 的FileProvider 组件提供了 getUriForFile() 方法,用来生成文件的 content URL 。

如果你想要在app之间分享一些文本或者数字数据,你应该发送一个包含数据data的 Intent 。想要学习怎么使用 Intent 发送简单的数据,请看培训教程:Sharing Simple Data.

这门课解释了如何安全地,从应用程序到另一个应用程序共享文件,使用Android FileProvider组件来生成的URI和临时权限授予接收应用程序内容URI。

前往课程:Setting Up File Sharing
这节课向你展示了如何为你的应用程序添加默认的FileProvider接口,以及如何指定你想提供给其他应用程的文件。

注意: FileProvider 类是v4包中的一部分,请确保你的应用包含这个库。

 

1. 指定 FileProvider

在manifest中为你的app定义一个FileProvider请求入口。该入口指定在生成内容uri时使用的权限,就像一个xml文件的名字一样,指定你app能分享的的目录。

下面的代码展示了怎么向你的manifest中添加<provider>元素,指定FileProvider类,权限和xml文件名字。

 

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
        ...>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.myapp.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
        ...
    </application>
</manifest> xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
        ...>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.myapp.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
        ...
    </application>
</manifest>

在这个例子中, android:authorities 属性指定了你想要通过FileProvide产生的 URL 权限。在这个例子中,权限是:com.example.myapp.fileprovider。

 

对于你自己的app,可以指定一个由app包名加上字符"fileprovider"拼接而成的权限。想要学习更多关于权限和android:authorities属性,请参考Content URIs

 

2.指定可分享的目录

一旦你添加了FileProvider到你的manifest中,你就需要指定包含了你想要分享的文件目录。为了指定目录,首先应该在你的工程中的 res/xml/ 子目录下创建filepaths.xml 文件。在这个文件中,通过为每个目录添加一个xml节点来指定目录。下面的片段展示了res/xml/filepaths.xml文件的内容。这个片段也示范了怎么分享一个你内置存储中的文件子目录。

 

<paths>
    <files-path path="images/" name="myimages" />
</paths>
    <files-path path="images/" name="myimages" />
</paths>

比如:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="aitoutiao"
        path="Android/data/com.example.myapp/" />
    <external-path
        name="external_storage_root"
        path="." />
</paths>

<files-path> 中指定了你app存储中的分享文件目录,path属性分配了files文件夹下面的iamges.子目录。name 属性告诉了FileProvider添加路径段在 files/images/子目录下的myimages到 content UIRs中,。

 

<paths>节点可以有多个子节点,来指定多个不同的分享目录。除了<files-path>节点之外,你可以使用<external-path>节点来分享外部存储中的目录, <cache-path> 节点可以分享内部缓存中的目录。

注意:XML 文件是你想要分享的唯一指定的目录,你不能以编程的方式来添加目录。

您现在拥有了一个完整规范的FileProvider,生成内容文件的uri文件,在应用程序的内部存储files/下或files/子目录下的文件。当你的app产生一个文件content URL时,应该在<provider>节点中指定权限,myimages/路径和文件的名字。

例如,如果你根据这篇课程中的片段定义了一个FileProvider,你为文件default_image.jpg请求一个content URL FileProvider,返回下面的URL:

content://com.example.myapp.fileprovider/myimages/default_image.jpg

 

获取URL:

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

3. 调启应用安装界面

添加权限:

<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
/**
     * 安装apk
     */
    public void installApk(Context context, String filePath) {
        File apkfile = new File(filePath);
        if (!apkfile.exists()) {
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(context, "com.example.myapp.fileProvider", apkfile);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        context.startActivity(intent);
        Log.e("tag", "apk正在安装...");
    }

注意报名一定要填写对了!

 

 

FileProvider API: https://developer.android.com/reference/android/support/v4/content/FileProvider.html

Sharing a File: https://developer.android.com/training/secure-file-sharing/share-file.html

Sending Simple Data to Other Apps:https: //developer.android.com/training/sharing/send.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值