Uri uri = data.getData();
Log.d(TAG, “uri:” + uri);
//String filePath = PickUtils.getPath(this, uri);
//textView.setText(filePath);
}
super.onActivityResult(requestCode, resultCode, data);
}
重点来了,我们可以很轻松的拿到Uri
, 但是转absolute path
在不同的机型却遇到了奇奇怪怪的问题,至今没有完全弄明白。
大概的意思就是有些机型转path时会失败,比如在华为10.0的机型上,通过下载内容
中打开Download
的文件就会失败,场景是原本的documentid
可以转为long型,但它变成了这个样子msf:123
,导致转换失败。
有很多人都存在这个问题,比如这个地址:https://stackoverflow.com/questions/58660420/api-level-29-intent-action-get-content-returning-wrong-id-from-downloads-folder
解决方法:在转换绝对路径失败的情况,将文件拷贝到自己的app的缓存目录下,然后返回路径。 代码在文章末尾。
我们可以轻松的拿到Uri之后,实际上在不转绝对路径的情况下,用Uri已经可以做很多事情了,比如获取文件类型、比如获取文件的byte[]、获取文件名 等等。
- 获取文件类型,返回的结果需要在
类型对应
中去对照。
/**
-
获取文件的类型。
-
@param context 上下文
-
@param uri uri
-
@return
*/
public static String getFormatByUri(@NonNull Context context, @NonNull Uri uri) {
String type = context.getContentResolver().getType(uri);
if (TextUtils.isEmpty(type)) return null;
return type;
}
- 获取字节数组
/**
-
根据uri获取 byte[]
-
@param context
-
@param uri
-
@return
-
@throws IOException
*/
public static byte[] getBytesByUri(Context context, Uri uri) throws IOException {
InputStream iStream = context.getContentResolver().openInputStream(uri);
if (iStream == null) return null;
return getBytes(iStream);
}
private static byte[] getBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
- 获取文件名
/**
-
获取文件名
-
@param uri uri
-
@return
*/
public String getFileNameByUri(Uri uri) {
String filename = “”;
Cursor returnCursor = getContentResolver().query(uri, null,
null, null, null);
if (returnCursor != null) {
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
filename = returnCursor.getString(nameIndex);
returnCursor.close();
}
return filename;
}
当然,这个完美的工具类还是提供给大家。出处我不记得了,我稍微改了一点,目前用下来非常完美。 只是在转path不成功的情况下,会拷贝文件放到应用的缓存目录,大家需要注意下清理缓存的时机。
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 android.provider.OpenableColumns;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
- Created by pangw on 2018/5/23.
*/
public class PickUtils {
public static final String DOCUMENTS_DIR = “documents”;
@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];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
if (id != null && id.startsWith(“raw:”)) {
return id.substring(4);
}
String[] contentUriPrefixesToTry = new String[]{
“content://downloads/public_downloads”,
“content://downloads/my_downloads”
};
for (String contentUriPrefix : contentUriPrefixesToTry) {
try {
// note: id 可能为字符串,如在华为10.0系统上,选择文件后id为:“msf:254”,导致转Long异常
Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.parseLong(id));
String path = getDataColumn(context, contentUri, null, null);
if (path != null && !path.equals(“”)) {
return path;
}
} catch (Exception e) {
}
}
// path could not be retrieved using ContentResolver, therefore copy file to accessible cache using streams
String fileName = getFileName(context, uri);
File cacheDir = getDocumentCacheDir(context);
File file = generateFileName(fileName, cacheDir);
String destinationPath = null;
if (file != null) {
destinationPath = file.getAbsolutePath();
saveFileFromUri(context, uri, destinationPath);
}
return destinationPath;
}
// 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())) {
String path = getDataColumn(context, uri, null, null);
if (path != null && !path.equals(“”)) return path;
// path could not be retrieved using ContentResolver, therefore copy file to accessible cache using streams
String fileName = getFileName(context, uri);
File cacheDir = getDocumentCacheDir(context);
File file = generateFileName(fileName, cacheDir);
String destinationPath = null;
if (file != null) {
destinationPath = file.getAbsolutePath();
saveFileFromUri(context, uri, destinationPath);
}
return destinationPath;
}
// File
else if (“file”.equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
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());
}
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = “_data”;
final String[] projection = {column};
String path = “”;
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
path = cursor.getString(column_index);
return path;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return path;
}
public static String getFileName(@NonNull Context context, Uri uri) {
String mimeType = context.getContentResolver().getType(uri);
String filename = null;
if (mimeType == null && context != null) {
String path = getPath(context, uri);
if (path == null) {
filename = getName(uri.toString());
} else {
File file = new File(path);
filename = file.getName();
}
} else {
Cursor returnCursor = context.getContentResolver().query(uri, null,
null, null, null);
if (returnCursor != null) {
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
filename = returnCursor.getString(nameIndex);
returnCursor.close();
}
}
return filename;
}
public static String getName(String filename) {
if (filename == null) {
return null;
}
int index = filename.lastIndexOf(‘/’);
return filename.substring(index + 1);
}
public static File getDocumentCacheDir(@NonNull Context context) {
Log.d(“PickUtils”, “getDocumentCacheDir”);
File dir = new File(context.getCacheDir(), DOCUMENTS_DIR);
if (!dir.exists()) {
dir.mkdirs();
}
return dir;
}
@Nullable
public static File generateFileName(@Nullable String name, File directory) {
if (name == null) {
return null;
}
File file = new File(directory, name);
if (file.exists()) {
String fileName = name;
String extension = “”;
int dotIndex = name.lastIndexOf(‘.’);
if (dotIndex > 0) {
fileName = name.substring(0, dotIndex);
extension = name.substring(dotIndex);
}
int index = 0;
while (file.exists()) {
index++;
Android核心知识点
面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验。
下面这份PDF是我翻阅了差不多3个月左右一些Android大博主的博客从他们那里取其精华去其糟泊所整理出来的一些Android的核心知识点,全部都是精华中的精华,我能面试到现在2-2资深开发人员跟我整理的这本Android核心知识点有密不可分的关系,在这里本着共赢的心态分享给各位朋友。
不管是Android基础还是Java基础以及常见的数据结构,这些是无原则地必须要熟练掌握的,尤其是非计算机专业的同学,面试官一上来肯定是问你基础,要是基础表现不好很容易被扣上基础不扎实的帽子,常见的就那些,只要你平时认真思考过基本上面试是没太大问题的。
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上我搜集整理的2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
oid大博主的博客从他们那里取其精华去其糟泊所整理出来的一些Android的核心知识点,全部都是精华中的精华,我能面试到现在2-2资深开发人员跟我整理的这本Android核心知识点有密不可分的关系,在这里本着共赢的心态分享给各位朋友。
[外链图片转存中…(img-T7pTx3k8-1714334886015)]
不管是Android基础还是Java基础以及常见的数据结构,这些是无原则地必须要熟练掌握的,尤其是非计算机专业的同学,面试官一上来肯定是问你基础,要是基础表现不好很容易被扣上基础不扎实的帽子,常见的就那些,只要你平时认真思考过基本上面试是没太大问题的。
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上我搜集整理的2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!