GetPathFromUri4kitkat【Android 4.4 kitkat以上及以下根据uri获取路径的方法】
版权声明:本文为HaiyuKing原创文章,转载请注明出处!
前言
在Android4.4之前和之后,通过Intent调用文件管理器选择文件,获取的文件uri地址形式是不同的。
Android6.0 content://com.android.providers.media.documents/document/image%3A593410
Android4.2.2 file:///storage/emulated/0/Pictures/Screenshots/Screenshot_2017-04-17-14-39-13.png
所以,当我们需要用到文件的绝对路径地址(/storage/emulated/0/Pictures/Screenshots/Screenshot_20170706-113240.png)的时候,则需要一个通用的方法。
效果图
Android 6.0 | Android4.2.2 |
![]() |
![]() |
代码分析
一般使用getPath( context,uri)方法即可。
使用步骤
一、项目组织结构图
注意事项:
1、导入类文件后需要change包名以及重新import R文件路径
2、Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖
二、导入步骤
将GetPathFromUri4kitkat.java文件复制到项目中
package com.why.project.getpathfromuri4kitkatdemo.utils; import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore; import java.io.File; /**
* @CreateBy HaiyuKing
* @Used Android 4.4 kitkat以上及以下根据uri获取路径的方法
* @参考资料 http://www.2cto.com/kf/201502/376975.html
*/
public class GetPathFromUri4kitkat {
/**
* 专为Android4.4设计的从Uri获取文件绝对路径,以前的方法已不好使
* @param uri - Android6.0 content://com.android.providers.media.documents/document/image%3A593410
* Android4.2.2 file:///storage/emulated/0/Pictures/Screenshots/Screenshot_2017-04-17-14-39-13.png
* @return Android6.0 /storage/emulated/0/Pictures/Screenshots/Screenshot_20170706-113240.png
* Android4.2.2 /storage/emulated/0/Pictures/Screenshots/Screenshot_2017-04-17-14-39-13.png
*/
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // 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];
} // TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(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;
} /**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context
* The context.
* @param uri
* The Uri to query.
* @param selection
* (Optional) Filter used in the query. 构造筛选语句
* @param selectionArgs
* (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) { Cursor cursor = null; //筛选列
final String column = MediaStore.Files.FileColumns.DATA;//"_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){
//java.lang.IllegalArgumentException: column '_data' does not exist
//华为的特殊处理:content://com.huawei.hidisk.fileprovider/root/storage/emulated/0/tencent/TIMfile_recv/xxx.doc
String rootPre = File.separator + "root";// /root
return uri.getPath().startsWith(rootPre) ? uri.getPath().replace(rootPre,"") : uri.getPath();
} finally {
if (cursor != null)
cursor.close();
}
return null;
} /**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
} /**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
} /**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}
GetPathFromUri4kitkat.java
在AndroidManifest.xml中添加权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.why.project.getpathfromuri4kitkatdemo"> <!-- ======================(GetPathFromUri4kitkat)========================== -->
<!-- 向SD卡读取数据权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application> </manifest>
添加运行时权限的处理(本demo中采用的是修改targetSDKVersion=22)
三、使用方法
package com.why.project.getpathfromuri4kitkatdemo; import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; import com.why.project.getpathfromuri4kitkatdemo.utils.GetPathFromUri4kitkat; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private Button btn_openFile;
private TextView tv_filePath; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initViews();
initEvents(); } private void initViews() {
btn_openFile = (Button) findViewById(R.id.btn_openFile);
tv_filePath = (TextView) findViewById(R.id.tv_filePath);
} private void initEvents() { btn_openFile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT);
String IMAGE_UNSPECIFIED = "*/*";
innerIntent.setType(IMAGE_UNSPECIFIED); // 查看类型
Intent wrapperIntent = Intent.createChooser(innerIntent, "File Browser");
MainActivity.this.startActivityForResult(wrapperIntent, 1111);
}
});
} /*=========================================实现打开文件管理器功能==============================================*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.w(TAG, "{onActivityResult}resultCode=" + resultCode);
Log.w(TAG, "{onActivityResult}requestCode=" + requestCode);
if (resultCode == Activity.RESULT_OK) {
//调用文件管理器选择文件的回调
if (requestCode == 1111) {
Uri result = data == null ? null : data.getData();
Log.w(TAG, "{onActivityResult}result=" + result); tv_filePath.setText("Uri:"+result.toString());
String pathStr = GetPathFromUri4kitkat.getPath(MainActivity.this,result);
Log.w(TAG, "{onActivityResult}pathStr=" + pathStr);
tv_filePath.setText(tv_filePath.getText() + "\n\n" + "Path:"+pathStr);
}
}
}
}
混淆配置
无
参考资料
Android 4.4 kitkat以上及以下根据uri获取路径的方法
项目demo下载地址
https://github.com/haiyuKing/GetPathFromUri4kitkatDemo
GetPathFromUri4kitkat【Android 4.4 kitkat以上及以下根据uri获取路径的方法】的更多相关文章
- Android 4.4 根据uri获取路径的方法
当我们选择图片以后,返回的是Uri,此时我们要把路径存储到数据库,必须将其转换成String类型. URI: //content://com.android.providers.media.docu ...
- android 获取路径目录方法以及判断目录是否存在,创建目录
Environment 常用方法: * 方法:getDataDirectory()解释:返回 File ,获取 Android 数据目录.* 方法:getDownloadCacheDirectory( ...
- android红米等关于读取本地文件夹图片获取路径的问题的解决
在Android开发中,有从本地文件夹中读取图片的功能,使用一下代码打开图片选择列表: Intent intent = new Intent(); intent.setAction(Intent. ...
- android获取路径目录方法
Environment常用方法: getExternalStrongeDirectory() 返回File,获取外部存储目录即SDCard getDownloadCacheDirectory() 返回 ...
- Android Uri获取真实路径以及文件名的方法【转】
原文地址:https://blog.csdn.net/MikoGodZd/article/details/50979653 在Android 编程中经常会用到uri转化为文件路径 下面是4.4后通过U ...
- Android 4.4 KitKat 新特性
New in Android 4.4 KitKat 本文是一个概览,关于KitKat,也即Android4.4的新东西,先是功能型的,之后是设计上的. 很多特性本文并没有提到,很多提到的特性也只是简短 ...
- Android 4.4 KitKat, the browser and the Chrome WebView
Having V8 as the JavaScript engine for the new web view, the JavaScript performance if much better, ...
- 让你的短信应用迎接Android 4.4(KitKat)
原文地址:Getting Your SMS Apps Ready for KitKat 发送和接收短信是手机最基本的功能,很多的开发者也开发了很多成功的应用来增强Android这一方面的体验.你们当中 ...
- Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 10
今天编译一个project,我设置为api 14,可是编译报错: Using 1.7 requires compiling with Android 4.4 (KitKat); currently u ...
随机推荐
- []T 还是 []*T, 这是一个问题
全面分析Go语言中的类型和类型指针的抉择 目录 [−] 副本的创建 T的副本创建 *T的副本创建 如何选择 T 和 *T 什么时候发生副本创建 最常见的case map.slice和数组 for-ra ...
- 本地广播 localBroadcastManager Android
使用localBroadcastManager发出的广播只能在本应用程序的内部进行传递. App应用内广播可理解为一种局部广播,广播的发送者和接收者都同属于一个App. 相比于全局广播(普通广播),A ...
- ConnectionString 属性尚未初始化
关于"ConnectionString 属性尚未初始化"的问题(如下图), 我在下面一段代码中发现了问题所在: public bool ReturnFlag(stri ...
- Java线程与Linux内核线程的映射关系
Linux从内核2.6开始使用NPTL (Native POSIX Thread Library)支持,但这时线程本质上还轻量级进程. Java里的线程是由JVM来管理的,它如何对应到操作系统的线程是 ...
- 高数量类别特征(high-cardinality categorical attributes)的预处理方法
high-cardinality categorical attributes,从字面上理解,即对于某个category特征,不同值的数量非常多,这里暂且把它叫做高数量类别属性.反之,即低数量类别属性 ...
- Akka实践一些总结
最近在一些服务中使用了akka,主要用来做异步解耦和本地消息分发(路由),这里简单总结一下用法. 与spring集成 网上有不少集成的例子,要使用到spring的扩展. 我这边没有这样处理,而是简单把 ...
- Boosting(提升方法)之GBDT
一.GBDT的通俗理解 提升方法采用的是加法模型和前向分步算法来解决分类和回归问题,而以决策树作为基函数的提升方法称为提升树(boosting tree).GBDT(Gradient Boosting ...
- 在 EFCore 定义的实体中进行 FreeSql 开发
EFCore 和 FreeSql 都是 ORM,在各自领域都有着独特的优势. 问题起源 假设某项目是使用 EFCore 开发的,且实体 特性或FluentApi 都配置好了,如: protected ...
- Unity C#笔记 协程
什么是协程 协同程序,在主程序运行的同时,开启另外一段逻辑处理,来协同当前程序的执行. 可能看了这段文字介绍还是有点模糊,其实可以用多线程来比较. 多线程 多线程,顾名思义,多条同时执行的线程. 最初 ...
- App 更换应用图标
一般情况下,我们App图标在Androidmanifest.xml中设置,通过Application android:icon属性指定,写法如下: <?xml version="1.0 ...