电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Android7.0以上Uri轉路徑的方法實現(已驗證)

瀏覽:86日期:2022-09-27 08:09:09

網絡上看到過很多種Uri轉路徑的方法,可基本上都只適用于很少的Uri值,可能沒有結果(例如,對于由MediaStore索引的非本地文件),也可能沒有可用的結果(例如,對于可移動存儲上的文件)。

解決方法

使用ContentResolver和openInputStream()在Uri標識的內容上獲取InputStream。在控制的文件上使用InputStream和FileOutputStream復制內容,然后使用該文件。

代碼如下:

private static String getFilePathForN(Context context, Uri uri) { try { Cursor returnCursor = context.getContentResolver().query(uri, null, null, null, null); int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); returnCursor.moveToFirst(); String name = (returnCursor.getString(nameIndex)); File file = new File(context.getFilesDir(), name); InputStream inputStream = context.getContentResolver().openInputStream(uri); FileOutputStream outputStream = new FileOutputStream(file); int read = 0; int maxBufferSize = 1 * 1024 * 1024; int bytesAvailable = inputStream.available(); int bufferSize = Math.min(bytesAvailable, maxBufferSize); final byte[] buffers = new byte[bufferSize]; while ((read = inputStream.read(buffers)) != -1) { outputStream.write(buffers, 0, read); } returnCursor.close(); inputStream.close(); outputStream.close(); return file.getPath(); } catch (Exception e) { e.printStackTrace(); } return null;}

附上全系統的代碼:

