android Q出来之后 我去官网上看了一下androidQ 具体权限变更,存储权限改变比较大的,官方建议是 沙盒存储不用申请权限,这有点和ios的相似,好处呢就是app卸载之后 在app内下载的图片也都随之消失,因为androidQ的沙盒是在app的目录下创建的保存文件的一个文件夹app内下载图片或者文件都会保存到这个目录,使用这个进行版本比较就好了,当然也可以不使用这个沙盒存储方式,就是绝对路径
首先 还是要添加 权限
第二步
String sdCardDir = Environment.getExternalStorageDirectory() + "/DCIM/"; File appDir = new File(sdCardDir, "文件夹"); if (!appDir.exists()) {//不存在 appDir.mkdir(); } String fileName = "文件夹名" + System.currentTimeMillis() + ".jpg"; myCaptureFile = new File(appDir, fileName); try { FileOutputStream fos = new FileOutputStream(myCaptureFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri uri = Uri.fromFile(myCaptureFile); intent.setData(uri); getActivity().sendBroadcast(intent);
绝对路径可以适配Android多个版本,
上面是存储文件我们使用绝对路径 那么选取图片一样也是绝对路径,
比如我们在修改头像的时候 通过 onActivityResult ,Uri uri = data.getData();获取uri 我这里有一个工具类 贴出来
public class FileUtil { /** * 根据URI获取文件真实路径(兼容多张机型) * @param context * @param uri * @return */ public static String getFilePathByUri(Context context, Uri uri) { if ("content".equalsIgnoreCase(uri.getScheme())) { int sdkVersion = Build.VERSION.SDK_INT; if (sdkVersion >= 19) { // api >= 19 return getRealPathFromUriAboveApi19(context, uri); } else { // api < 19 return getRealPathFromUriBelowAPI19(context, uri); } } else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * 适配api19及以上,根据uri获取图片的绝对路径 * * @param context 上下文对象 * @param uri 图片的Uri * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null */ @SuppressLint("NewApi") public static String getRealPathFromUriAboveApi19(Context context, Uri uri) { String filePath = null; if (DocumentsContract.isDocumentUri(context, uri)) { // 如果是document类型的 uri, 则通过document id来进行处理 String documentId = DocumentsContract.getDocumentId(uri); if (isMediaDocument(uri)) { // MediaProvider // 使用':'分割 String type = documentId.split(":")[0]; String id = documentId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=?"; String[] selectionArgs = {id}; // Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } filePath = getDataColumn(context, contentUri, selection, selectionArgs); } else if (isDownloadsDocument(uri)) { // DownloadsProvider Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId)); filePath = getDataColumn(context, contentUri, null, null); }else if (isExternalStorageDocument(uri)) { // ExternalStorageProvider final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { filePath = Environment.getExternalStorageDirectory() + "/" + split[1]; } }else { //Log.e("路径错误"); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { // 如果是 content 类型的 Uri filePath = getDataColumn(context, uri, null, null); } else if ("file".equals(uri.getScheme())) { // 如果是 file 类型的 Uri,直接获取图片对应的路径 filePath = uri.getPath(); } return filePath; } /** * 适配api19以下(不包括api19),根据uri获取图片的绝对路径 * * @param context 上下文对象 * @param uri 图片的Uri * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null */ private static String getRealPathFromUriBelowAPI19(Context context, Uri uri) { return getDataColumn(context, uri, null, null); } /** * 获取数据库表中的 _data 列,即返回Uri对应的文件路径 * * @return */ private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { String path = null; String[] projection = new String[]{MediaStore.Images.Media.DATA}; Cursor cursor = null; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(projection[0]); path = cursor.getString(columnIndex); } } catch (Exception e) { if (cursor != null) { cursor.close(); } } return path; } /** * @param uri the Uri to check * @return Whether the Uri authority is MediaProvider */ private static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } private static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri the Uri to check * @return Whether the Uri authority is DownloadsProvider */ private static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } } 使用上面的工具类 String filePathByUri = FileUtil.getFilePathByUri(this, uri); 取到真是路径并上传到server,这个方法有好处有坏处,建议还是更具官方给的方法做是最好的,沙盒那种方式确实是不错的,不然一些app会造出很多垃圾图片,占用内存