Android6.0+ apk下载及安装出现的权限问题

1、下载apk创建流时出现错误:java.io.FileNotFoundException: /storage/emulated/0/app/update/main.apk (Permission denied)

public static File getFileFromServer(String path, ProgressDialog pd) throws Exception {
        //如果相等的话表示当前的sdcard挂载在手机上并且是可用的    
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            //获取到文件的大小     
            pd.setMax(conn.getContentLength());
            InputStream is = conn.getInputStream();
            File file = new File(Environment.getExternalStorageDirectory() + app/update + "/", "main.apk");

            FileOutputStream fos = new FileOutputStream(file);//写入字节流
            BufferedInputStream bis = new BufferedInputStream(is);
            byte[] buffer = new byte[1024];
            int len;
            int total = 0;
            while ((len = bis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
                total += len;
                //获取当前下载量    
                pd.setProgress(total);
            }
            fos.close();
            bis.close();
            is.close();
            return file;
        } else {
            return null;
        }
    }

这个报错出现在以上代码中的写入字节流步骤。导致这个的原因是android6.0以后对权限的控制更严格了,我们仅在Manifest文件中添加这两个权限是不够的,需要动态申请权限。

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
a、一种方法 在读写之前加入以下代码

        int REQUEST_EXTERNAL_STORAGE = 1;
        String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
        int permission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    MainActivity.this,
                    PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE
            );
        }   



2、7.0安装apk时报错提示:android.os.FileUriExposedException: file:///storage/emulated/0/app/update/main.apk exposed beyond app through Intent.getData()

	    intent.setAction(Intent.ACTION_VIEW);
	    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
	    //执行的数据类型   
	    intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");//
	    context.startActivity(intent);

报错在Uri.fromFile这个方法上。7.0为了提高安全性,添加了这种私有目录访问限制,此举是为了提高私有文件的安全性,面向 Android N 或更高版本的应用私有目录将被限制访问。这里就需要了解FileProvider这个类了。provider是android的一大组件,FileProvider顾名思义就是类似一个文件共享接口。还是在此代码基础上我们来用这个实现7.0+的安装

a.首先  增加一个xml文件夹在res下,然后新建一个xml文件,名字如pathlist.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path
            name="external_storage_root"
            path="."/>
    </paths>
</resources>

其中paths节点就是可访问的路径列表,external-path是路径,是一个关键字。这里的.代表了 Environment.getExternalStorageDirectory()。
如果你将path设为path="app",那么它代表着根目录下的app目录(/storage/emulated/0/app)

b.接着 在AndroidManifest.xml清单文件中注册provider。

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.kz.target.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/pathlist"/>
        </provider>

这里的resource就是上面增加的pathlist.xml文件,名字注意一致。这里面重要的是authorities标识,名字你可以换成任意字符串。

c.使用FileProvider

        Intent intent = new Intent(Intent.ACTION_VIEW);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            String authority = context.getPackageName() + ".provider"; //注意名字和注册的authorities一致
            Uri contentUri = FileProvider.getUriForFile(context, authority, file);
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android" +
                    ".package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        context.startActivity(intent);



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值