【我的Android进阶之旅】Android 7.0报异常:java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated;

5423人阅读 评论(3) 收藏 举报
分类:

之前开发的一个和第三方合作的apk,在之前公司的 Android 5.1 系统的手表上运行正常,今天在公司新开发的 Android 7.1系统的手表上运行的时候,使用 DownloadManager 下载之后,查询下载状态的时候,报了异常

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

异常详细信息如下:

03-17 15:59:43.288 31487-31487/com.netease.xtc.cloudmusic E/CloudMusicDownloadService: DownloadChangeObserver.onChange() throwable = java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated; use ContentResolver.openFileDescriptor() instead
                                                                                           at android.app.DownloadManager$CursorTranslator.getString(DownloadManager.java:1545)
                                                                                           at com.netease.xtc.cloudmusic.services.download.CloudMusicDownloadService.queryDownloadStatus(CloudMusicDownloadService.java:634)
                                                                                           at com.netease.xtc.cloudmusic.services.download.CloudMusicDownloadService.access$900(CloudMusicDownloadService.java:55)
                                                                                           at com.netease.xtc.cloudmusic.services.download.CloudMusicDownloadService$DownloadChangeObserver$3.call(CloudMusicDownloadService.java:590)
                                                                                           at com.netease.xtc.cloudmusic.services.download.CloudMusicDownloadService$DownloadChangeObserver$3.call(CloudMusicDownloadService.java:587)
                                                                                           at rx.Observable.unsafeSubscribe(Observable.java:8666)
                                                                                           at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
                                                                                           at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:220)
                                                                                           at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
                                                                                           at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
                                                                                           at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                           at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
                                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                                           at java.lang.Thread.run(Thread.java:761)

跳转到报错的地方,如下图所示:
这里写图片描述

在运行下面两行代码的时候报错了。

  int fileNameIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
  String fileName = c.getString(fileNameIdx);

而且 DownloadManager.COLUMN_LOCAL_FILENAME 已经是被废弃的常量了,点击查看源代码如下所示:

 /**
     * Path to the downloaded file on disk.
     * <p>
     * Note that apps may not have filesystem permissions to directly access
     * this path. Instead of trying to open this path directly, apps should use
     * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain access.
     *
     * @deprecated apps should transition to using
     *             {@link ContentResolver#openFileDescriptor(Uri, String)}
     *             instead.
     */
    @Deprecated
    public final static String COLUMN_LOCAL_FILENAME = "local_filename";

Android 在 Android 7.0 或更高版本开发的应用在尝试访问DownloadManager.COLUMN_LOCAL_FILENAME 时会触发java.lang.SecurityException。

Android官方建议我们使用 ContentResolver#openFileDescriptor(Uri, String)来获取文件相关信息。源代码如下所示:

 /**
     * Open a raw file descriptor to access data under a URI.  This
     * is like {@link #openAssetFileDescriptor(Uri, String)}, but uses the
     * underlying {@link ContentProvider#openFile}
     * ContentProvider.openFile()} method, so will <em>not</em> work with
     * providers that return sub-sections of files.  If at all possible,
     * you should use {@link #openAssetFileDescriptor(Uri, String)}.  You
     * will receive a FileNotFoundException exception if the provider returns a
     * sub-section of a file.
     *
     * <h5>Accepts the following URI schemes:</h5>
     * <ul>
     * <li>content ({@link #SCHEME_CONTENT})</li>
     * <li>file ({@link #SCHEME_FILE})</li>
     * </ul>
     *
     * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information
     * on these schemes.
     * <p>
     * If opening with the exclusive "r" or "w" modes, the returned
     * ParcelFileDescriptor could be a pipe or socket pair to enable streaming
     * of data. Opening with the "rw" mode implies a file on disk that supports
     * seeking. If possible, always use an exclusive mode to give the underlying
     * {@link ContentProvider} the most flexibility.
     * <p>
     * If you are writing a file, and need to communicate an error to the
     * provider, use {@link ParcelFileDescriptor#closeWithError(String)}.
     *
     * @param uri The desired URI to open.
     * @param mode The file mode to use, as per {@link ContentProvider#openFile
     * ContentProvider.openFile}.
     * @return Returns a new ParcelFileDescriptor pointing to the file.  You
     * own this descriptor and are responsible for closing it when done.
     * @throws FileNotFoundException Throws FileNotFoundException if no
     * file exists under the URI or the mode is invalid.
     * @see #openAssetFileDescriptor(Uri, String)
     */
    public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
            @NonNull String mode) throws FileNotFoundException {
        return openFileDescriptor(uri, mode, null);
    }

