Android 7.0下载安装APK

Android 7.0下载安装APK

这里只说安装,不说下载。因为下载网上一搜一大堆,暂且说下一下Android7.0 下载安装APK时的兼容性问题。

简介

随着Android版本越来越高,Android对隐私的保护力度也越来越大。
Android6.0引入的动态权限控制(Runtime Permissions),Android7.0又引入“私有目录被限制访问”,“StrictMode API 政策”。在7.0以后,谷歌加强了应用私有目录访问访问权限,当在执行上述代码会出现android.os.FileUriExposedException 错误。
对于这个异常描述有
1,对于面向 Android N 的应用,Android 框架执行的 StrictMode,API 禁止向您的应用外公开 file://URI。
如果一项包含文件 URI 的 Intent 离开您的应用,应用失败,并出现 FileUriExposedException异常。
2,若要在应用间共享文件,您应发送一项 content://URI,并授予 URI 临时访问权限。
进行此授权的最简单方式是使用 FileProvider类。 如需有关权限和共享文件的更多信息,所以提供了一下方法使用 FileProvider 解决

FileProvider的使用

第一步需要在AndroidManifest.xml文件中注册provider

在AndroidManifest.xml清单文件中注册provider,因为provider也是Android四大组件之一,可以简单把它理解为向外提供数据的组件,这种组件在实际开发中用的频率并不高,四大组件都可以在清单文件中进行配置。

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="keepservice.myapplication.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        provider>

按照惯例,我们也做一个说明:

1、android:authorities:官方说明为:包名+fileprovider
2、android:name:为包名,v4包下新增的类
3、android:resource:指向之前的xml文件
4、android:exported:要求必须为false,为true则会报安全异常。

引用官方解释如下:
这个属性用于指示该服务是否能够被其他应用程序组件调用或跟它交互。如果设置为true,则能够被调用或交互,否则不能。设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。
它的默认值依赖与该服务所包含的过滤器。没有过滤器则意味着该服务只能通过指定明确的类名来调用,这样就是说该服务只能在应用程序的内部使用(因为其他外部使用者不会知道该服务的类名),因此这种情况下,这个属性的默认值是false。另一方面,如果至少包含了一个过滤器,则意味着该服务可以给外部的其他应用提供服务,因此默认值是true。这个属性不是限制把服务暴露给其他应用程序的唯一方法。还可以使用权限来限制能够跟该服务交互的外部实体。

讲了一大推,答案就是false写死的!因为这是调用系统的安装界面,没有跟其他应用程序组件交互或者相互调用。
android:grantUriPermissions:true为授权url ,false为禁止

第二步:指定共享的目录

上面配置文件中 android:resource=”@xml/file_paths” 指的是当前组件引用 res/xml/file_paths.xml 这个文件。

我们需要在资源(res)目录下创建一个xml目录,然后创建一个名为“file_paths”(名字可以随便起,只要和在manifest注册的provider所引用的resource保持一致即可)的资源文件,内容如下:


<paths>
    <external-path path="" name="download" />
paths>

Android 7.0下载安装APK_第1张图片

files-path 代表的根目录: Context.getFilesDir()
external-path代表的根目录: Environment.getExternalStorageDirectory()
cache-path代表的根目录: getCacheDir()

上述代码中path=”“,是有特殊意义的,它代码根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了。

如果你将path设为path=”pictures”,name设置为download,那么它代表着根目录下的pictures目录(eg:/storage/emulated/0/pictures/download),如果你向其它应用分享pictures目录范围之外的文件是不行的。

第三步:代码中使用provide

上述准备工作做完之后,现在我们就可以使用FileProvider了。

private void installApk() {
        File apkfile = new File(mSavePath, "hyyunadmin.apk");
        if (!apkfile.exists())
        {
            return;
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        // 通过Intent安装APK文件
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ){

            Uri apkUri =
                    FileProvider.getUriForFile(MainActivity.this, "keepservice.myapplication.fileprovider", apkfile);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            MainActivity.this.startActivity(intent);
            System.exit(0);
        }else{

            intent.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive");
            MainActivity.this.startActivity(intent);
            System.exit(0);
        }
    }

1、intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) 来对目标应用临时授权该 Uri 所代表的文件,
2、而且 getUriForFile 中的 authority 参数需要填写清单文件中的 authorities 的值。也是就是:包名+fileprovider

源码下载

你可能感兴趣的:(Android 7.0下载安装APK)