在android9.0下FileProvider只是为了隐私传递,并不能直接创建,复制,移动文件。
操作一般在primary sd卡下,如果需要操作U盘,需要授权
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MANAGE_DOCUMENTS" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_MEDIA" />
//读写权限 private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_PERMISSION_CODE); } }
第二步获取U盘路径:U盘读写权限,然后进行路径授权操作,这个路径是针对此路径的授权,所以,最好申请根路径:
Intent intent1 = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
StorageManager sm = getSystemService(StorageManager.class);
// 这里的路径,UUID是根据查询数据库得到,或者通过StorageManager,具体获得看第三步骤
StorageVolume volume = sm.getStorageVolume(new File("/storage/" + UUID));
if (volume != null) {
intent1 = volume.createAccessIntent(null)
}
}
if (intent == null) {
intent1 = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
}
intent1.setAction(Intent.ACTION_OPEN_DOCUMENT_TREE); intent1.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(intent1, OPEN_DOCUMENT_TREE_CODE);
附:获取U盘UUID路径获取代码,自己编译framework或者用反射:
(1)方法一 String authority = "com.android.externalstorage.documents"; final Uri rootsUri = DocumentsContract.buildRootsUri("com.android.externalstorage.documents"); ContentResolver resolver = getContentResolver(); final ContentProviderClient client = resolver.acquireUnstableContentProviderClient( authority); final PackageManager pm = getPackageManager(); ProviderInfo provider = pm.resolveContentProvider( authority, PackageManager.GET_META_DATA); if (provider == null) { Log.w(TAG, "Failed to get provider info for " + authority); } if (!provider.exported) { Log.w(TAG, "Provider is not exported. Failed to load roots for " + authority); } if (!provider.grantUriPermissions) { Log.w(TAG, "Provider doesn't grantUriPermissions. Failed to load roots for " + authority); } if (!android.Manifest.permission.MANAGE_DOCUMENTS.equals(provider.readPermission) || !android.Manifest.permission.MANAGE_DOCUMENTS.equals(provider.writePermission)) { Log.w(TAG, "Provider is not protected by MANAGE_DOCUMENTS. Failed to load roots for " + authority); } Cursor cursor = null; try { cursor = client.query(rootsUri, null, null, null, null); } catch (RemoteException e) { e.printStackTrace(); } while (cursor.moveToNext()) { String rootId = getCursorString(cursor, DocumentsContract.Root.COLUMN_ROOT_ID); String title = getCursorString(cursor, DocumentsContract.Root.COLUMN_TITLE); String summary = getCursorString(cursor, DocumentsContract.Root.COLUMN_SUMMARY); String documentId = getCursorString(cursor, DocumentsContract.Root.COLUMN_DOCUMENT_ID); long availableBytes = getCursorLong(cursor, DocumentsContract.Root.COLUMN_AVAILABLE_BYTES); long capacityBytes = getCursorLong(cursor, DocumentsContract.Root.COLUMN_CAPACITY_BYTES); String mimeTypes = getCursorString(cursor, DocumentsContract.Root.COLUMN_MIME_TYPES); // if("primary".equals(rootId)){ Log.e(TAG, "rootId:" + rootId + "title:" + title +"summary:" + summary +"documentId:" + documentId +"availableBytes:" + availableBytes +"capacityBytes:" + capacityBytes +"mimeTypes:" + mimeTypes); // } }
(2)方法二
final StorageManager sm = getSystemService(StorageManager.class); final List<StorageVolume> volumes = sm.getStorageVolumes(); HashMap<String, String> paths = new HashMap<>();
volumes.forEach(new Consumer<StorageVolume>() { @Override public void accept(StorageVolume volume) { String state = volume.getState();
if (!volume.isPrimary()){ File path = volume.getPathFile(); Log.v("storageVolume:", "path" + path.exists()); Log.v("storageVolume:", "path isDirectory" + path.isDirectory()); Log.v("storageVolume:", "path isFile " + path.isFile()); Log.v("storageVolume:", "path " + path.getAbsolutePath()); Log.v("storageVolume:", "UUID: " + volume.getUuid()) } }
最后。我们就可以增删改查文件了,到目前,U盘路径获取,授权都已经OK,下面进行操作U盘,增删改查
protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case OPEN_DOCUMENT_TREE_CODE: if (data != null && data.getData() != null) { Uri uri = data.getData(); Log.i(TAG,"DocumentsUtils.OPEN_DOCUMENT_TREE_CODE : " + uri); getUsbDrivePath(uri); } break; } super.onActivityResult(requestCode, resultCode, data); }
private void getUsbDrivePath(Uri uri) { DocumentFile uRootFile = DocumentFile.fromTreeUri(MainActivity.this,uri); uRootFile.listFiles(); //所有文件 uRootFile.findFile("文件名");//查找文件 uRootFile.findFile("文件名").delete();//删除文件 Uri fileUrl = uRootFile.findFile("").getUri(); InputStream inputStream = getContentResolver().openInputStream(fileUrl);//读写文件 createFile 创建文件 createDirectory创建文件夹 delete() 删除 }
InputStream inputStream = mContext.getContentResolver().openInputStream(documentFIle.getUri()); OutputStream outputStream = mContext.getContentResolver().openOutputStream(documentFIle.getUri());
读写。