这里写图片描述

查看Android 官方文档,关于Android 7.0 的权限管理更改,如下图所示:

参考链接为:
https://developer.android.google.cn/about/versions/nougat/android-7.0-changes.html#sharing-files

这里写图片描述

因此为了解决这个异常,我们有以下两个方法解决。

方法一、使用 ContentResolver#openFileDescriptor(Uri, String)来替代访问由 DownloadManager 公开的文件。

方法二、使用DownloadManager.COLUMN_LOCAL_URI查出文件Uri,然后使用Uri new一个File,再获取File的相关信息,如下所示:

int fileUriIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String fileUri = c.getString(fileUriIdx);
String fileName = null;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
    if (fileUri != null) {
        fileName = Uri.parse(fileUri).getPath();
    }
} else {
    //Android 7.0以上的方式:请求获取写入权限,这一步报错
    //过时的方式:DownloadManager.COLUMN_LOCAL_FILENAME
    int fileNameIdx = c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
    fileName = c.getString(fileNameIdx);
}

运行之后,不会报错,并且能够获取到正常的文件名。

参考链接
1. https://developer.android.google.cn/about/versions/nougat/android-7.0-changes.html#sharing-files
2. http://www.cnblogs.com/dazhao/p/6547811.html
3. http://www.jianshu.com/p/56b9fb319310


作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址: http://blog.csdn.net/ouyang_peng/article/details/62891782

这里写图片描述

查看评论

Android6.0中设置权限时候的SecurityException异常的处理

说来也巧了,今天碰到了一个特别奇怪的问题。上午写了一个小demo其中有一个功能是获取通讯的,大家肯定知道这时候肯定要添加一个权限: 添加完后就开始运行了,竟然报错了, ...
  • njweiyukun
  • njweiyukun
  • 2015-11-25 23:18:55
  • 11470

Android 6.0 SecurityException: Permission Denial

在写一个群发短信APP时涉及到获取系统的联系人信息,添加联系人的事件为下:mBtAdd.setOnClickListener(new View.OnClickListener() { ...
  • yhaolpz
  • yhaolpz
  • 2016-05-01 13:56:00
  • 9648

有关Android 6.0权限问题java.lang.SecurityException: Permission Denial

http://www.jianshu.com/p/e1ab1a179fbbhttp://www.tuicool.com/articles/fMZ7Vvr看网址
  • sinat_35541927
  • sinat_35541927
  • 2016-08-25 16:18:23
  • 3846

JAVA刚碰见的问题( java.lang.SecurityException: The jurisdiction policy files are not signed by a trusted s

1.  failed to load the jni shared library jre bin server jvm.dll           解决:这个主要是eclipse的版本和安...
  • gebitan505
  • gebitan505
  • 2016-07-04 14:47:06
  • 4135

java.lang.SecurityException: Permission Denial

原文链接:http://yelinsen.iteye.com/blog/977683 我们经常在一个activity中去start另一个activity,或者与另一个acitivity的结果进行交互...
  • hey_piggy
  • hey_piggy
  • 2016-04-26 21:03:09
  • 8014

Caused by: java.lang.SecurityException

01-02 03:56:52.751  6767  7344 E SurfaceFlinger: Permission Denial: can't access SurfaceFlinger pid=...
  • lei7143
  • lei7143
  • 2017-12-29 11:53:03
  • 289

java.lang.SecurityException: Prohibited package name: java.util 问题分享

Prohibited package name: java.util ,错误解决供参考,先排查代码问题,再确认是否是版本配套问题...
  • zouheliang
  • zouheliang
  • 2017-09-27 11:43:44
  • 615

Java.lang.SecurityException

本人遇到的问题是第二个。在eclipse中清除tomcat相关,重新设置java版本,检查jdk的security文件加下的两个jar,然后重启eclipse,重新配置tomcat,再次启动。ok,错...
  • weisong530624687
  • weisong530624687
  • 2017-02-21 15:00:08
  • 1354

错误解决: java.lang.SecurityException: Permission Denial

场景:  java.lang.SecurityException: Permission Denial: starting Intent { cmp=com.siveco.bluebee.phone....
  • knighttools
  • knighttools
  • 2014-11-20 12:03:33
  • 65481

java.lang.SecurityException: Permission Denial:错误解决办法

在SDK23也就是Android6.0.1里编写调用系统通讯录读写权限的程序,在AndroidManifest.xml中,已经配置了 但...
  • OREO_GO
  • OREO_GO
  • 2016-08-23 22:25:01
  • 2886
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 230万+
    积分: 2万+
    排名: 345
    博客专栏
    最新评论