在app开发过程中,调用系统的相机和相册进行图片的选择上传是一个基本且普遍的需求,下面就简单介绍下我的实际开发中是如何实现这一需求的。
1.调用系统的相机和相册
/**
* 调用系统相机
*/
private void openCamra() {
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return;
}
// 指定图片加载路径
File file = new File(Constant.CAMERA_TEMP_PATH);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
Uri uri = Uri.fromFile(file);
Intent intent1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent1.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent1, Constant.OPEN_CAMER);
}
/**
* 调用系统相册
*/
private void openGallery() {
// 手机相册
Intent choosePicture = new Intent(Intent.ACTION_PICK);
choosePicture.setType("image/*");
startActivityForResult(choosePicture,
Constant.OPEN_ALBUM);
}
调用系统相册比较简单,指定intent的参数即可,建议requestCode放在一个定义好的常量类中。在调用系统相机的时候,首先是判断sd卡是否存在,然后创建一个File文件,然后转换成Url对象传给相机,这样做的好处是指定了相机拍摄的文件路径,返回的时候的可以很方便对该文件进行一系列的处理(压缩,上传等),如果不指定文件路径,返回的图片是一张默认的缩略图,达不到上传的精度。
2.处理返回的图片
主要是在onActivityResult方法中进行接收处理操作
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Constant.OPEN_CAMER:
//指定临时文件路径
String filepath_album1 = Constant.CAMERA_TEMP_PATH;
//创建处理后的图片文件
File desfile = BitmapUtils.getInstance().getPicFile();
//对该图片进行压缩处理
BitmapUtils.getInstance().getimage(filepath_album1,
desfile.getAbsolutePath());
//将处理后的图片放在适配中,我用的是ImageLoader进行图片显示,所以是这样写法
list_pic.add("file://" + desfile.getAbsolutePath());
file_pic_list.add(desfile);
getmAdapter().setmDatas(list_pic);
break;
case Constant.OPEN_ALBUM:
if (data != null) {//调用相机data可能为null,注意
Uri uri_album = data.getData();
//将Uri转换为String路径
String filepath_album = BitmapUtils.getInstance().getPathByUri(mActivity, uri_album);
File file = BitmapUtils.getInstance().getPicFile();
BitmapUtils.getInstance().getimage(filepath_album, file.getAbsolutePath());
list_pic.add("file://" + file.getAbsolutePath());
file_pic_list.add(file);
getmAdapter().setmDatas(list_pic);
}
break;
}
}
涉及到的方法类:
public class BitmapUtils {
public static BitmapUtils getInstance() {
return InstanceHolder.INSTANCE;
}
private static final class InstanceHolder {
private static final BitmapUtils INSTANCE = new BitmapUtils();
}
private BitmapUtils() {
}
/**
* new File
*/
public File getPicFile() {
File file = new File(Environment.getExternalStorageDirectory() + "/pic/", System.currentTimeMillis() + ".jpg");
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
/**
* 尺寸大小的缩放
*/
public void getimage(String srcPath, String desPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存,
// 返回值也不再是一个Bitmap对象,而是null。虽然Bitmap是null了,
// 但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);//文件图片用该方法,此时Bitmap为null
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;//源图片的宽,高
int h = newOpts.outHeight;
//最好动态指定设置宽高
float hh = 480;//这里设置高度为480f
float ww = 320;//这里设置宽度为320f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be;//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
compressImage(bitmap, desPath);//压缩好比例大小后再进行质量压缩
}
/**
* 存储大小的缩放
*/
public void compressImage(Bitmap image, String file) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.JPEG, 80, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 85;
while ((baos.toByteArray().length / 1024 > 200) && (options > 1)) { // 循环判断如果压缩后图片是否大于200kb,大于继续压缩
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
options -= 10;// 每次都减少10
}
baos.writeTo(fileOutputStream);
// 用完了记得回收
image.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String getPathByUri(final Context context, final Uri uri) {
try {
return getRealFilePath(context, uri);
} catch (Exception e) {
return uri.getPath();
}
}
/**
* get url by uri
*/
private String getRealFilePath(final Context context, final Uri uri) {
if (null == uri) return null;
final String scheme = uri.getScheme();
String data = null;
if (scheme == null)
data = uri.getPath();
else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
data = uri.getPath();
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (index > -1) {
data = cursor.getString(index);
}
}
cursor.close();
}
}
return data;
}
}
以上就是获取图片的简单过程,基本避开了一些常见的陷阱,希望对大家有点启发和帮助。
热门评论
Constant.CAMERA_TEMP_PATH在哪里定义的?
怎么都没评论了,写的不错,学习了