/** * 文件Uri轉路徑(兼容各品牌手機) */public class PathUtils { /** * android7.0以上處理方法 */ private static String getFilePathForN(Context context, Uri uri) { try { Cursor returnCursor = context.getContentResolver().query(uri, null, null, null, null); int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); returnCursor.moveToFirst(); String name = (returnCursor.getString(nameIndex)); File file = new File(context.getFilesDir(), name); InputStream inputStream = context.getContentResolver().openInputStream(uri); FileOutputStream outputStream = new FileOutputStream(file); int read = 0; int maxBufferSize = 1 * 1024 * 1024; int bytesAvailable = inputStream.available(); int bufferSize = Math.min(bytesAvailable, maxBufferSize); final byte[] buffers = new byte[bufferSize]; while ((read = inputStream.read(buffers)) != -1) {outputStream.write(buffers, 0, read); } returnCursor.close(); inputStream.close(); outputStream.close(); return file.getPath(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 全平臺處理方法 */ public static String getPath(final Context context, final Uri uri) throws Exception { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; final boolean isN = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; if (isN) { return getFilePathForN(context, uri); } // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) {final String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(':');final String type = split[0];if ('primary'.equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + '/' + split[1];} } // DownloadsProvider else if (isDownloadsDocument(uri)) {final String id = DocumentsContract.getDocumentId(uri);final Uri contentUri = ContentUris.withAppendedId( Uri.parse('content://downloads/public_downloads'), StringUtils.toLong(id));return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) {final String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(':');final String type = split[0];Uri contentUri = null;if ('image'.equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;} else if ('video'.equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;} else if ('audio'.equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;}final String selection = '_id=?';final String[] selectionArgs = new String[] { split[1]};return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ('content'.equalsIgnoreCase(uri.getScheme())) { return getDataColumn(context, uri, null, null); } // File else if ('file'.equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * 獲取此Uri的數據列的值。這對于MediaStore uri和其他基于文件的內容提供程序非常有用。 */ public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = '_data'; final String[] projection = {column }; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) {final int column_index = cursor.getColumnIndexOrThrow(column);return cursor.getString(column_index); } } catch (IllegalArgumentException e){ //do nothing } finally { if (cursor != null)cursor.close(); } return null; } public static boolean isExternalStorageDocument(Uri uri) { return 'com.android.externalstorage.documents'.equals(uri.getAuthority()); } public static boolean isDownloadsDocument(Uri uri) { return 'com.android.providers.downloads.documents'.equals(uri.getAuthority()); } public static boolean isMediaDocument(Uri uri) { return 'com.android.providers.media.documents'.equals(uri.getAuthority()); }}

參考資料:https://stackoverflow.com/questions/42508383/illegalargumentexception-column-data-does-not-exist

另發現一篇,親測,Android 4.4到Android 10可用,測試的系統有VIVO、OPPO、MIUI、EMUI...

解決的國內產商問題:華為的黃色圖標管理器,他返回了4.4的標準的Uri了,不是4.4以上的標準的Uri,導致解析的時候,判斷到版本 > 4.4,然后用了4.4以上的標準的解析,然后失敗了,并非不回調。

直接可用的代碼片段:

public class FileUtils { private Context context; public FileUtils(Context context) { this.context = context; } public String getFilePathByUri(Uri uri) { // 以 file:// 開頭的 if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { return uri.getPath(); } // 以/storage開頭的也直接返回 if (isOtherDocument(uri)) { return uri.getPath(); } // 版本兼容的獲??! String path = getFilePathByUri_BELOWAPI11(uri); if (path != null) { LogUtils.d('getFilePathByUri_BELOWAPI11獲取到的路徑為:' + path); return path; } path = getFilePathByUri_API11to18(uri); if (path != null) { LogUtils.d('getFilePathByUri_API11to18獲取到的路徑為:' + path); return path; } path = getFilePathByUri_API19(uri); LogUtils.d('getFilePathByUri_API19獲取到的路徑為:' + path); return path; } private String getFilePathByUri_BELOWAPI11(Uri uri) { // 以 content:// 開頭的,比如 content://media/extenral/images/media/17766 if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { String path = null; String[] projection = new String[]{MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); if (cursor != null) {if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); if (columnIndex > -1) { path = cursor.getString(columnIndex); }}cursor.close(); } return path; } return null; } private String getFilePathByUri_API11to18(Uri contentUri) { String[] projection = {MediaStore.Images.Media.DATA}; String result = null; CursorLoader cursorLoader = new CursorLoader(context, contentUri, projection, null, null, null); Cursor cursor = cursorLoader.loadInBackground(); if (cursor != null) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); result = cursor.getString(column_index); cursor.close(); } return result; } private String getFilePathByUri_API19(Uri uri) { // 4.4及之后的 是以 content:// 開頭的,比如 content://com.android.providers.media.documents/document/image%3A235700 if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (DocumentsContract.isDocumentUri(context, uri)) {if (isExternalStorageDocument(uri)) { // ExternalStorageProvider String docId = DocumentsContract.getDocumentId(uri); String[] split = docId.split(':'); String type = split[0]; if ('primary'.equalsIgnoreCase(type)) { if (split.length > 1) { return Environment.getExternalStorageDirectory() + '/' + split[1]; } else { return Environment.getExternalStorageDirectory() + '/'; } // This is for checking SD Card }} else if (isDownloadsDocument(uri)) { //下載內容提供者時應當判斷下載管理器是否被禁用 int stateCode = context.getPackageManager().getApplicationEnabledSetting('com.android.providers.downloads'); if (stateCode != 0 && stateCode != 1) { return null; } String id = DocumentsContract.getDocumentId(uri); // 如果出現這個RAW地址,我們則可以直接返回! if (id.startsWith('raw:')) { return id.replaceFirst('raw:', ''); } if (id.contains(':')) { String[] tmp = id.split(':'); if (tmp.length > 1) { id = tmp[1]; } } Uri contentUri = Uri.parse('content://downloads/public_downloads'); LogUtils.d('測試打印Uri: ' + uri); try { contentUri = ContentUris.withAppendedId(contentUri, Long.parseLong(id)); } catch (Exception e) { e.printStackTrace(); } String path = getDataColumn(contentUri, null, null); if (path != null) return path; // 兼容某些特殊情況下的文件管理器! String fileName = getFileNameByUri(uri); if (fileName != null) { path = Environment.getExternalStorageDirectory().toString() + '/Download/' + fileName; return path; }} else if (isMediaDocument(uri)) { // MediaProvider String docId = DocumentsContract.getDocumentId(uri); String[] split = docId.split(':'); String type = split[0]; Uri contentUri = null; if ('image'.equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ('video'.equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ('audio'.equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } String selection = '_id=?'; String[] selectionArgs = new String[]{split[1]}; return getDataColumn(contentUri, selection, selectionArgs);} } } return null; } private String getFileNameByUri(Uri uri) { String relativePath = getFileRelativePathByUri_API18(uri); if (relativePath == null) relativePath = ''; final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME }; try (Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null)) { if (cursor != null && cursor.moveToFirst()) {int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME);return relativePath + cursor.getString(index); } } return null; } private String getFileRelativePathByUri_API18(Uri uri) { final String[] projection; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { projection = new String[]{ MediaStore.MediaColumns.RELATIVE_PATH }; try (Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null)) {if (cursor != null && cursor.moveToFirst()) { int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.RELATIVE_PATH); return cursor.getString(index);} } } return null; } private String getDataColumn(Uri uri, String selection, String[] selectionArgs) { final String column = MediaStore.Images.Media.DATA; final String[] projection = {column}; try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null)) { if (cursor != null && cursor.moveToFirst()) {final int column_index = cursor.getColumnIndexOrThrow(column);return cursor.getString(column_index); } } catch (IllegalArgumentException iae) { iae.printStackTrace(); } return null; } private boolean isExternalStorageDocument(Uri uri) { return 'com.android.externalstorage.documents'.equals(uri.getAuthority()); } private boolean isOtherDocument(Uri uri) { // 以/storage開頭的也直接返回 if (uri != null && uri.getPath() != null) { String path = uri.getPath(); if (path.startsWith('/storage')) {return true; } if (path.startsWith('/external_files')) {return true; } } return false; } private boolean isDownloadsDocument(Uri uri) { return 'com.android.providers.downloads.documents'.equals(uri.getAuthority()); } private boolean isMediaDocument(Uri uri) { return 'com.android.providers.media.documents'.equals(uri.getAuthority()); }}

調用 getFilePathByUri(Uri uri) 即可獲得最終的路徑。

到此這篇關于Android7.0以上Uri轉路徑的方法實現(已驗證)的文章就介紹到這了,更多相關Android7 Uri轉路徑內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Android
相關文章:
主站蜘蛛池模板: 油缸定制-液压油缸厂家-无锡大鸿液压气动成套有限公司 | 沈阳庭院景观设计_私家花园_别墅庭院设计_阳台楼顶花园设计施工公司-【沈阳现代时园艺景观工程有限公司】 | 广州展览制作工厂—[优简]直营展台制作工厂_展会搭建资质齐全 | 留学生辅导网-在线课程论文辅导-留学生挂科申诉机构 | 特种电缆厂家-硅橡胶耐高温电缆-耐低温补偿导线-安徽万邦特种电缆有限公司 | 焊锡丝|焊锡条|无铅锡条|无铅锡丝|无铅焊锡线|低温锡膏-深圳市川崎锡业科技有限公司 | 南京欧陆电气股份有限公司-风力发电机官网 | 发电机组|柴油发电机组-批发,上柴,玉柴,潍柴,康明斯柴油发电机厂家直销 | 临沂招聘网_人才市场_招聘信息_求职招聘找工作请认准【马头商标】 | 谷歌关键词优化-外贸网站优化-Google SEO小语种推广-思亿欧外贸快车 | 沈飞防静电地板__机房地板-深圳市沈飞防静电设备有限公司 | 防水套管厂家-柔性防水套管-不锈钢|刚性防水套管-天翔管道 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 合肥风管加工厂-安徽螺旋/不锈钢风管-通风管道加工厂家-安徽风之范 | 砂石生产线_石料生产线设备_制砂生产线设备价格_生产厂家-河南中誉鼎力智能装备有限公司 | 煤矿人员精确定位系统_矿用无线通信系统_煤矿广播系统 | 警用|治安|保安|不锈钢岗亭-售货亭价格-垃圾分类亭-移动厕所厂家-苏州灿宇建材 | 德国GMN轴承,GMN角接触球轴承,GMN单向轴承,GMN油封,GMN非接触式密封 | 常州翔天实验仪器厂-恒温振荡器-台式恒温振荡器-微量血液离心机 恒温恒湿箱(药品/保健品/食品/半导体/细菌)-兰贝石(北京)科技有限公司 | 陶瓷加热器,履带式加热器-吴江市兴达电热设备厂 | 郑州大巴车出租|中巴车租赁|旅游大巴租车|包车|郑州旅游大巴车租赁有限公司 | 3D全息投影_地面互动投影_360度立体投影_水幕灯光秀 | 广东银虎 蜂窝块状沸石分子筛-吸附脱硫分子筛-萍乡市捷龙环保科技有限公司 | 节流截止放空阀-不锈钢阀门-气动|电动截止阀-鸿华阀门有限公司 | 电缆接头-防爆电缆接头-格兰头-金属电缆接头-防爆填料函 | 深圳希玛林顺潮眼科医院(官网)│深圳眼科医院│医保定点│香港希玛林顺潮眼科中心连锁品牌 | 企业管理培训,企业培训公开课,企业内训课程,企业培训师 - 名课堂企业管理培训网 | 仿古瓦,仿古金属瓦,铝瓦,铜瓦,铝合金瓦-西安东申景观艺术工程有限公司 | MOOG伺服阀维修,ATOS比例流量阀维修,伺服阀维修-上海纽顿液压设备有限公司 | 北京模型公司-工业模型-地产模型-施工模型-北京渝峰时代沙盘模型制作公司 | HDPE储罐_厂家-山东九州阿丽贝防腐设备 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 升降机-高空作业车租赁-蜘蛛车-曲臂式伸缩臂剪叉式液压升降平台-脚手架-【普雷斯特公司厂家】 | 合肥弱电工程_安徽安防工程_智能化工程公司-合肥雷润 | 隐形纱窗|防护纱窗|金刚网防盗纱窗|韦柏纱窗|上海青木装潢制品有限公司|纱窗国标起草单位 | 深圳法律咨询【24小时在线】深圳律师咨询免费 | 劳动法网-专业的劳动法和劳动争议仲裁服务网 | 2025世界机器人大会_IC China_半导体展_集成电路博览会_智能制造展览网 | 北京印刷厂_北京印刷_北京印刷公司_北京印刷厂家_北京东爵盛世印刷有限公司 | 专业甜品培训学校_广东糖水培训_奶茶培训_特色小吃培训_广州烘趣甜品培训机构 | 粉末包装机-给袋式包装机-全自动包装机-颗粒-液体-食品-酱腌菜包装机生产线【润立机械】 | 无线遥控更衣吊篮_IC卡更衣吊篮_电动更衣吊篮配件_煤矿更衣吊篮-力得电子 |