Android 11 API 30及以上文件适配

292 阅读2分钟

起因

因为华为市场的要求,targetSdkVersion版本必须30及以上,因此我们不得不进行升级

问题

1.上传文件出现Android Operation not permitted的问题不能上传 产生原因是因为原来的 android.permission.READ_EXTERNAL_STORAGE权限在30及以上分为了三个权限

<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

因此我们拿不到完全的文件权限。因此为了上传文件能够成功就必须进行完全文件权限校验然后即可成功. 即为我们上传之前需要先行判断读写权限,还需要判断是否为完全授权

if (Environment.isExternalStorageManager()) {
    //做业务逻辑
} else {
    //跳转权限设置页面
    val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
    intent.data = Uri.parse("package:" + packageName)
    startActivity(intent)
}

image.png 这样之后即可正确上传

  1. 保存文件失败 即服务器给了我们一个path,我们需要下载保存,如果按照原来的逻辑则会保存失败。 在30以下我们用的保存逻辑
    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
     URL url = null;
     url = new URL(videoData.getCoverURL());
     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
     conn.setConnectTimeout(5000);
     pd.setMax(conn.getContentLength() / (1024 * 1024));
     InputStream inputStream = conn.getInputStream();
     // 创建视频保存请求
     ContentValues values = new ContentValues();
     values.put(MediaStore.Video.Media.DISPLAY_NAME, System.currentTimeMillis() + ".mp4");  // 视频文件名
     values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");  // 视频文件类型
     values.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM);  // 系统相册目录
    
     // 获取ContentResolver
     ContentResolver resolver = context.getContentResolver();
     // 插入视频文件
     Uri uri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
     if (uri!=null) {
         // 打开输出流
         OutputStream outputStream = resolver.openOutputStream(uri);
    
         if (outputStream != null) {
             // 将视频数据写入到输出流
             byte[] buffer = new byte[1024];
             int bytesRead;
             int total = 0;
             while ((bytesRead = inputStream.read(buffer)) != -1) {
                 outputStream.write(buffer, 0, bytesRead);
                 total += bytesRead;
                 pd.setProgress(total / (1024 * 1024));
             }
    
             // 关闭输入流和输出流
             outputStream.flush();
             outputStream.close();
             inputStream.close();
    
         }
     }
        //30以下
       // String path = Environment.getExternalStorageDirectory().getPath();
     //file = new File(path, System.currentTimeMillis() + ".mp4");
     //FileOutputStream fos = new FileOutputStream(url);
     //BufferedInputStream bis = new BufferedInputStream(is);
     //byte[] buffer = new byte[1024];
     //int len;
     //int total = 0;
     //while ((len = bis.read(buffer)) != -1) {
     //    fos.write(buffer, 0, len);
     //    total += len;
     //    pd.setProgress(total / (1024 * 1024));
     //}
     //fos.close();
     //bis.close();
     //is.close();
     pd.dismiss();
     ThreadUtils.runOnUiThread(new Runnable() {
         @Override
         public void run() {
             MToast.showToast("保存视频成功!");
         }
     });
     return file;
     } else {
     ThreadUtils.runOnUiThread(new Runnable() {
         @Override
         public void run() {
             MToast.showToast("保存视频失败!");
         }
     });
     return null;}
    
然后在30以下还需要把文件插入到相册中去

```context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + file.getAbsolutePath())));

如此就解决了文件保存和上传的问题