Android 4.4(API级别19)引入了存储访问框架(SAF)。
通过SAF,用户可以轻松地浏览和打开所有首选文档存储提供商中的文档,图像和其他文件。
也就是说,接下来介绍的方式适用于android4.4+的操作系统。
参考链接:https://developer.android.com/guide/topics/providers/document-provider
private static final int READ_REQUEST_CODE = 42;
...
/**
* Fires an intent to spin up the "file chooser" UI and select an image.
*/
public void performFileSearch() {
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
// browser.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// Filter to only show results that can be "opened", such as a
// file (as opposed to a list of contacts or timezones)
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only images, using the image MIME data type.
// If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
// To search for all documents available via installed storage providers,
// it would be "*/*".
intent.setType("image/*");
startActivityForResult(intent, READ_REQUEST_CODE);
}
ACTION_OPEN_DOCUMEN
,还可以替换为ACTION_GET_CONTENT
,两者的区别如下:仅读取/导入数据
,请使用ACTION_GET_CONTENT
。 通过这种方法,应用程序可以导入数据的副本
,例如图像文件。具有长期,持久的访问权限
,请使用ACTION_OPEN_DOCUMENT
。CATEGORY_OPENABLE
,过滤出可以打开的文件"image/*"
"image/png"
"application/vnd.android.package-archive"
startActivityForResult
启动Inetent,以便在onActivityResult
接收文件选择结果@Override
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
// The ACTION_OPEN_DOCUMENT intent was sent with the request code
// READ_REQUEST_CODE. If the request code seen here doesn't match, it's the
// response to some other intent, and the code below shouldn't run at all.
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
// The document selected by the user won't be returned in the intent.
// Instead, a URI to that document will be contained in the return intent
// provided to this method as a parameter.
// Pull that URI using resultData.getData().
Uri uri = null;
if (resultData != null) {
uri = resultData.getData();
Log.i(TAG, "Uri: " + uri.toString());
showImage(uri);
}
}
}
public void dumpImageMetaData(Uri uri) {
// The query, since it only applies to a single document, will only return
// one row. There's no need to filter, sort, or select fields, since we want
// all fields for one document.
Cursor cursor = getActivity().getContentResolver()
.query(uri, null, null, null, null, null);
try {
// moveToFirst() returns false if the cursor has 0 rows. Very handy for
// "if there's anything to look at, look at it" conditionals.
if (cursor != null && cursor.moveToFirst()) {
// Note it's called "Display Name". This is
// provider-specific, and might not necessarily be the file name.
String displayName = cursor.getString(
cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
Log.i(TAG, "Display Name: " + displayName);
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
// If the size is unknown, the value stored is null. But since an
// int can't be null in Java, the behavior is implementation-specific,
// which is just a fancy term for "unpredictable". So as
// a rule, check if it's null before assigning to an int. This will
// happen often: The storage API allows for remote files, whose
// size might not be locally known.
String size = null;
if (!cursor.isNull(sizeIndex)) {
// Technically the column stores an int, but cursor.getString()
// will do the conversion automatically.
size = cursor.getString(sizeIndex);
} else {
size = "Unknown";
}
Log.i(TAG, "Size: " + size);
}
} finally {
cursor.close();
}
}
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
private String readTextFromUri(Uri uri) throws IOException {
StringBuilder stringBuilder = new StringBuilder();
try (InputStream inputStream =
getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(
new InputStreamReader(Objects.requireNonNull(inputStream)))) {
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
}
return stringBuilder.toString();
}
文件类型 | mime名称 | 文件类型 | mime名称 |
---|---|---|---|
3gp | video/3gpp | pdb | chemical/x-pdb |
aab | application/x-authoware-bin | application/pdf | |
aam | application/x-authoware-map | pfr | application/font-tdpfr |
aas | application/x-authoware-seg | pgm | image/x-portable-graymap |
ai | application/postscript | pict | image/x-pict |
aif | audio/x-aiff | pm | application/x-perl |
aifc | audio/x-aiff | pmd | application/x-pmd |
aiff | audio/x-aiff | png | image/png |
als | audio/X-Alpha5 | pnm | image/x-portable-anymap |
amc | application/x-mpeg | pnz | image/png |
ani | application/octet-stream | pot | application/vnd.ms-powerpoint |
apk | application/vnd.android.package-archive | ppm | image/x-portable-pixmap |
asc | text/plain | pps | application/vnd.ms-powerpoint |
asd | application/astound | ppt | application/vnd.ms-powerpoint |
asf | video/x-ms-asf | pqf | application/x-cprplayer |
asn | application/astound | pqi | application/cprplayer |
asp | application/x-asap | prc | application/x-prc |
asx | video/x-ms-asf | proxy | application/x-ns-proxy-autoconfig |
au | audio/basic | ps | application/postscript |
avb | application/octet-stream | ptlk | application/listenup |
avi | video/x-msvideo | pub | application/x-mspublisher |
awb | audio/amr-wb | pvx | video/x-pv-pvx |
bcpio | application/x-bcpio | qcp | audio/vnd.qcelp |
bin | application/octet-stream | qt | video/quicktime |
bld | application/bld | qti | image/x-quicktime |
bld2 | application/bld2 | qtif | image/x-quicktime |
bmp | image/bmp | r3t | text/vnd.rn-realtext3d |
bpk | application/octet-stream | ra | audio/x-pn-realaudio |
bz2 | application/x-bzip2 | ram | audio/x-pn-realaudio |
cal | image/x-cals | rar | application/x-rar-compressed |
ccn | application/x-cnc | ras | image/x-cmu-raster |
cco | application/x-cocoa | rdf | application/rdf+xml |
cdf | application/x-netcdf | rf | image/vnd.rn-realflash |
cgi | magnus-internal/cgi | rgb | image/x-rgb |
chat | application/x-chat | rlf | application/x-richlink |
class | application/octet-stream | rm | audio/x-pn-realaudio |
clp | application/x-msclip | rmf | audio/x-rmf |
cmx | application/x-cmx | rmm | audio/x-pn-realaudio |
co | application/x-cult3d-object | rmvb | audio/x-pn-realaudio |
cod | image/cis-cod | rnx | application/vnd.rn-realplayer |
cpio | application/x-cpio | roff | application/x-troff |
cpt | application/mac-compactpro | rp | image/vnd.rn-realpix |
crd | application/x-mscardfile | rpm | audio/x-pn-realaudio-plugin |
csh | application/x-csh | rt | text/vnd.rn-realtext |
csm | chemical/x-csml | rte | x-lml/x-gps |
csml | chemical/x-csml | rtf | application/rtf |
css | text/css | rtg | application/metastream |
cur | application/octet-stream | rtx | text/richtext |
dcm | x-lml/x-evm | rv | video/vnd.rn-realvideo |
dcr | application/x-director | rwc | application/x-rogerwilco |
dcx | image/x-dcx | s3m | audio/x-mod |
dhtml | text/html | s3z | audio/x-mod |
dir | application/x-director | sca | application/x-supercard |
dll | application/octet-stream | scd | application/x-msschedule |
dmg | application/octet-stream | sdf | application/e-score |
dms | application/octet-stream | sea | application/x-stuffit |
doc | application/msword | sgm | text/x-sgml |
dot | application/x-dot | sgml | text/x-sgml |
dvi | application/x-dvi | sh | application/x-sh |
dwf | drawing/x-dwf | shar | application/x-shar |
dwg | application/x-autocad | shtml | magnus-internal/parsed-html |
dxf | application/x-autocad | shw | application/presentations |
dxr | application/x-director | si6 | image/si6 |
ebk | application/x-expandedbook | si7 | image/vnd.stiwap.sis |
emb | chemical/x-embl-dl-nucleotide | si9 | image/vnd.lgtwap.sis |
embl | chemical/x-embl-dl-nucleotide | sis | application/vnd.symbian.install |
eps | application/postscript | sit | application/x-stuffit |
eri | image/x-eri | skd | application/x-Koan |
es | audio/echospeech | skm | application/x-Koan |
esl | audio/echospeech | skp | application/x-Koan |
etc | application/x-earthtime | skt | application/x-Koan |
etx | text/x-setext | slc | application/x-salsa |
evm | x-lml/x-evm | smd | audio/x-smd |
evy | application/x-envoy | smi | application/smil |
exe | application/octet-stream | smil | application/smil |
fh4 | image/x-freehand | smp | application/studiom |
fh5 | image/x-freehand | smz | audio/x-smd |
fhc | image/x-freehand | snd | audio/basic |
fif | image/fif | spc | text/x-speech |
fm | application/x-maker | spl | application/futuresplash |
fpx | image/x-fpx | spr | application/x-sprite |
fvi | video/isivideo | sprite | application/x-sprite |
gau | chemical/x-gaussian-input | spt | application/x-spt |
gca | application/x-gca-compressed | src | application/x-wais-source |
gdb | x-lml/x-gdb | stk | application/hyperstudio |
gif | image/gif | stm | audio/x-mod |
gps | application/x-gps | sv4cpio | application/x-sv4cpio |
gtar | application/x-gtar | sv4crc | application/x-sv4crc |
gz | application/x-gzip | svf | image/vnd |
hdf | application/x-hdf | svg | image/svg-xml |
hdm | text/x-hdml | svh | image/svh |
hdml | text/x-hdml | svr | x-world/x-svr |
hlp | application/winhlp | swf | application/x-shockwave-flash |
hqx | application/mac-binhex40 | swfl | application/x-shockwave-flash |
htm | text/html | t | application/x-troff |
html | text/html | tad | application/octet-stream |
hts | text/html | talk | text/x-speech |
ice | x-conference/x-cooltalk | tar | application/x-tar |
ico | application/octet-stream | taz | application/x-tar |
ief | image/ief | tbp | application/x-timbuktu |
ifm | image/gif | tbt | application/x-timbuktu |
ifs | image/ifs | tcl | application/x-tcl |
imy | audio/melody | tex | application/x-tex |
ins | application/x-NET-Install | texi | application/x-texinfo |
ips | application/x-ipscript | texinfo | application/x-texinfo |
ipx | application/x-ipix | tgz | application/x-tar |
it | audio/x-mod | thm | application/vnd.eri.thm |
itz | audio/x-mod | tif | image/tiff |
ivr | i-world/i-vrml | tiff | image/tiff |
j2k | image/j2k | tki | application/x-tkined |
jad | text/vnd.sun.j2me.app-descriptor | tkined | application/x-tkined |
jam | application/x-jam | toc | application/toc |
jar | application/java-archive | toy | image/toy |
jnlp | application/x-java-jnlp-file | tr | application/x-troff |
jpe | image/jpeg | trk | x-lml/x-gps |
jpeg | image/jpeg | trm | application/x-msterminal |
jpg | image/jpeg | tsi | audio/tsplayer |
jpz | image/jpeg | tsp | application/dsptype |
js | application/x-javascript | tsv | text/tab-separated-values |
jwc | application/jwc | tsv | text/tab-separated-values |
kjx | application/x-kjx | ttf | application/octet-stream |
lak | x-lml/x-lak | ttz | application/t-time |
latex | application/x-latex | txt | text/plain |
lcc | application/fastman | ult | audio/x-mod |
lcl | application/x-digitalloca | ustar | application/x-ustar |
lcr | application/x-digitalloca | uu | application/x-uuencode |
lgh | application/lgh | uue | application/x-uuencode |
lha | application/octet-stream | vcd | application/x-cdlink |
lml | x-lml/x-lml | vcf | text/x-vcard |
lmlpack | x-lml/x-lmlpack | vdo | video/vdo |
lsf | video/x-ms-asf | vib | audio/vib |
lsx | video/x-ms-asf | viv | video/vivo |
lzh | application/x-lzh | vivo | video/vivo |
m13 | application/x-msmediaview | vmd | application/vocaltec-media-desc |
m14 | application/x-msmediaview | vmf | application/vocaltec-media-file |
m15 | audio/x-mod | vmi | application/x-dreamcast-vms-info |
m3u | audio/x-mpegurl | vms | application/x-dreamcast-vms |
m3url | audio/x-mpegurl | vox | audio/voxware |
ma1 | audio/ma1 | vqe | audio/x-twinvq-plugin |
ma2 | audio/ma2 | vqf | audio/x-twinvq |
ma3 | audio/ma3 | vql | audio/x-twinvq |
ma5 | audio/ma5 | vre | x-world/x-vream |
man | application/x-troff-man | vrml | x-world/x-vrml |
map | magnus-internal/imagemap | vrt | x-world/x-vrt |
mbd | application/mbedlet | vrw | x-world/x-vream |
mct | application/x-mascot | vts | workbook/formulaone |
mdb | application/x-msaccess | wav | audio/x-wav |
mdz | audio/x-mod | wax | audio/x-ms-wax |
me | application/x-troff-me | wbmp | image/vnd.wap.wbmp |
mel | text/x-vmel | web | application/vnd.xara |
mi | application/x-mif | wi | image/wavelet |
mid | audio/midi | wis | application/x-InstallShield |
midi | audio/midi | wm | video/x-ms-wm |
mif | application/x-mif | wma | audio/x-ms-wma |
mil | image/x-cals | wmd | application/x-ms-wmd |
mio | audio/x-mio | wmf | application/x-msmetafile |
mmf | application/x-skt-lbs | wml | text/vnd.wap.wml |
mng | video/x-mng | wmlc | application/vnd.wap.wmlc |
mny | application/x-msmoney | wmls | text/vnd.wap.wmlscript |
moc | application/x-mocha | wmlsc | application/vnd.wap.wmlscriptc |
mocha | application/x-mocha | wmlscript | text/vnd.wap.wmlscript |
mod | audio/x-mod | wmv | audio/x-ms-wmv |
mof | application/x-yumekara | wmx | video/x-ms-wmx |
mol | chemical/x-mdl-molfile | wmz | application/x-ms-wmz |
mop | chemical/x-mopac-input | wpng | image/x-up-wpng |
mov | video/quicktime | wpt | x-lml/x-gps |
movie | video/x-sgi-movie | wri | application/x-mswrite |
mp2 | audio/x-mpeg | wrl | x-world/x-vrml |
mp3 | audio/x-mpeg | wrz | x-world/x-vrml |
mp4 | video/mp4 | ws | text/vnd.wap.wmlscript |
mpc | application/vnd.mpohun.certificate | wsc | application/vnd.wap.wmlscriptc |
mpe | video/mpeg | wv | video/wavelet |
mpeg | video/mpeg | wvx | video/x-ms-wvx |
mpg | video/mpeg | wxl | application/x-wxl |
mpg4 | video/mp4 | x-gzip | application/x-gzip |
mpga | audio/mpeg | xar | application/vnd.xara |
mpn | application/vnd.mophun.application | xbm | image/x-xbitmap |
mpp | application/vnd.ms-project | xdm | application/x-xdma |
mps | application/x-mapserver | xdma | application/x-xdma |
mrl | text/x-mrml | xdw | application/vnd.fujixerox.docuworks |
mrm | application/x-mrm | xht | application/xhtml+xml |
ms | application/x-troff-ms | xhtm | application/xhtml+xml |
mts | application/metastream | xhtml | application/xhtml+xml |
mtx | application/metastream | xla | application/vnd.ms-excel |
mtz | application/metastream | xlc | application/vnd.ms-excel |
mzv | application/metastream | xll | application/x-excel |
nar | application/zip | xlm | application/vnd.ms-excel |
nbmp | image/nbmp | xls | application/vnd.ms-excel |
nc | application/x-netcdf | xlt | application/vnd.ms-excel |
ndb | x-lml/x-ndb | xlw | application/vnd.ms-excel |
ndwn | application/ndwn | xm | audio/x-mod |
nif | application/x-nif | xml | text/xml |
nmz | application/x-scream | xmz | audio/x-mod |
nokia-op-logo | image/vnd.nok-oplogo-color | xpi | application/x-xpinstall |
npx | application/x-netfpx | xpm | image/x-xpixmap |
nsnd | audio/nsnd | xsit | text/xml |
nva | application/x-neva1 | xsl | text/xml |
oda | application/oda | xul | text/xul |
oom | application/x-AtlasMate-Plugin | xwd | image/x-xwindowdump |
pac | audio/x-pac | xyz | chemical/x-pdb |
pae | audio/x-epac | yz1 | application/x-yz1 |
pan | application/x-pan | z | application/x-compress |
pbm | image/x-portable-bitmap | zac | application/x-zaurus-zac |
pcx | image/x-pcx | zip | application/zip |
1、创建文件,可以在onActivity中接收到结果
// Here are some examples of how you might call this method.
// The first parameter is the MIME type, and the second parameter is the name
// of the file you are creating:
//
// createFile("text/plain", "foobar.txt");
// createFile("image/png", "mypicture.png");
// Unique request code.
private static final int WRITE_REQUEST_CODE = 43;
...
private void createFile(String mimeType, String fileName) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
// Filter to only show results that can be "opened", such as
// a file (as opposed to a list of contacts or timezones).
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Create a file with the requested MIME type.
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(intent, WRITE_REQUEST_CODE);
}
2、获取Uri之后,要是文件的Document.COLUMN_FLAGS
包含SUPPORTS_DELETE
,则可以删除该文件:
DocumentsContract.deleteDocument(getContentResolver(), uri);
3、编辑文件
private static final int EDIT_REQUEST_CODE = 44;
/**
* Open a file for writing and append some text to it.
*/
private void editDocument() {
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's
// file browser.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// Filter to only show results that can be "opened", such as a
// file (as opposed to a list of contacts or timezones).
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only text files.
intent.setType("text/plain");
startActivityForResult(intent, EDIT_REQUEST_CODE);
}
private void alterDocument(Uri uri) {
try {
ParcelFileDescriptor pfd = getActivity().getContentResolver().
openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream =
new FileOutputStream(pfd.getFileDescriptor());
fileOutputStream.write(("Overwritten by MyCloud at " +
System.currentTimeMillis() + "\n").getBytes());
// Let the document provider know you're done by closing the stream.
fileOutputStream.close();
pfd.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
4、检查最新的文件数据
final int takeFlags = intent.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(uri, takeFlags);
1、Android 7.0
在存储访问框架中添加了虚拟文件
的概念。
2、即使虚拟文件没有二进制
表示形式,您的客户端应用程序也可以通过将其强制转换为其他文件类型或使用ACTION_VIEW意图查看这些文件来打开其内容
。
3、要打开虚拟文件,您的客户端应用程序需要包含特殊的逻辑来处理它们。如果要获取文件的字节表示形式(例如,预览文件),则需要从文档提供者处请求其他MIME类型。
4、要在您的应用程序中获取虚拟文档的URI,首先要创建一个Intent以打开文件选择器UI
,就像前面在Seach中为文档显示的代码一样。
5、重要提示:由于应用无法使用openInputStream()方法直接打开虚拟文件
,因此,如果您在ACTION_OPEN_DOCUMENT意向中包括CATEGORY_OPENABLE类别,则您的应用将不会收到任何虚拟文件。用户做出选择后,系统将调用onActivityResult()方法,如先前在处理结果中所示。您的应用可以检索文件的URI,然后使用类似于以下代码片段的方法来确定文件是否为虚拟文件。验证文件为虚拟文件后,可以将其强制转换为其他MIME类型
,例如图像文件。以下代码段显示了如何检查虚拟文件是否可以表示为映像,如果可以,则从虚拟文件获取输入流。
private boolean isVirtualFile(Uri uri) {
if (!DocumentsContract.isDocumentUri(this, uri)) {
return false;
}
Cursor cursor = getContentResolver().query(
uri,
new String[] { DocumentsContract.Document.COLUMN_FLAGS },
null, null, null);
int flags = 0;
if (cursor.moveToFirst()) {
flags = cursor.getInt(0);
}
cursor.close();
return (flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0;
}
private InputStream getInputStreamForVirtualFile(Uri uri, String mimeTypeFilter)
throws IOException {
ContentResolver resolver = getContentResolver();
String[] openableMimeTypes = resolver.getStreamTypes(uri, mimeTypeFilter);
if (openableMimeTypes == null ||
openableMimeTypes.length < 1) {
throw new FileNotFoundException();
}
return resolver
.openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null)
.createInputStream();
}