安卓内外部存储完全解析 -- 别再弄混了

安卓内外部存储完全解析 -- 别再弄混了,第1张

安卓开发离不开手机存储,然而大部分人对于安卓开发中的存储概念存在误区,内部外部SD卡傻傻分不清?

以下引用来自对 官方文档 的理解

呵呵呵,先别说话,然而重点来了(敲黑板),按照官方的说法,

内部存储是指系统的存储空间,没有root是访问不到的呦亲,比如sharedPreferenced或者database都是保存在这里面的。

外部存储,又分为 2 部分:

然而现实中,常常有同事把手机那个32G,64G存储叫做内部存储= =,宝宝好累,人家明明是 ExternalStorage !!

希望本篇能让大家对内外部存储有一个正确鲜明的认识

getFilesDir()

路径如下

文档 云:若想 *** 作该路径,你需要一个输出流:

就像这样:

注: this 是 context 对象

路径下会看到新文件

如果你还想读取的话, 文档 云:你需要一个输入流:

Log如下

getCacheDir()

文档 云:

路径如下:

特别的,还有getDir() :

getDir("- -!txt", ContextMODE_PRIVATE)getAbsolutePath()

路径如下:

app_是系统自己加上去的

内部存储就是系统的存储,没有root你是看不到的,内部存储最大特点就是可以用Context对象调用各个获取路径的方法。比如: contextfileList()

那就是

下的文件遍历。

而 deleteFile("ABC") 就是

删除下名为 ABC 的文件

</br></br></br>

*** 作外部存储你首先需要以下权限

当你申请了write权限,那么read权限默认也就通过啦

再判断状态:

if (EnvironmentMEDIA_MOUNTEDequals(EnvironmentgetExternalStorageState))

EnvironmentgetExternalStorageDirectory()

这个路径根据手机厂家不同会有些许变化

直接传入 Environment 中的常量获取相应的路径,如下:

EnvironmentgetExternalStoragePublicDirectory(EnvironmentDIRECTORY_ALARMS));

或者

EnvironmentgetExternalStoragePublicDirectory(EnvironmentDIRECTORY_PICTURES));

公有目录下,系统会区分不同类别 (例如铃声在系统设置中显示为铃声而不是音乐)

44以后访问该目录不再需要权限了

getExternalFilesDir(String type)

eg

getExternalFilesDir(EnvironmentDIRECTORY_MUSIC)

特别的:ContextCompat下的

ContextCompatgetExternalFilesDirs(context,type)

返回一个File[],在44以后第一条数据默认外部主存储目录,第二条数据就是sd卡路径啦,但是注意44之前是没有第二条数据的哦

该目录下的特点是卸载程序后,该目录和其下所有文件均会被删除

getExternalCacheDir()

注意,使用该目录注意管理空间,你不能等系统帮你清理,而是自己清理不再需要的缓存

特别的:ContextCompat下的

ContextCompatgetExternalCacheDirs()

道理同上

发现特点了吗朋友,无论外部内部,只有路径中有包名,那么就是私有的,而且是随着程序的卸载而被删除的, 有包名的路径均是Context中的方法,而公有的路径均是Environment调用的

这个货真真是要了老命,一般的方法根部不好使,结合网上有的方法加上公司项目中的方法,总结如下:

百分百好用的获取SD卡路径方法:

最后集合 path 中的值就是SD卡根目录

虽然无视版本百分百好用,但是如果你的手机有SD卡槽却没插SD卡,该方法最后 path 返回的是 null ,也就是说该方法无法判断到底是没插SD卡还是根本不支持SD卡

其实还有一种方法

String path = Systemgetenv("SECONDARY_STORAGE");

该方法只要你手机支持SD卡,无论你插没插SD卡,均会返回SD卡路径,但是 60及以上该方法被移除

Environment中源码其实就是根据这个方法获取路径的

安卓官方文档大家一定要看,他就是我们开发者的权威呀,圣经呀!!

pathclassloader和dexclassloader的区别如下:

1DexClassLoader和PathClassLoader都属于符合双亲委派模型的类加载器(因为它们没有重载loadClass方法)。也就是说,它们在加载一个类之前,回去检查自己以及自己以上的类加载器是否已经加载了这个类。如果已经加载过了,就会直接将之返回,而不会重复加载。

2DexClassLoader和PathClassLoader其实都是通过DexFile这个类来实现类加载的。这里需要顺便提一下的是,Dalvik虚拟机识别的是dex文件,而不是class文件。因此,我们供类加载的文件也只能是dex文件,或者包含有dex文件的apk或jar文件。

3PathClassLoader是通过构造函数new DexFile(path)来产生DexFile对象的;而DexClassLoader则是通过其静态方法loadDex(path, outpath, 0)得到DexFile对象。这两者的区别在于DexClassLoader需要提供一个可写的outpath路径,用来释放apk包或者jar包中的dex文件。换个说法来说,就是PathClassLoader不能主动从zip包中释放出dex,因此只支持直接 *** 作dex格式文件,或者已经安装的apk(因为已经安装的apk在cache中存在缓存的dex文件)。而DexClassLoader可以支持apk、jar和dex文件,并且会在指定的outpath路径释放出dex文件。

4另外,PathClassLoader在加载类时调用的是DexFile的loadClassBinaryName,而DexClassLoader调用的是loadClass。因此,在使用PathClassLoader时类全名需要用”/”替换””

最近App在android11上出现了一个诡异的native 崩溃,很不容易出现,但都是有个特点就是安装App后过一段时间才会出现,杀进程没用,覆盖安装同一个apk,崩溃立刻消失,日志为如下:

搜索系统art源码中抛出异常的地方:

发现大致意思就是,我们App中集成了framwwork的androidnetwifiIWifiScanner这个类,在系统dexopt之后发生了内联优化,导致这个系统的类被内敛到odex中了,然后被系统检测到caller与callee处于不同的dex file,也就是在App的odex中有一份,在系统framework-wifijar中也有一份,所以主动发起abort(inline不允许跨dex文件),导致应用出现闪退等异常问题,但是sdk小于P的话,只会报WARNING而不是FATAL。

于是在安装了App之后手动对apk进行dexopt

这个崩溃就必现了,这样就比较好分析了,只需要防止这个类被dex优化内敛就行了,加个try-catch就可以。

参考:

Android疑难杂症——因内联优化导致90机型Native Crash

Android P新增检测项 应用热修复受重大影响

以上就是关于安卓内外部存储完全解析 -- 别再弄混了全部的内容,包括:安卓内外部存储完全解析 -- 别再弄混了、pathclassloader和dexclassloader的区别、android内联优化导致Inlined method resolution crossed dex file boundary等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

原文地址: http://outofmemory.cn/web/10144789.html

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

发表评论

登录后才能评论

评论列表(0条)

保存