前言
我们移动开发程序员应该首先明白一个要点,能够学习的东西可以区分为『知识』和『技能』。
知识,就是你知道就知道、不知道就不知道的东西,比如『计算机系统中一个字节是包含8个bit』,你知道了之后就算掌握了。
技能,是需要练习的东西,不是知道不知道的区别,只有熟练还是不熟练的区分,比如『写代码要用有意义的命名规则』,你知道了这一点,不代表你掌握了这个写代码命名的技巧,你需要去写代码练习,但是练习还不够,你需要反复练习,还需要别人给你反馈,你才能练习得更好。
是的,知乎上有些内容全都是『知识』(有的还只是伪知识),不是技能,记住,知识只需要记忆力,技能需要反复练习。
第一个name属性,如果你的应用中只是在app中使用到了一处,这个name可以写成android.support.v4.content.FileProvider就可以了,这里我使用的时候是在一个library module当中,所以是为了防止跟其他module的重名。
具体ImageSelectorProvider实现:
public class ImageSelectorProvider extends FileProvider {
//do nothing 避免与应用中的FileProvider重名
}
就是简单的一个继承FileProvider,什么也没干。
第二个authorities属性,这个是相当于一个授权的字符串,如果你只是使用在一个app当中,这个可以随便写死,但是如果是可以被多个app共用的,那么这个最好写成跟包名一致的前缀,这里我是在一个library module当中使用的,直接引用${applicationId},这样在被其他app依赖使用的时候,就会被替换成具体的应用包名。如果不这样做,当多个应用中包含相同authorities属性值的时候,你会发现无法安装应用,具体请查看[INSTALL FAILED CONFLICTING PROVIDER问题完美解决方案](()
第三个exported属性,false表示我们的provider不需要对外开放。
第三个grantUriPermissions属性,true表示允许获取对文件的临时访问权限。
再往下在meta-data属性中我们要配置一个resource属性,这里resource是设置一个xml文件,放置在res/xml/文件目录下的。
out_file_paths.xml内容:
<?xml version="1.0" encoding="utf-8"?>首先这里要注意的是,这个xml文件,如果你只是在你的app当中有多个library module使用FileProvider适配,在不同module的AndroidManfiest.xml中配置的这个xml的文件名必须是不同的,否则会出现问题,如果是相同的名字的话最终这个文件会被合并掉,这个问题也是折腾了好久,所以一定要记得多个模块的话要起一个不同的文件名!
这个xml中可以配置的属性:
-
<files-path>
:内部存储空间应用私有目录下的 files/ 目录,等同于Context.getFilesDir()
所获取的目录路径; -
<cache-path>
:内部存储空间应用私有目录下的 cache/ 目录,等同于Context.getCacheDir()
所获取的目录路径; -
<external-path>
:外部存储空间根目录,等同于Environment.getExternalStorageDirectory()
所获取的目录路径; -
<external-files-path>
:外部存储空间应用私有目录下的 files/ 目录,等同于Context.getExternalFilesDir(null)
所获取的目录路径; -
<external-cache-path>
:外部存储空间应用私有目录下的 cache/ 目录,等同于Context.getExternalCacheDir()
;
其中每个属性下面可以配置 name 和 path 两个属性,name是相当于一个别名,随便起,不要重复就行,path就是在当前这个属性下面的共享目录,比如这里写的是external-path,path是·TQImageSelector/CameraImage/,那么就表示是在
Environment.getExternalStorageDirectory().getPath()
+TQImageSelector/CameraImage/这个目录下,最终这个目录会被共享访问。如果文件是直接存放在根目录下进行共享,那么path可以写成path="."
这样可以访问根目录下的所有文件。
代码中使用, 以启动相机拍照为例:
public void startCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
File cameraFile = FileUtils.createCameraFile(this);
cameraPath = cameraFile.getAbsolutePath();
if (getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.M) {
Uri imageUri = ImageSelectorProvider.getUriForFile(this, getPackageName()+“.provider”, cameraFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(cameraIntent, REQUEST_CAMERA);
} else {
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile));
startActivityForResult(cameraIntent, REQUEST_CAMERA);
}
}
}
注意这里创建了一个file,创建的这个file必须是在你前面xml文件的path中配置的目录下面,它会传递到Provider.getUriForFile()
方法中。另外intent最好加上flgIntent.FLAG_GRANT_READ_URI_PERMISSION
, 虽然在清单文件中也配置了。
返回结果的获取
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》开源
Android优秀开源项目:
- ali1024.coding.net/public/P7/Android/git
总结
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。
虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。
系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。
虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。