前言

维护的一个项目的时候发现,项目使用了一个5年前的库,是通过直接拉源码的并改写的方式来实现的。去GitHub找到了这个库PhotoPicker。作者说项目不维护了,建议大家使用zhihu/Matisse。想着换库可能比直接改要麻烦,我就改了下这个库,上传到GitHub自己用了。

分析一下需要注意的地方

  • Glide版本过老,需要升级。
  • target api修改成29,在androidx下要能正常使用。
  • android 7.0的url适配,需要使用FileProvider,设置authority字段。
  • 有需要上传图片文件的情况,在获取不到绝对路径的时候,可以使用uri获取文件流然后上传。
  • 有些方法和字段过时:在10.0的机子上,通过 MediaStore.Images.Media.DATA字段获取不到图片的路径;api29之前,拍照过后通常是使用广播的形式通知MediaStore刷新,图库才能显示出图片,在29之后使用MediaScannerConnection的api扫描。

使用

工程目录下gradle文件添加jitpack依赖:

allprojects {repositories {google()mavenCentral()gradlePluginPortal()maven { url "https://jitpack.io" }}
}

添加权限AndroidManifest.xml

     <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.CAMERA" />

sample使用了第三方库九宫格,添加依赖如下(本库也支持单选,请根据自己情况而定)

dependencies {//此处省略...//9宫格的图片选择implementation 'com.jaeger.ninegridimageview:library:1.1.1'//本地库依赖//implementation project(':photopicker')//远程依赖implementation 'com.github.PengHaiZhuo:PhotoPicker:1.0.4'
}

