距离上次更新博客都感觉是好久远的事了,不过不管过多久,有更新总是不错的。今天给大家带来一个自己写的获取Android手机相册图片或相机拍照图片的例子,可以相册可以单选或多选,在单选或相机模式下可以设置是否裁剪,裁剪是调用的系统的裁剪方法,对于6.0以上的系统,会先去申请相机和读写SDcard权限。先简单看几张效果图:
模拟器动态图如下:
手机静态图:
1、
2、
3、
4、
一、老规矩,先说说实现的思路:
(1)首先是相册选择:由于Android的多样性,通过系统来选择图片也是可行的,但是兼容性不好,对不同版本返回的uri解析也不同,而且还不能实现多张同时选择。因此为了达到好的用户体验,就抛弃了系统选择图片的这种方式。因为图片都是存储在手机Sdcard上的,因此我们可以通过扫描Sdcard来获取所以图片的路径,然后再根据路径来获取图片,这样就不会有什么问题了。为了扫描Sdcard,我们使用ContentResolver来查询媒体类型为:jpg或png的图片,然后分文件夹来存储相应的图片路径就可以了。
对于对图片按文件夹分类时,我们只需要存储文件夹的路径和里面第一张图片就行了,就可以把图片列表展示给用户选择,然后选择相应文件夹时,再查询相应文件夹下所有图片类型的文件,获取其实际路径就OK了。
(2)相机拍照:我们可以用默认的方式调用相机拍照,然后在返回的data里面获取图片,但是这个图片是缩略图,不是很清晰。所以我们改变策略,Android系统调用相机拍照时可以设置所拍的照片的存储路径,这样我们就可以自己定义文件路径,然后拍照成功后,到相应路径下面去获取图片就可以了,而且还是高清五码的哦 吼吼。不过我们自己定义图片路径并且保存成功后,还需要做一步就是通知系统刷新图库,这样我们才能及时在图片文件夹列表里面找到我们刚拍摄的图片。
综上:我们对图片的处理都是通过图片的实际路径来获取图片,这样就不会存在兼容性问题了。
二、代码比较多,并且大多都是处理交互UI的,这里就没必要贴出来了,只贴出重要代码即可:
(1)扫描系统图库,并存储所以图片路径和分文件夹存储图片和相应的图片数量:
public void scanImgs()
{
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
Toast.makeText(context, "当前存储卡不可用", Toast.LENGTH_SHORT).show();
return;
}
new Thread()
{
@Override
public void run() {
Uri muri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver cr = activity.getContentResolver();
Cursor cursor = cr.query(muri, null, MediaStore.Images.Media.MIME_TYPE + " = ? or " + MediaStore.Images.Media.MIME_TYPE + " = ? ", new String[]{"image/jpeg", "image/png"}, MediaStore.Images.Media.DATE_MODIFIED);
Set dirPaths = new HashSet();
int count = cursor.getCount();
for(int i = count - 1; i >= 0; i--) {
cursor.moveToPosition(i);
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
if(i == count - 1)
{
ImgFloderBean imgflder = new ImgFloderBean();
imgflder.setFirstImgPath(path);
imgflder.setDirName("所以图片");
imgflder.setType(0);
imgflder.setSelected(true);
imgFloderBeens.add(imgflder);
}
ImgBean imgBean = new ImgBean();
imgBean.setPath(path);
imgBean.setSelected(false);
// checkSelectedImgBeans(imgBean);
imgs.add(imgBean);
tempImgs.add(imgBean);
File parentFile = new File(path).getParentFile();
if (parentFile == null)
continue;
String dirPath = parentFile.getAbsolutePath();
ImgFloderBean imgFloderBean = null;
if (dirPaths.contains(dirPath)) {
continue;
} else {
dirPaths.add(dirPath);
imgFloderBean = new ImgFloderBean();
imgFloderBean.setDir(dirPath);
imgFloderBean.setFirstImgPath(path);
imgFloderBean.setDirName(parentFile.getName());
imgFloderBean.setType(1);
imgFloderBean.setSelected(false);
imgFloderBeens.add(imgFloderBean);
}
if (parentFile.list() == null)
continue;
int picSize = parentFile.list(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
if (s.endsWith(".jpg") || s.endsWith(".jpeg") || s.endsWith(".png"))
return true;
return false;
}
}).length;
if (imgFloderBean != null) {
imgFloderBean.setSize(picSize);
}
}
cursor.close();
Message message = Message.obtain();
message.what = 0x001;
handler.sendMessage(message);
}
}.start();
}
(2)扫描文件夹下面的图片:
public void scanChildDirPaths(String dirPath)
{
this.dirPath = dirPath;
File file = new File(dirPath);
String[]childFilePaths = file.list(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
if(s.endsWith(".jpg") || s.endsWith(".jpeg") || s.endsWith(".png"))
return true;
return false;
}
});
if(childFilePaths != null)
{
imgGridViewAdapter.setIsaddpath(true);
imgGridViewAdapter.setPpath(dirPath);
imgs.clear();
int length = childFilePaths.length;
for(int i = 0; i < length; i++)
{
ImgBean imgBean = new ImgBean();
imgBean.setPath(childFilePaths[i]);
imgs.add(imgBean);
}
Collections.reverse(imgs);
imgGridViewAdapter.notifyDataSetInvalidated();
}
}
(3)相机拍照后,更新系统相册
try {
MediaStore.Images.Media.insertImage(context.getContentResolver(),
imageUri.getPath(), imgname, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 最后通知图库更新
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + file.getPath())));
(4)打开相机,设置自定义图片保存路径:
file = new File(getImgPath());
if (!file.exists()) {
file.mkdirs();
}
imgname = getHeadImgName();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = Uri.fromFile(new File(file, imgname));
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//设置图片保存路径
activity.startActivityForResult(intent, REQUEST_CAMERA_RESULT_CODE);
这里以申请相机权限为例:
(1)首先判断是否允许调用相机权限
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)//相机权限
{
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_CODE);//去申请相机权限
}
else
{
}
(2)在onRequestPermissionsResult中处理权限申请结果,如果用户拒绝,则给出相应的提示:
if (requestCode == REQUEST_CAMERA_CODE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(context, "camera--1", Toast.LENGTH_SHORT).show();
} else
{
Toast.makeText(context, "请允许打开摄像头权限", Toast.LENGTH_SHORT).show();
}
return;
}
四、调用方法(这里是在Activity中)
private PickPhotoDialog pickPhotoDialog;
//点击事件里面添加
pickPhotoDialog = new PickPhotoDialog(MainActivity.this, MainActivity.this);
Window window = pickPhotoDialog.getWindow();
window.setGravity(Gravity.BOTTOM);
window.setWindowAnimations(R.style.DialogEnter);
pickPhotoDialog.setCutImg(true, 5);//第一个参数为true:表示图片会被裁剪,此时第二个参数默认为1,只能选择一种图片;为false时,表示不裁剪,然后第二个参数表示选择图片的数量。
pickPhotoDialog.setOnPhotoResultListener(new PickPhotoDialog.OnPhotoResultListener() {
@Override
public void onCameraResult(String path) {//相机拍照图片路径
List imgBeens = new ArrayList();
ImgBean imgBean = new ImgBean();
imgBean.setPath(path);
imgBeens.add(imgBean);
adViewpagerUtil = new AdViewpagerUtil(MainActivity.this, viewpager, lydots, 8, 4, imgBeens);
adViewpagerUtil.initVps();
}
@Override
public void onCutPhotoResult(Bitmap bitmap) {
//图片(相机和相册)裁剪后返回的bitmap
}
@Override
public void onPhotoResult(List selectedImgs) {//相册多图选择返回图片路径结果集
if(selectedImgs != null && selectedImgs.size() > 0) {
adViewpagerUtil = new AdViewpagerUtil(MainActivity.this, viewpager, lydots, 8, 4, selectedImgs);
adViewpagerUtil.initVps();
}
else
{
if(adViewpagerUtil != null) {
adViewpagerUtil.startLoopViewPager();
}
}
}
});
//权限申请
@TargetApi(23)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (pickPhotoDialog != null)
{
pickPhotoDialog.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if(pickPhotoDialog != null)
{
pickPhotoDialog.onActivityResult(requestCode, resultCode, data);
}
}
GitHub下载
CSDN下载