Android获取系统图片的研究

Catalogue
  1. 1 相册获取图片(单张)
    1. 1.1 直接获取
    2. 1.2 从照相机获取照片
  2. 2 实现相册多选功能
  3. 3 最佳实践
    1. 3.1 获取权限
  4. 参考资料

在Android开发过程中,我们经常会遇到从相册中获取图片、拍照获取图片、相册多选的需求,那么今天就从这三点出发来研究一下Android获取系统的图片的方法吧~

1 相册获取图片(单张)

从相册获取单张图片的方式主要有两个,一种是直接获取,另外一种是在进入内容(图片)选择界面之前弹出一个类别选择窗。

1.1 直接获取

1
2
3
4
5
void getImageFromAlbum() {  
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");//相片类型
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}

进行内容类别选择之后,才进入具体的内容界面:

1
2
3
4
5
6
void getContent() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1);//定义弹窗的标题。
}

1.2 从照相机获取照片

1
2
3
4
5
6
7
8
9
10
11
protected void getImageFromCamera() {  
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
Intent intent = new Intent();
intent.setAction("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent, 2);
}
else {
Toast.makeText(getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
}
}

当图片的信息返回后,我们要在onActivityResult方法中获取返回的图片信息。

1
2
3
4
5
6
7
8
9
10
@Override  
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
Uri uri = data.getData();
//to do find the path of pic

} else if (requestCode == 2 ) {
Uri uri = data.getData();
//to do find the path of pic
} }

不同的机器获得相片的方式不太一样,可能有的相机能够通过 inten.getData()获取到uri然后再根据uri获取数据的路径,在封装成bitmap,但有时候有的相机获取到的是null的,这时候我们该怎么办呢?
其实这时候我们就应该从bundle中获取数据,通过(Bitmap) bundle.get(“data”)直接获取到相机图片的bitmap数据。为了能够同时适应上述两种情况,我们这时候就应该在获取图片时做判断了。我们可以在响应的时候做一个判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override  
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
Uri uri = data.getData();
//to do find the path of pic by uri

} else if (requestCode == 2 ) {
Uri uri = data.getData();
if(uri == null){
//use bundle to get data
Bundle bundle = data.getExtras();
if (bundle != null) {
Bitmap photo = (Bitmap) bundle.get("data"); //get bitmap
//spath :生成图片取个名字和路径包含类型
saveImage(Bitmap photo, String spath);
} else {
Toast.makeText(getApplicationContext(), "err****", Toast.LENGTH_LONG).show();
return;
}
}else{
//to do find the path of pic by uri
}
}
}

后面的过程就需要通过bitmap转化成相应的图片文件了。不过得到最终的图片是被压缩了的

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void saveImage(Bitmap photo, String spath) {  
try {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(spath, false));
photo.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}

2 实现相册多选功能

Android自身没有实现相册多选功能,如果想要实现的话,还是有办法的。通过getContentResolver().query()遍历整个相册即可获取所有的本地图片,然后利用GridView或者其它的方式将这些图片展示即可。

1
2
3
4
5
6
7
8
9
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
if (cursor.moveToFirst()) {
do {
String uriStr = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));
//这里可以先将uriStr保存到内存,之后再加载到Adapter中。
Log.d("TAG", "query: " + column);
} while (cursor.moveToNext());
}

3 最佳实践

3.1 获取权限

不要忘记了,Android在读取外部存储空间时需要获取android.permission.READ_EXTERNAL_STORAGE权限。但是6.0以上的Android系统有了动态获取权限的概念,具体请查看官方文档
上面提到读取外部存储空间时需要读取权限,其实所有需要访问外部存储空间的操作都是需要访问权限的。但是对于内部存储空间的访问则不需要权限的申请。关于内部存储空间与外部存储空间的区别,具体请查看这篇文章


参考资料

Android开发之获取相册照片和获取拍照照片