最近做项目遇到拍照然后显示图片到列表,再上传缩略图到服务器。为了避免OOM就在想怎么做才是最好的,最安全的。下面是我的个人想法,如果有更好的办法,希望可以给我留言共同学习,谢谢。
解决办法:安卓拍照会生成原图和缩略图的uri,我们可以去Media-Db中寻找,不需要手动压缩图片,然后显示到列表,点击加载大图,列表显示缩略图。但是安卓手机各有不同,又遇到新问题,入下:
问题一:
小米手机返回的全是file:///storage/emulated/0/ibanshou/20170325_110120.jpg,
三星等其他机器是content://media/external/images/media/25087
问题二:
拍照默认不生成缩略图。
下面我就贴出我的代码:
首先是调用系统相机拍照。并让它返回Uri。
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
ContentValues contentValues = new ContentValues();
if(Build.MANUFACTURER.toLowerCase().equals("samsung"))
contentValues.put(MediaStore.Images.Media.ORIENTATION, 90f);
contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
//mPhotoUri是拍照返回的Uri
mPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);startActivityForResult(intent, 1);}
接着是在回调中生成缩略图:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
if (isTakePhoto) {//拍照的
intent.putExtra("imageUri", mPhotoUri.toString());
//根据得到的Uri去生成对于的缩略图,并更新Media数据库的关联。
long id = ContentUris.parseId(mPhotoUri);
// MINI.KIND是要生成缩略图的质量,不懂可以百度下这个。
MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(), id,
MediaStore.Images.Thumbnails.MINI_KIND, null);
} else {//相册选的
if (data != null) {
if (data.getExtras() != null)
intent.putExtras(data.getExtras());
if (data.getData() != null)
intent.setData(data.getData());
}
}
setResult(1, intent);
finish();
}
下面回到列表页面的回调,显示到ImageView:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
mImageCaptureUri = data.getData();
image_path = data.getStringExtra("imageUri");
if (mImageCaptureUri != null) {
//选相册
FileUtils.getPic(mImageCaptureUri, mContext, image_iv1, imagePath, 0);
} else if (!StringUtils.dealNull(image_path).equals("")) {
//拍照
mImageCaptureUri = Uri.parse(data.getStringExtra("imageUri"));
FileUtils.getPic(mImageCaptureUri, mContext, image_iv1, imagePath, 0);
}
}
}
下面贴出FileUtils的相关代码,主要是对Media-DB的操作:
/**
* 获取缩略图
*/
public static String getThumbnails(Context mContext, long image_id) {
String image_path = "";
ContentResolver cr = mContext.getContentResolver();
String[] projection = {MediaStore.Images.Thumbnails.DATA, MediaStore.Images.Thumbnails.IMAGE_ID};
Cursor cursor = cr.query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection,
MediaStore.Images.Thumbnails.IMAGE_ID + "=" + image_id, null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
int dataColumn = cursor.getColumnIndex(MediaStore.Images.Thumbnails.DATA);
int dataColumn_id = cursor.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID);
do {
image_path = cursor.getString(dataColumn);
Log.i("yfchu", image_path + "\n" + cursor.getInt(dataColumn_id));
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
}
return image_path;
}
/**
* 获取图片Id
*/
public static long getImageId(Uri uri, Context mContext) {
long imageId = -1;
String path = uri.getEncodedPath();
if (path != null)
path = Uri.decode(path);
StringBuffer buff = new StringBuffer();
buff.append("(").append(MediaStore.Images.ImageColumns.DATA).append("=")
.append("'" + path + "'").append(")");
String[] projection = {Images.ImageColumns._ID, Images.ImageColumns.TITLE,
Images.ImageColumns.DISPLAY_NAME, Images.ImageColumns.DATA};
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, projection,
buff.toString(), null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
do {
imageId = cursor.getInt(cursor.getColumnIndex(Images.ImageColumns._ID));
String title = cursor.getString(cursor.getColumnIndex(Images.ImageColumns.TITLE));
String name = cursor.getString(cursor.getColumnIndex(Images.ImageColumns.DISPLAY_NAME));
String data = cursor.getString(cursor.getColumnIndex(Images.ImageColumns.DATA));
Log.i("yfchu", imageId + "\n" + title + "\n" + name + "\n" + data);
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
}
return imageId;
}
/**
* 获取图片角度
*/
public static int getImageRotate(Uri uri, Context mContext, long id) {
int rotate = 0;
String path = uri.getEncodedPath();
if (path != null)
path = Uri.decode(path);
String[] projection = {Images.Media.DATA, Images.Media.ORIENTATION};
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, projection,
Images.Media._ID + "=" + id, null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
do {
rotate = cursor.getInt(cursor.getColumnIndex(Images.Media.ORIENTATION));
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
}
return rotate;
}
/*
* 获取图片--这是主要方法
* */
public static void getPic(Uri mImageCaptureUri, Context mContext,
ImageView image_iv1, String[] imagePath,int position) {
long image_id = -1;
if (mImageCaptureUri.getScheme().equals("file"))//判断是file还是content
image_id = FileUtils.getImageId(mImageCaptureUri, mContext);//根据路径去Db查询imageId
else
image_id = ContentUris.parseId(mImageCaptureUri);//content的尾部就是imageId直接拿。
int rotate = FileUtils.getImageRotate(mImageCaptureUri, mContext, image_id);//获取图片角度
String path = FileUtils.getThumbnails(mContext, image_id);//根据ImageId去Thumbnails中查询ImageId列中相等的字段就是它的缩略图
if (path.equals("")) {//为空代表无缩略图
try {
if (image_id != -1) {//得到ImageId但是系统没有生成缩略图,帮它生成缩略图并关联。下次再选就有了
MediaStore.Images.Thumbnails.getThumbnail(
mContext.getContentResolver(), image_id,
MediaStore.Images.Thumbnails.MINI_KIND, null);
path = FileUtils.getThumbnails(mContext, image_id);
} else {
//这里处理特殊情况,就是原图和缩略图在db中都查询不到得情况。
//你只能自己压缩了。这里写压缩图片方法。
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (image_id != -1) {//一切正常,数据库查到大图和缩略图等,直接显示。
File file = new File(path);
imagePath[position] = file.getAbsolutePath();
if (imagePath[position] != null) {
Picasso.with(mContext).load(file).rotate(rotate).into(image_iv1);
}
}
}
根据这些网站总结学习的:
http://blog.csdn.net/csqingchen/article/details/45502813
还有看源码,从中知道如何系统生成缩略图到db
MediaStore.Images.Media.insertImage()