【我的Android进阶之旅】Android 7.0报异常:java.lang.SecurityException: COLUMN_LOCAL_FILENAME is deprecated;
2017-03-17 16:57
405 查看
之前开发的一个和第三方合作的apk,在之前公司的 Android 5.1 系统的手表上运行正常,今天在公司新开发的 Android 7.1系统的手表上运行的时候,使用 DownloadManager 下载之后,查询下载状态的时候,报了异常
异常详细信息如下:
跳转到报错的地方,如下图所示:
在运行下面两行代码的时候报错了。
而且 DownloadManager.COLUMN_LOCAL_FILENAME 已经是被废弃的常量了,点击查看源代码如下所示:
Android 在 Android 7.0 或更高版本开发的应用在尝试访问DownloadManager.COLUMN_LOCAL_FILENAME 时会触发java.lang.SecurityException。
Android官方建议我们使用 ContentResolver#openFileDescriptor(Uri, String)来获取文件相关信息。源代码如下所示:
查看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的相关信息,如下所示:
运行之后,不会报错,并且能够获取到正常的文件名。
参考链接
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
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
相关文章推荐
- Android 7.0报错 java.lang.SecurityException: MODE_WORLD_READABLE no longer supported
- Android异常总结---E/AndroidRuntime(23439): Caused by: java.lang.IllegalArgumentException: column '_id' d
- Android异常:唤醒锁未授权。(Caused by: java.lang.SecurityException: Neither user 10044 nor current process has android.permission.WAKE_LOCK.)
- Android问题分享:DownloadManager基本用法及发生java.lang.SecurityException异常的解决办法
- Android 异常- java.lang.SecurityException: Permission Denial:xxx
- 【Android】java.lang.NumberFormatException: Expected an int but was 53.81 at line 1 column 782 异常
- Android学习----异常(3)---java.lang.IllegalArgumentException: column '_id' does not exist
- Android 7.0 java.lang.SecurityException: MODE_WORLD_READABLE no longer supported闪退
- android content provider java.lang.SecurityException: Permission Denial异常解决
- 【Android】java.lang.SecurityException: Permission Denial: starting Intent 应用启动失败异常
- JNI DETECTED ERROR IN APPLICATION:java.lang.SecurityExceptionandroid--解决JNI安全权限异常
- Android异常总结---E/AndroidRuntime(23439): Caused by: java.lang.IllegalArgumentException: column '_id' d
- Android 异常处理:java.lang.IllegalArgumentException(...contains a path separator)
- 某APK中使用了动态注册BroadcastReceiver,Launcher中动态加载此APK出现java.lang.SecurityException异常的解决方法
- android java.lang.IllegalArgumentException: The observer is null 异常解决
- Android 问题异常 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo
- Android 异常 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper
- Android Caused by: java.lang.IllegalArgumentException: column '_id' does not exist
- java.lang.SecurityException: Prohibited package name异常
- 某APK中使用了动态注册BroadcastReceiver,Launcher中动态加载此APK出现java.lang.SecurityException异常的解决方法