android 9.0以上版本,获取U盘路径的两种方式

本文介绍了在Android 9.0及以上版本中获取U盘路径的两种方法:一是利用DocumentProvider,二是使用StorageManager,并提示若StorageManager方法不可用,可能需要借助反射技术。

第一种,通过DocumentProvider:

private void handleDocumentsProvider() {
    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);
        String flags = getCursorString(cursor, DocumentsContract.Root.COLUMN_FLAGS);
        DocumentPathBean documentPathBean = new DocumentPathBean(rootId, title, documentId, availableBytes, flags, "/storage/" + rootId);

        Log.e(TAG, "rootId:" + rootId + "flags:" + flags);
        if(!"primary".equals(rootId) && !"home".equals(rootId)){
        Log.e(TAG, "rootId:" + rootId + "title:" + title
                +"summary:" + summary +"documentId:" + documentId +"availableBytes:" + availableBytes +"capacityBytes:" + capacityBytes +"mimeTypes:" + mimeTypes);
        }
    }


}

第二种,通过StorageManager,无法使用的记得用反射;

    private HashMap<String, String> getUsbDrivePath() {

        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) {
                File path = volume.getPathFile();

                if (volume.isPrimary()) {
                    Log.v("storageVolume:", "put desc primary");
//                    pathMap.put("primary",path.getAbsolutePath());
                } else {
                    String state = volume.getState();
                    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:", "put desc " + volume.getDescription(DocumentActivity.this) + "volume.isPrimary:" + volume.isPrimary());
//                String mediaStoreVolumeName = storageVolume.getMediaStoreVolumeName();
//                String absolutePath = storageVolume.getDirectory().getAbsolutePath();


                }


            }


        });

        return paths;

    }
Android 9.0 及以上版本,为了进一步增强应用程序的安全性,Android 引入了更严格的后台限制,禁止所有未在前台运行的应用程序启动服务。如果您想在后台启动服务,需要使用 `startForegroundService()` 方法,并且需要在 5 秒钟内调用 `startForeground()` 方法将服务设置为前台服务。 以下是一个使用 `startForegroundService()` 和 `startForeground()` 的示例代码: ``` if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 创建一个 NotificationChannel NotificationChannel channel = new NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT); // 向系统注册 NotificationChannel NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } // 创建一个 Intent,启动你的服务 Intent serviceIntent = new Intent(this, YourService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 在 Android 9.0 及以上版本上,需要调用 startForegroundService() 方法启动服务。 startForegroundService(serviceIntent); // 在启动服务后,5 秒钟内调用 startForeground() 方法将服务设置为前台服务。 // 如果在 5 秒钟内没有调用 startForeground() 方法,系统会认为服务无法正常启动,会抛出异常。 new Handler().postDelayed(new Runnable() { @Override public void run() { startForeground(1, new Notification()); } }, 5000); } else { // 在 Android 9.0 以下版本上,可以直接调用 startService() 方法启动服务。 startService(serviceIntent); } ``` 注意:在 Android 9.0 及以上版本上,如果你使用的是 `startForeground()` 方法,会在 5 秒钟后抛出 `ANR` 异常,因为 Android 9.0 及以上版本要求服务必须在 5 秒钟内设置为前台服务。如果你想在后台运行服务,必须使用 `startForegroundService()` 和 `startForeground()` 方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值