Andorid 9.0 无Mounted情况下,DocumentFile读写U盘

在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());

读写。

猜你喜欢

转载自blog.csdn.net/Angle_Byron/article/details/129561969
今日推荐