android n 代码 下载,Android N 7.0 以上系统的文件下载报错闪退解决

收到一个客户报过来的问题,换了新采购的设备之后,下载某个文件,然后下载完成之后就闪退。初步觉得应该是系统版本过高导致的权限问题。

后台查看报错日志

java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=com.xjj.cloud.ypjczd (has extras) }

Caused by: java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated; use ContentResolver.openFileDescriptor() instead

6df1cbcb8368

报错日志

原因是使用 DownloadManager.COLUMN_LOCAL_FILENAME 报错,看了下代码,这个已经过时了,源码推荐使用 ContentResolver 来获取文件名。

原来的代码

DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);

long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

DownloadManager.Query query = new DownloadManager.Query();

query.setFilterById(downId);

Cursor c = manager.query(query);

String filename = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));

使用 ContentResolver 之后

DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);

long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);

DownloadManager.Query query = new DownloadManager.Query();

query.setFilterById(downId);

Cursor c = manager.query(query);

String filename = "";

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {

int fileUriIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);

String fileUri = c.getString(fileUriIdx);

if (fileUri != null) {

filename = Uri.parse(fileUri).getPath();

}

} else {

//过时的方式:DownloadManager.COLUMN_LOCAL_FILENAME

int fileNameIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);

filename = c.getString(fileNameIdx);

}

获取文件名可以获取了,打开文件又报错。抛出异常

android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com./files/1529633205126858.pdf exposed beyond app through Intent.getData()

6df1cbcb8368

文件打开异常

因为之前直接 Uri.fromFile(apkFile) 构建出一个 Uri ,而这个 Uri 在 7.0 以上系统是不能用的,改使用 FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile);

原先打开文件的代码:

String extName = fileName.substring(fileName.lastIndexOf(".") + 1);

Intent intent = new Intent();

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setAction(Intent.ACTION_VIEW);

intent.addCategory("android.intent.category.DEFAULT");

File file = new File(fileName);

if (file.exists()) {

intent.setDataAndType(Uri.fromFile(file), getMIMEType(extName));

context.startActivity(intent);

} else {

Toast.makeText(context, "文件不存在", Toast.LENGTH_LONG).show();

}

改动之后

String extName = fileName.substring(fileName.lastIndexOf(".") + 1);

Intent intent = new Intent();

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setAction(Intent.ACTION_VIEW);

intent.addCategory("android.intent.category.DEFAULT");

File file = new File(fileName);

if (file.exists()) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

Uri contentUri = FileProvider.getUriForFile(context,

context.getApplicationContext().getPackageName() + ".fileprovider", file);

intent.setDataAndType(contentUri, getMIMEType(extName));

context.startActivity(intent);

} else {

intent.setDataAndType(Uri.fromFile(file), getMIMEType(extName));

context.startActivity(intent);

}

} else {

Toast.makeText(context, "文件不存在", Toast.LENGTH_LONG).show();

}

使用 FileProvider 要同时在配置文件中定义 FileProvider ,在application节点底下,与activity节点同级。添加如下代码

android:name="android.support.v4.content.FileProvider"

android:authorities="${applicationId}.provider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/provider_paths"/>

还要在 res 目录底下创建一个新的 provider_paths.xml 文件。因为我在 AndroidMenifest 文件中定义的目录是 xml/provider_paths.xml ,所以创建的 provider_paths.xml 文件放在 res/xml 目录底下。

这样子就可以在 Android N 7.0 以上系统正常下载文件以及打开文件了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值