版权声明:本文为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获取路径的方法】的更多相关文章

  1. Android 4.4 根据uri获取路径的方法

    当我们选择图片以后,返回的是Uri,此时我们要把路径存储到数据库,必须将其转换成String类型. URI:  //content://com.android.providers.media.docu ...

  2. android 获取路径目录方法以及判断目录是否存在,创建目录

    Environment 常用方法: * 方法:getDataDirectory()解释:返回 File ,获取 Android 数据目录.* 方法:getDownloadCacheDirectory( ...

  3. android红米等关于读取本地文件夹图片获取路径的问题的解决

    在Android开发中,有从本地文件夹中读取图片的功能,使用一下代码打开图片选择列表: Intent intent = new Intent();   intent.setAction(Intent. ...

  4. android获取路径目录方法

    Environment常用方法: getExternalStrongeDirectory() 返回File,获取外部存储目录即SDCard getDownloadCacheDirectory() 返回 ...

  5. Android Uri获取真实路径以及文件名的方法【转】

    原文地址:https://blog.csdn.net/MikoGodZd/article/details/50979653 在Android 编程中经常会用到uri转化为文件路径 下面是4.4后通过U ...

  6. Android 4.4 KitKat 新特性

    New in Android 4.4 KitKat 本文是一个概览,关于KitKat,也即Android4.4的新东西,先是功能型的,之后是设计上的. 很多特性本文并没有提到,很多提到的特性也只是简短 ...

  7. 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, ...

  8. 让你的短信应用迎接Android 4.4(KitKat)

    原文地址:Getting Your SMS Apps Ready for KitKat 发送和接收短信是手机最基本的功能,很多的开发者也开发了很多成功的应用来增强Android这一方面的体验.你们当中 ...

  9. 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 ...

随机推荐

  1. BDD测试之selenium控制滚动条

    一.对于页面存在滚动条,可以通过插入JS控制滚动条(最常用的方法) (1)将滚动条移动到指定坐标位置处 ((JavascriptExecutor) driver).executeScript(&quo ...

  2. bzoj4476 [Jsoi2015]送礼物

    化简式子 $M>=m+ans*(r-l+k)$ 发现$M,m$确定时,总区间长度越小越好,于是假定右端点为最小值$M+ans*l>=m+ans*r+ans*k$, 右面都确定了,但最大值仍 ...

  3. Evensgn 剪树枝 树规

    f[x][0]表示与其父边相连的连通块内没有黑苹果的方案数, f[x][1]则表示有黑苹果, 如果父边被切断,相当于没有黑苹果 初始化时,假设切掉父边,f[x][0]=1,f[x][1]=0; 递归回 ...

  4. 【强连通分量+概率】Bzoj2438 杀人游戏

    Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是 ...

  5. Loadrunner下载脚本

    由于最近又在SGM做性能测试,扒拉出一篇去年5.6月份的一个脚本. 最近写的翻来看看其实也蛮简单的,还是就不放博客了. Action(){ //定义文件大小 int flen; //定义响应数据内容大 ...

  6. Spring mvc 下载文件处理

    @RequestMapping(value = "downFile") public void downFile(HttpServletResponse response, Str ...

  7. 【公告】关于8.8MIP组件审核平台故障的说明

    故障通报 2017 年 8 月 8 日 下午 14:11,由于机器故障原因,MIP 组件管理平台暂时无法提供服务. 2017 年 8 月 8 日 下午 16:46, 故障已解决.MIP 组件管理平台服 ...

  8. 一个实时收集MySql变更记录的组件CanalSharp.AspNetCore

    一.关于CanalSharp CanalSharp 是阿里巴巴开源项目 Canal 的 .NET 客户端.为 .NET 开发者提供一个更友好的使用 Canal 的方式.Canal 是mysql数据库b ...

  9. js防抖和节流

    今天在网上看到的,里面的内容非常多.说下我自己的理解. 所谓的防抖就是利用延时器来使你的最后一次操作执行.而节流是利用时间差的办法,每一段时间执行一次.下面是我的代码: 这段代码是右侧的小滑块跟随页面 ...

  10. 关于微信JS-SDK 分享接口的两个报错记录

    一.前提: 微信测试号,用微信开发者工具测试 二.简单复述文档: 1.引入JS文件 在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/j ...