Android 10文件存储适配

Android 10文件存储适配,第1张

概述Android10文件存储适配安卓Q即安卓10.0已经发布多时,不过大多数开发者并没有真机去测试,最近各厂商系统陆续推送了10.0的升级,因此必须要考虑去适配10.0系统了(建议大家先查看安卓Q系统权限变更相关文章,这里只说存储权限的适配方法,不做详细介绍)!关于10.0系统权限方面的改变,大家可 AndroID 10文件存储适配

安卓Q即安卓10.0已经发布多时,不过大多数开发者并没有真机去测试,最近各厂商系统陆续推送了10.0的升级,因此必须要考虑去适配10.0系统了(建议大家先查看安卓Q系统权限变更相关文章,这里只说存储权限的适配方法,不做详细介绍)!

关于10.0系统权限方面的改变,大家可以搜索相关文章,这里主要讲一下存储权限的变化,10.0之前我们在保存或者查询文件时,首先需要申请存储权限:

  <uses-permission androID:name="androID.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission
        androID:name="androID.permission.WRITE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />

但是,在10.0(targetSdkVersion=29)系统中,该权限已经不再起作用。应用中的行为表现为,即便你开启了存储权限,当你检测是否开启时,返回的结果是未开启,所以当你在把targetSdkVersion设为29或更高时,就一定要考虑这个问题了!对于暂时不想适配的,又不影响应用运行的方法,其它文章也有介绍,比如:targetSdkVersion设置为29以下,以及:

<application androID:allowExternalStorageSandBox="false" ... >
  </application>

等,但这些方法都是暂时的,过后的版本,不论你怎么设置,都无法再使用10.0以前的文件存储方式了,也就是说你必须要适配安卓Q即10.0!

Q的存储方式变化,即引入了沙盒机制,应用可以随意访问自身在沙盒内创建的文件夹及文件,不需要任何权限,且在沙盒内创建的文件夹及文件会随着应用的卸载一并删除。沙盒路径为:

内部存储/AndroID/data/com.xx.xx(应用包名)/files/


当你为应用创建沙盒文件时,可去这里查看!

需要注意的是,沙盒里的文件并不能对外显示,比如Q以前,我们保存图片后,去相册里查看,立马就能看到刚刚保存的图片,但在Q系统中,保存图片到沙盒后,再去相册中查看是看不到的,这里需要一个骚 *** 作,是保存到沙盒中后,需要再手动复制一份到公共文件夹中(公共文件夹包括:Downloads、documents、Pictures 、DCIM、MovIEs、Music、ringtones 等),在公共文件夹中创建的文件在应用卸载时是不会被删除的。

因此,我们在保存图片,音视频,其它文件时,需要对外显示的,就可以复制一份到相应的公共文件夹,不需要对外显示的就不用动,应用内部显示自己保存的内容时,就直接访问自己的沙盒中的目录就可以了!

具体方法:
保存图片:

String filepath=context.getExternalfilesDir(Environment.DIRECTORY_PICTURES) + "/" + 自己定义的文件夹名称+ "/";
String filename="xxx.png";
file imagefile = new file(filepath, filename);//这一步,系统会自动为你在沙盒中创建文件夹
...此处为保存(下载)图片的方法...

String filepath=context.getExternalfilesDir(Environment.DIRECTORY_PICTURES) + "/" + 自己定义的文件夹名称+ "/";
String filename="xxx.png";
file imagefile = new file(filepath, filename);//这一步,系统会自动为你在沙盒中创建文件夹
...此处为保存(下载)图片的方法...


下载完成后,可以去上述文件夹路径查看是否保存成功!若要对外显示,则需要复制到公共文件夹:

    @RequiresAPI(API = Build.VERSION_CODES.Q)
    public static voID copyPrivateimgToCommen(Context context, String orgfilePath, String displayname) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.files.fileColumns.disPLAY_name, displayname);
        values.put(MediaStore.files.fileColumns.Title, displayname);
        values.put(MediaStore.files.fileColumns.MIME_TYPE, "image/*");
        values.put(MediaStore.Images.Media.relative_PATH, Environment.DIRECTORY_PICTURES + "/" + 自己定义的文件夹名称);
        Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        ContentResolver resolver = context.getContentResolver();
        Uri insertUri = resolver.insert(external, values);
        inputStream ist = null;
        OutputStream ost = null;
        try {
            ist = new fileinputStream(new file(orgfilePath));
            if (insertUri != null) {
                ost = resolver.openOutputStream(insertUri);
            }
            if (ost != null) {
                byte[] buffer = new byte[4096];
                int byteCount = 0;
                while ((byteCount = ist.read(buffer)) != -1) {
                    ost.write(buffer, 0, byteCount);
                }
            }
        } catch (IOException e) {

        } finally {
            try {
                if (ist != null) {
                    ist.close();
                }
                if (ost != null) {
                    ost.close();
                }
            } catch (IOException e) {

            }
        }
    }