使用

    /*** 当前选择的图片路径*/private ArrayList<String> imagePathsList = new ArrayList<>();/*** 允许上传照片最大数量*/private static final int INT_MAXSIZE_IMG = 9;/*** 跳转到图片选择器* @param position:预览图片需要传当前图片位置,配合imagePathsList使用* @param isPick 是否是添加图片*/private void toPickPhoto(int position,boolean isPick){if (isPick) {PickImageIntent intent = new PickImageIntent(mContext);//设置为多选模式intent.setSelectModel(SelectMode.MULTI);// 是否拍照intent.setIsShowCamera(true);//设置最多选择照片数量if (imagePathsList.size() > 0 && imagePathsList.size() < (INT_MAXSIZE_IMG + 1)) {// 最多选择照片数量intent.setSelectedCount(INT_MAXSIZE_IMG + 1 - imagePathsList.size());} else {intent.setSelectedCount(0);}/*// 已选中的照片地址,用于回显选中状态intent.setSelectedPaths(imagePathsList);*/startActivityForResult(intent, REQUEST_CAMERA_CODE);} else {//预览图片PreViewImageIntent intent = new PreViewImageIntent(mContext);intent.setCurrentItem(position);intent.setPhotoPaths(imagePathsList);startActivityForResult(intent, REQUEST_PREVIEW_CODE);}}

重写onActivityResult方法,获取选择的照片路径列表

 private static final int REQUEST_CAMERA_CODE = 10;private static final int REQUEST_PREVIEW_CODE = 20;@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode==RESULT_OK){switch (requestCode) {case REQUEST_CAMERA_CODE:if (data != null) {ArrayList<String> list = data.getStringArrayListExtra(ImagePickerConstract.EXTRA_RESULT);//todo 显示图片}break;case REQUEST_PREVIEW_CODE:if (data != null) {ArrayList<String> ListExtra = data.getStringArrayListExtra(ImagePickerConstract.EXTRA_RESULT);if (imagePathsList != null) {imagePathsList.clear();}imagePathsList.addAll(ListExtra);//todo 预览里可能删除了图片,所以需要更新显示的图片}break;}}}

部分截图

图片选择

可以选择文件夹中文件也可以拍照。

预览

使用了PhotoView控件,可放大缩小查看图片

9宫格


2021-12月21提交了1.0.4版,处理如下

  • 因为jcenter库关了,修改了配置文件
  • 通过Context访问自己的私有目录,不需要读写权限,不管什么系统版本
  • android11必须进行文件权限适配!在android11,通过内容提供者扫描很多文件扫不出来,能扫出来的只有那些DCIM、Download这种有权限的
  • android 10是谷歌给开发者们的一个过渡版本,只需要在配置文件的application节点设置android:requestLegacyExternalStorage="true"即可不做文件权限适配。可以在sd卡创建乱七八糟的文件,可以通过内容提供者扫描出公有目录各种文件
  • 关于绝对路径,很多情况下获取不到,所以能拿到uri的话,请通过输入输出流处理,比如转成bitmap或者保存到公有目录Download这种目录下

已完成Android11文件权限适配,记录如下

  1. 无外部可操作存储,拍照文件保存目录默认在/data/data/< package name >/files/<app name>/images
  2. 有外部可操作存储,拍照文件存放目录在Android11前后发生变化,Android11之前在/mnt/sdcard/<app name>/images ,Android11之后在/mnt/sdcard/Android/data/< package name >/<app name>/images
  3. 媒体文件扫描在Android11前后发生变化,android11之前会按照媒体上一级目录显示分类,android11之后只有一个media目录
  4. 拍照后通知gallery刷新的方式发生了变更

2021-12-22补充示例:在Android10上通过内容提供者保存文件到公有目录

val context = this@MainActivity
val fileName = "p-touch.pdf"
val subFileName="phz"
val pdfUrl ="https://download.brother.com/welcome/docp000648/cv_pt3600_schn_sig_lad962001.pdf"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {savePDFUsingMediaStore(context, pdfUrl, fileName,subFileName)
} else {//android 10以前随便存,不过要记得获取读写权限val file = File(Environment.getExternalStorageDirectory(),subFileName)//val contentUri = getUriForFile(context, “配置文件中FileProvider设置的authorities字段”, file)//文件存在 sd卡/<subFileName>/<fileName>val target = File(file, fileName)URL(pdfUrl).openStream().use { input ->FileOutputStream(target).use { output ->input.copyTo(output)}}
}

保存pdf

@RequiresApi(Build.VERSION_CODES.Q)
private fun savePDFUsingMediaStore(context: Context, url: String, fileName: String,subFileName:String) {val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf")put(MediaStore.Downloads.DATE_ADDED, (System.currentTimeMillis() / 1000).toInt())put(MediaStore.Downloads.RELATIVE_PATH,Environment.DIRECTORY_DOWNLOADS + File.separator + subFileName            )}val resolver = context.contentResolver//文件存在sd卡/Download/<subFileName>/<fileName>//uri打印 content://media/external/downloads/<id>val uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)uri?.let {lifecycleScope.launch(Dispatchers.IO) {URL(url).openStream().use { input ->resolver.openOutputStream(uri).use { output ->input.copyTo(output!!, DEFAULT_BUFFER_SIZE)}}}}
}

Demo地址

可参照:SampleDemo

Android图片选择器PhotoPicker相关推荐

  1. android图片选择器框架支持长图,基于RxJava的Android图片选择器. – RxPicker

    RxPicker 基于 RxJava 的 Android 图片选择器. 特性 与 RxJava 结合,支持响应式得到选择图片结果 兼容 Android 7.0 自定义 ImageLoader 预览 使 ...

  2. android 仿照ios 图片选择,GitHub - wildma/PictureSelector: Android 图片选择器(仿 IOS 图片选择控件)...

    PictureSelector Android 图片选择器(仿 IOS 图片选择控件) 效果图 功能特点 支持通过拍照获取图片 支持通过相册获取图片 支持图片是否裁剪两种场景 支持仿 IOS 底部弹出 ...

  3. Matisse Android图片选择器详细使用

    Matisse Android 图片选择器 详细使用方式 前言 我们在做App的时候很多需求都要选择图片 比如说: 上传头像 上传朋友圈 发送图片 内容编辑插入图片 我们也可以使用系统的组件来完成我们 ...

  4. android 自定义相册选择,Android图片选择器,支持拍照、从相册选择、裁剪、自定义主题...

    在很多项目中都会用到图片选择器,比如在选择头像的时候,还会要求选择图片进行裁剪后再进行上传:而有的项目要支持拍照后进行图片裁剪再进行上传.由于Android系统兼容性问题,我们不得不考虑自己实现图片裁 ...

  5. Android 图片选择器和图片裁剪库

    前言:现在大部分的App都支持上传图片和裁剪图片的功能,比如设置用户头像.聊天发送图片.发表动态.论坛帖子等.上传图片需要先从选择手机中选择要上传的图片,所以图片选择器在App中是很常见的组件,一般的 ...

  6. Android 图片选择器、图片剪切,文件选择器

    单张图片选择 1.在build.gradle中dependencies下添加依赖 compile 'com.github.lovetuzitong:MultiImageSelector:1.2' 2. ...

  7. android壁纸选择器,Android 图片选择器

    前言 在安卓开发中经常用到修改头像功能,通常就拍照和选择相册图片两种.有很多时候还需要对图片进行裁剪.所以这个工具可以更快速完成这些功能.对于6.0权限的处理,每个人用的都不一样,所以这个工具使用的是 ...

  8. Android 图片选择器(支持拍照,预览)

    最近项目中需要选择本地图片,自己就在网上找了一个第三方框架,此框架不太满足自己的需求,此框架拍照后,会自动将照片返回,我需要将图片设置为选中状态并不返回,自己修改了框架源码,改成自己的需求,下面有图片 ...

  9. Android 图片选择器(拍照)自定义

    开发经常遇到获取图片问题 /*** 读取手机中所有图片信息*/ private void getAllPhotoInfo() {new Thread(new Runnable() {@Override ...

最新文章

  1. 每日一皮:为什么在生产环境操作要谨慎再谨慎?太形象了!
  2. android 处理双击事件
  3. 使用spring实现邮件的发送(含测试,源码,注释)
  4. ecshop首页显示折扣的方法,ecshop商品显示折扣的方法
  5. python2逐步转向python3之小程序实践学习
  6. (转)江南愤青丨丨监管办法之后,网贷一地鸡毛(2016年)
  7. 五笔字根表识别码图_五笔字根表图
  8. Java Web三大组件
  9. 车载终端794认证,905认证
  10. 物联网卡与普通的sim卡的区别
  11. 二叉树的前序遍历-python
  12. 1286.字母组合迭代器
  13. 关于git提交报错Please tell me who you are.
  14. word2016安装Aurora,并添加到选项卡
  15. 脚本修改root密码和命令修改root密码
  16. 2021 最新分享 Java 面试题库万字精华 github 上标星 80
  17. 使用jqprint打印网页指定区域的内容
  18. python百分号用法_python里百分号
  19. @Entity @Table注解
  20. 伏格尔法、位势法寻找闭回路

热门文章

  1. 关于keras.sum()和kears.softmax()等函数中维度的理解
  2. OpenGL多重纹理使用与理解
  3. 关于物联网,互联网我们用到的通信
  4. 苹果手机开不了机怎么办
  5. (附代码)数独大作业【读取数独,解数独,生成唯一解数独(随机,特定形状,不同难度生成),玩数独】
  6. 用python绘制叠加等边三角形_使用turtle库绘制叠加等边三角形
  7. 教你用VS Code插件实现五彩斑斓的伪代码
  8. 美团App 插件化实践
  9. C语言检查IP、MAC、子网掩码合法函数 实用 码住喽!
  10. 编写程序FooBizBaz.java,从1循环到150并且在每行打印一个值,另外在每个3的倍数行上打印出“foo”,在每个5的倍数行上打印“biz”,在每个7的倍数行上打印输出“baz”。