超简,超快速解决Android10的文件存储,和安装适配标题
安卓10的沙盒机制已经出来有一年多了,我就不介绍了,直奔主题。
最近在维护公司的几个项目,比较老了,都是用的v7v4库,所以在之前的大佬开发的时候安卓版本号还是10以下的,结果今天老板发现了在安卓10的设备上 在主应用程序中下载子应用程序会出错,更新也是,因为之前在学校的时候适配过安卓10的媒体文件的存储,所以一开始信心满满,结果就是踩了许多坑…
关于安卓10的文件存储建议看一下这篇文章,无论是媒体文件还是其他文件都描写的很详细:
https://blog.csdn.net/zhendong_hu/article/details/104921985
这篇文章里面介绍的多媒体存储有存储到公共目录和沙盒的,公共目录就是你点开相册是看得见的,存储到沙盒里点开相册是看不见的,一般是放在你程序的APP包里的,卸载APP图片也跟着一起卸载,还是挺安全和便于管理的。
然而里面存储到公共目录的方法只提到了使用ContentValues来进行操作,这有可能让一些下载框架主要是使用用File来进行操作感到头疼,所以咋们可以将uri转化为File,然后再将File转为String为保存路径来操作,话不多少,贴我自己一个小Demo里面的代码,也是以媒体文件为例子
public void saveSignImage(String fileName, Bitmap bitmap){try{//设置保存参数到ContentValues中ContentValues contentValues = new ContentValues();//设置文件名contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);//兼容Android Q和以下版本if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){//android Q中不再使用DATA字段,而用RELATIVE_PATH代替//RELATIVE_PATH是相对路径不是绝对路径//DCIM是系统文件夹,关于系统文件夹可以到系统自带的文件管理器中查看,不可以写没存在的名字contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/signImage"); //表示在DCIM下创建自己的signImage文件夹,名字可以自定义//contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "Music/signImage");} else{contentValues.put(MediaStore.Images.Media.DATA, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());}//设置文件类型contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/PNG");//这个MIME类型可以百度,百度上基本上所有类型怎么写都有//执行insert操作,向系统文件夹中添加文件//EXTERNAL_CONTENT_URI代表外部存储器,该值不变Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); //生成UriFile ff=uritoFile(uri); //这里调用了uri转file的方法,会贴在下面Log.d("123",ff.toString());//可以像我这样去打印日志观察if (uri != null){//若生成了uri,则表示该文件添加成功//使用流将内容写入该uri中即可// OutputStream outputStream = getContentResolver().openOutputStream(uri); 这是之前使用uri操作的FileOutputStream fos=new FileOutputStream(ff.toString());if (fos != null){bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);fos.flush();fos.close();}}}catch (Exception e){}}//uri转file的方法,很多论坛都有public File uritoFile(Uri uri,Context context){String[] arr = {MediaStore.Images.Media.DATA};Cursor cursor = context.getContentResolver().query(uri, arr, null, null, null); int imgIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);cursor.moveToFirst();String imgPath = cursor.getString(imgIndex);File file = new File(imgPath);return file;}
接下来就是重头戏了,
关于安卓10的文件安装,这里为什么没有提到下载呢,因为我在一开始是配的时候也以为是下载的问题,结果看了一下目录结构,apk是下载下来的,但是安装的界面系统却调用吧出来?!(在安卓10的设备上)
这是之前公司程序员自定义的目录,使用的是老的Environment.getExternalStorageDirectory()的方法获得保存路径,不过由于是自定义的目录,也下载下来了
然后这是我用的谷歌推荐的 getExternalFilesDir(type字段),把下载的APK保存到私人目录,也就是APP专属目录,里面也是下载下来的,却安装不上
然后我就在日志里面找啊找,一共出现了几个错误,然后冷静思考了下,既然系统没有给我调出安装界面,那一定就是安装的问题,所以定位到了这个错误
什么?!竟然说找不到这个Acitivity?明明已经把APK下载下来了啊,按理来说APK里面是有相关资源的,所以答案只有一个,没有扫描到我所在的文件夹里的文件!!然后我就把从异常那里到file:///那里复制下来 百度一下~
然后我想说的都在这个链接里面啦!↓↓↓↓↓
https://blog.csdn.net/u012881042/article/details/103890475/
额,里面所说的在res/xml里创建xml文件就是在res里创建个xml目录,然后在下面创建一个values xml文件~
提一嘴:谷歌是支持文件存储到自定义目录和沙盒目录里面的,安全性这方面在往IOS靠近,还是可以的(谷歌真坑)…
打完收工~