此方法参考自其它开发者文章,主要在于这几个字段:
MediaStore.files.fileColumns.MIME_TYPE:文件类型,图片即“image/”,视频即“vIDeo/”,
MediaStore.Images.Media.relative_PATH:存储路径,图片即MediaStore.Images,视频即MediaStore.VIDeo。
注意:即便是在自己的沙盒中,保存图片和视频等,也要根据文件类型,选择对应的文件夹如:Environment.DIRECTORY_PICTURES或者Environment.DIRECTORY_MOVIES。

保存视频:方法同保存图片,但要注意区分文件类型及存储路径!

如何查询自己保存的文件?以图片为例:

            file privatefile = getExternalfilesDir(Environment.DIRECTORY_PICTURES + "/自己定义的文件夹名称");
            file[] files = privatefile.Listfiles();
            if (files != null) {
                for (file file : files) {
                     //file 即你保存的图片文件
                }
            }

其它类型,就取对应的Environment.DIRECTORY_路径!

写在最后,以上方法都是在Q系统下的 *** 作方法,适配时需要判断系统版本号,Build.VERSION.SDK_INT<Q时,依然要申请存储权限,并按Q之前的 *** 作方法去 *** 作,>=Q时,则无需再申请权限,按Q *** 作方式 *** 作即可!

 

补充:
安卓Q如何进行选择相册和拍照呢?又如何进行文件上传 *** 作呢?

如果只用来显示,那么只需要获取到图片/视频Uri就可以了,但是如果要获取到file进行上传 *** 作呢?如果你还是用Q以前的方法:file file=new file(path);的话你会发现,根本无法获取到这个文件,我们只能通过曲线救国的方法,即拍照和选取相册完成后,得到图片uri,并通过该uri转成file的形式,将file保存在沙盒文件夹内,然后再去沙盒文件夹内取file,再上传!也就是需要把你要上传的文件复制一份到沙盒…呵呵!

另外,拍照时调用相机方法有变化,需要判断系统版本号,Q系统需要通过Uri形式获取到拍照结果:

            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.disPLAY_name, filename);
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/*");
            values.put(MediaStore.Images.Media.relative_PATH, Environment.DIRECTORY_PICTURES);
            uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

需要记录这个Uri,拍照结果在onActivityResult中获取:
Q系统通过url转file的形式得到图片路径:

    public static String uriTofile(Context context, Uri uri, String privatefilename) {
        file privatefile = new file(getimagePathCache(context), privatefilename + ".png");
        file fileParent = privatefile.getParentfile();
        if (!fileParent.exists()) {
            fileParent.mkdirs();
        }
        if (privatefile.exists()) return privatefile.getabsolutePath();
        inputStream ist = null;
        OutputStream ost = null;
        try {
            privatefile.createNewfile();
            ist = context.getContentResolver().openinputStream(uri);
            ost = new fileOutputStream(privatefile);
            byte[] buffer = new byte[4096];
            int byteCount = 0;
            while ((byteCount = ist.read(buffer)) != -1) {  // 循环从输入流读取 buffer字节
                ost.write(buffer, 0, byteCount);        // 将读取的输入流写入到输出流
            }
        } catch (IOException e) {
            return "";
        } finally {
            try {
                if (ist != null) {
                    ist.close();
                }
                if (ost != null) {
                    ost.close();
                }
            } catch (IOException e) {
                return "";
            }
        }
        return privatefile.getabsolutePath();
    }

其中的getimagePathCache方法就是你的沙盒文件夹路径:

context.getExternalfilesDir(Environment.DIRECTORY_PICTURES) + "/cache/";//cache是自定义的文件夹名称

相册选择结果同样在onActivityResult中获取:
相册选择的结果可以直接通过onActivityResult方法返回的intent.getData()获取,然后调用上述uri转file方法,得到图片路径!

如果考虑这种缓存文件占用内存空间,则在使用后删除即可!


原文链接:https://blog.csdn.net/baiyuliang2013/article/details/103735264

总结

以上是内存溢出为你收集整理的Android 10文件存储适配全部内容,希望文章能够帮你解决Android 10文件存储适配所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1003731.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存