记录Android读取内置、外置SD卡和外置USB文件内容处理过程。
1、最开始想到的是获取文件路径,通过FileInputStream来读取。发现内置与外置SD卡路径不同,通过判断也是可以实现的。但是读取USB需要权限申请才行,而且权限申请后系统文件居然不显示USB内容了,只能通过代码读取文件或文件夹自己实现显示,路径还和外置SD卡一样,还不好判断是应该用OTG读取USB还是直接读取外置SD卡,果断放弃了读取USB文件内容,只保留读取SD卡内容。
2、后面想到为什么要将Uri转成路径呢,为什么不直接通过Uri读取文件内容,想到就试试,发现什么都不用判断,不管是内置外置SD卡或者外接USB,直接就可以读取,简直不能再简单了。代码如下:
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_KML && resultCode == RESULT_OK && data != null) {
String path = data.getData().getPath();
if (path != null && (path.toUpperCase().endsWith(".KML") || path.toUpperCase().endsWith(".OVKML"))) {
new Thread(() -> {
try {
KmlReader reader = new KmlReader(kmlReaderCallback);
//直接通过Uri读取文件内容,不用判断是内置还是外置SD卡或USB
InputStream inputStream = getContentResolver().openInputStream(data.getData());
reader.read(inputStream);
} catch (IOException | XmlPullParserException e) {
e.printStackTrace();
Logs.e(e.toString());
AndroidUtilities.runOnUIThread(() -> ToastUtils.show(getString(R.string.file_open_error)));
}
}).start();
} else {
ToastUtils.show(getString(R.string.wrong_format));
}
}
}
3、有大神知道这是为什么吗?查看源码:
public final @Nullable InputStream openInputStream(@NonNull Uri uri) throws FileNotFoundException { Objects.requireNonNull(uri, "uri"); // 这边获取的Uri协议一直都是content,不管是内置还是外置存储 String scheme = uri.getScheme(); if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { // Note: left here to avoid breaking compatibility. May be removed // with sufficient testing. OpenResourceIdResult r = getResourceId(uri); try { InputStream stream = r.r.openRawResource(r.id); return stream; } catch (Resources.NotFoundException ex) { throw new FileNotFoundException("Resource does not exist: " + uri); } } else if (SCHEME_FILE.equals(scheme)) { // Note: left here to avoid breaking compatibility. May be removed // with sufficient testing. return new FileInputStream(uri.getPath()); } else { // 这是将文件当做Asset资源文件读取? AssetFileDescriptor fd = openAssetFileDescriptor(uri, "r", null); try { return fd != null ? fd.createInputStream() : null; } catch (IOException e) { throw new FileNotFoundException("Unable to create stream"); } } }
public FileInputStream createInputStream() throws IOException { if (mLength < 0) { // ParcelFileDescriptor.AutoCloseInputStream继承自FileInputStream return new ParcelFileDescriptor.AutoCloseInputStream(mFd); } // AutoCloseInputStream继承自ParcelFileDescriptor.AutoCloseInputStream return new AutoCloseInputStream(this); }