• Android分区存储相关


    参考链接https://blog.csdn.net/guolin_blog/article/details/105419420/

    Android 10 作用域存储(分区存储)

    Android的外置存储特点

    • 存储在SD卡的文件不会计入到应用程序的占用空间当中,也就是说即使你在SD卡存放了1G的文件,你的应用程序在设置中显示的占用空间仍然可能只有几十K。
    • 存储在SD卡的文件,即使应用程序被卸载了,这些文件仍然会被保留下来,这有助于实现一些需要数据被永久保留的功能。

    对用户的影响

    • 这会将用户的SD卡空间搞得乱糟糟的,而且即使卸载一个完全不再使用的程序,它所产生的垃圾文件却可能会一直保留在我的手机上。
    • 存储在SD卡上的文件属于公有文件,所有的应用程序都有权随意访问,这也对数据的安全性带来了很大的挑战。

    Android的分区存储特点

    • 从Android 10开始,每个应用程序只能有权在自己的外置存储空间关联目录下读取和创建文件
    • 读取手机相册的内容(图片、音频、视频),要使用MediaStore来进行访问,访问其他文件要通过系统的文件选择器。
    • 自己的应用向手机媒体库提供的内容可以不申请权限直接访问,但是要访问媒体库其他内容就要申请READ_EXTERNAL_STORAGE。
    • WRITE_EXTERNAL_STORAGE权限将会在未来的Android版本中废弃

    适配问题

    • 对于targetSdkVersion < 29 的应用来说可以不做分区存储的适配,也可以正常运行在Android10的手机上。
    • 对于targetSdkVersion >= 29 的应用来说可以在Manifest中申请android:requestLegacyExternalStorage="true"
      这只是一种权宜之计,在未来的Android系统版本中,这段配置随时都可能会失效。

    获取相册中的图片示例

    • 申请读取权限
    // 从图库中挑选一张图片 并返回图片的uri
    Intent  intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
            startActivityForResult(intent, GET_PIC);
    
            // uri为onActivityResult()成功返回的Intent.getData;
            ImageDecoder.Source source = ImageDecoder.createSource(getContext().getContentResolver(), uri);
            Drawable drawable = ImageDecoder.decodeDrawable(source);
            fragmentBlinkBinding.rlBackPic.setBackground(drawable);
    
    //打印图库中所有图片的uri
     ContentResolver contentResolver = getContentResolver();
            Cursor query = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null);
            if(query != null){
                while (query.moveToNext()){
                    long id = query.getLong(query.getColumnIndexOrThrow(MediaStore.MediaColumns._ID));
                    Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
                    System.out.println(uri);
                }
                query.close();
            }
    //uri示例
    content://media/external/images/media/195430
    

    拿到uri以后显示图片操作举例

    • 使用Glide加载图片
    Glide.with(context).load(uri).into(imageView);
    
    • 使用ImageDecoder类
            @RequiresApi(api = Build.VERSION_CODES.P)
            ImageDecoder.Source source = ImageDecoder.createSource(getContext().getContentResolver(), uri);
            Drawable drawable = ImageDecoder.decodeDrawable(source);
            fragmentBlinkBinding.rlBackPic.setBackground(drawable);
    
    • 使用Bitmap
            ParcelFileDescriptor r = contentResolver.openFileDescriptor(uri, "r");
            Bitmap bitmap = BitmapFactory.decodeFileDescriptor(r.getFileDescriptor());
            r.close();
            imageView.setImageBitmap(bitmap);
    

    从网络加载一张图片放入图库

    索引 含义 是否必须
    DISPLAY_NAME 文件名称
    MIME_TYPE 文件类型
    RELATIVE_PATH 相对路径 跟绝对路径二选一
    MediaStore.MediaColumns.DATA 绝对路径 跟相对路径二选一
    MIME_TYPE 可以通过查询
       ContentValues contentValues = new ContentValues();
                    contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "aa.png");
                    contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
                        contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
                    else
                        contentValues.put(MediaStore.MediaColumns.DATA, Environment.getExternalStorageDirectory().getPath() + "/" + Environment.DIRECTORY_DCIM + "/" + "");
                    // 插入图片的uri,此时文件为空
                    Uri insert = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
                    if (insert != null) {
                        try {
                          URL url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603617504519&di=9b6a431f0de43d87593286bd0f79e504&imgtype=0&src=http%3A%2F%2Fh.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2F0dd7912397dda144dac4acc9b2b7d0a20df486f8.jpg");
                            try (OutputStream outputStream = getContentResolver().openOutputStream(insert); InputStream inputStream = url.openStream()) {
                                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
                                BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
                                byte[] bytes = new byte[1024];
                                int var;
                                while ((var = bufferedInputStream.read(bytes)) >= 0) {
                                    bufferedOutputStream.write(bytes,0,var);
                                    bufferedOutputStream.flush();
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                        }
                    }
                }
    

    DIRECTORY_MUSIC 音乐目录

    DIRECTORY_PICTURES 图片目录

    DIRECTORY_MOVIES 电影目录

    DIRECTORY_DOWNLOADS 下载目录

    DIRECTORY_DCIM 相机拍照或录像文件的存储目录

    DIRECTORY_DOCUMENTS 文件文档目录

    存储技巧就是可以在存储时直接将自己应用的所有图片放在同一个文件夹下,只需修改路径在DCIM+"/"+"自己的文件夹名字"+"/"。

  • 相关阅读:
    飞机游戏
    nodejs制作爬虫程序
    关于解析字符串
    引用nodejs的url模块实现url路由功能
    appium定位学习
    appium移动端自动化测试的一些感想
    appium的工作原理
    appium desktop 定位弹出框时报错
    APPium连接真机输入框中输入的内容与代码中不一致
    appium 链接真机后,运行代码,但是APP并没有启动
  • 原文地址:https://www.cnblogs.com/FCY-LearningNotes/p/13873394.html
Copyright © 2020-2023  润新知