Android仿qq从相册选择照片
2016-05-22 23:54
633 查看
博客恢复更新后,还是打算每周至少写一篇技术博客吧,再多的话也没什么时间(╮(╯_╰)╭)。
先看下效果图吧,弄了半天没整出小鱼2M的gif图,所以暂时先用几张截图代替吧,大体流程也就这样。现在几乎每个应用都要有拍照和选择照片的功能了,单选的话直接跳转到系统相册就可以了,但是多选的的话就得自己写了,倒不是写这个功能有多么麻烦,只是现在的产品啊,明明都是抄袭别的应用了,却还要想保持个性,所以我就把这块功能直接抽成library,方便以后应用的集成和修改。
![](https://img-blog.csdn.net/20160522230328109)
![](https://img-blog.csdn.net/20160522230345719)
![](https://img-blog.csdn.net/20160522230409142)
![](https://img-blog.csdn.net/20160522230440407)
![](https://img-blog.csdn.net/20160522230454626)
然后在onActivityResult中获取数据
2.预览模式
需要传一个String的List
首先我们要知道Android里面的图片都是保存在什么地方的,打开AndroidStudio的Android Device Monitor然后打开data/data目录,如果是真机的话,这一步需要root,并且还有改变目录的权限,root的话网上一搜一大堆工具,我就不推荐了,修改文件目录的权限可以用Re文件管理器,非常好用
![](https://img-blog.csdn.net/20160526113938204)
在下面我们可以找到很多包名带有Provider的目录,其中com.android.providers.media就是我要找的,com.android.providers.contacts是手机联系人的provider,如果你想要选择联系的话,可以用这个。
![](https://img-blog.csdn.net/20160526114106931)
找到里面external.db文件,并将它弄到电脑上
![](https://img-blog.csdn.net/20160526114536563)
然后用SQLite Expert打开,并选择里面的images表
![](https://img-blog.csdn.net/20160526114836660)
剩下的步骤就是去找你需要的字段了,我就不再多说了。
下面是我的查询代码,包括结果的处理
先看下效果图吧,弄了半天没整出小鱼2M的gif图,所以暂时先用几张截图代替吧,大体流程也就这样。现在几乎每个应用都要有拍照和选择照片的功能了,单选的话直接跳转到系统相册就可以了,但是多选的的话就得自己写了,倒不是写这个功能有多么麻烦,只是现在的产品啊,明明都是抄袭别的应用了,却还要想保持个性,所以我就把这块功能直接抽成library,方便以后应用的集成和修改。
imageSelector的用法
1.选图片模式startActivityForResult(new ImageSelect.Builder(this) .setLimit(9) .setMode(ImageSelect.MODE_SELECT) .Build(),ALBUM);
然后在onActivityResult中获取数据
if(requestCode==ALBUM&&resultCode==RESULT_OK){ pathList=ImageSelect.getImagePath(data); }
2.预览模式
需要传一个String的List
startActivity(new ImageSelect.Builder(this) .setMode(ImageSelect.MODE_PREVIEW) .setPreSource(pathList) .setIndex(position) .Build());
授人以渔
其实要实现这样的功能逻辑上并没有什么难点,无非就是来回传值限制最大张数什么的,但是让我无从下手就是如何才能获取到手机里所有的图片呢,网上一搜一大片都是一模一样的,都给出了现成的字段,用ContentProvider进行查询,然后Cursor遍历等等,但是为什么用这个字段查询却没有给出说明,如果我想要的数据并没有在那么现成的字段里面怎么办?比如我之前参考的一个博客,在获取相册的时候用的图片的父目录,这种方式还是挺容易出错的。首先我们要知道Android里面的图片都是保存在什么地方的,打开AndroidStudio的Android Device Monitor然后打开data/data目录,如果是真机的话,这一步需要root,并且还有改变目录的权限,root的话网上一搜一大堆工具,我就不推荐了,修改文件目录的权限可以用Re文件管理器,非常好用
在下面我们可以找到很多包名带有Provider的目录,其中com.android.providers.media就是我要找的,com.android.providers.contacts是手机联系人的provider,如果你想要选择联系的话,可以用这个。
找到里面external.db文件,并将它弄到电脑上
然后用SQLite Expert打开,并选择里面的images表
剩下的步骤就是去找你需要的字段了,我就不再多说了。
加载器LoaderCallbacks
选好字段后我们还需要把这些数据查询出来,这里我推荐大家使用LoaderCallbacks,LoaderManager.LoaderCallbacks是3.0之后出现的新特性,通过LoaderManager.LoaderCallbacks接口可以很轻松的实现异步加载数据到Fragment或Activity 中,Loaders提供了回调机制onLoadFinished()通知最终的运行结果,有点类似AsyncTask类,但由于Loader对于并发可以用过Loader管理器统一管理,所以更适合批量处理多个异步任务的处理(当然内部仍然是多线程)。下面是我的查询代码,包括结果的处理
public LoaderManager.LoaderCallbacks<Cursor> mLoaderCallback =new LoaderManager.LoaderCallbacks<Cursor>() { private final String[] IMAGE_PROJECTION = { MediaStore.Images.Media.DATA, //图片路径 MediaStore.Images.Media.BUCKET_DISPLAY_NAME, //相册名字 MediaStore.Images.Media.DATE_ADDED, //创建时间 MediaStore.Images.Media.MIME_TYPE, //图片类型 MediaStore.Images.Media.SIZE, //图片大小 MediaStore.Images.Media.BUCKET_ID, //相册id MediaStore.Images.Media._ID //图片id }; @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[3] + "=? OR " + IMAGE_PROJECTION[3] + "=? ", new String[]{"image/jpeg", "image/png"}, IMAGE_PROJECTION[2] + " DESC"); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { if(data==null||data.getCount()<=0) re 4000 turn; List<Result> results = new ArrayList<>(); data.moveToFirst(); do { String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0])); String fileName = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1])); long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2])); long id=data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[6])); long buckId=data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[5])); Result result = new Result(path,fileName,dateTime,id,buckId); results.add(result); }while(data.moveToNext()); processResult(results); } @Override public void onLoaderReset(Loader<Cursor> loader) { } }; private void processResult(List<Result> results) { Album all=new Album(); all.setName(getString(R.string.all_photo)); List<Album> albumList=new ArrayList<>(); for (Result result : results) { Photo photo=new Photo(result.getId(),result.getPath(),result.getTime()); Album album=getAlbumById(albumList,result.getBucketId()); if(album==null){ album=new Album(); album.setId(result.getBucketId()); album.setName(result.getName()); albumList.add(album); } album.getPhotoList().add(photo); all.getPhotoList().add(photo); } if(albumList.size()>1){ albumList.add(0,all); } adapter.updateData(albumList); } private Album getAlbumById(List<Album> list,long id){ for (Album album : list) { if(album.getId()==id){ return album; } } return null; }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories