获取相册照片和获取拍照照片
程序员文章站
2024-02-10 14:21:28
...
在Android的开发过程中,我们可能会读取手机里面的照片或者通过相机拍摄获取照片,这是两种常用的获取图片的方式,在做项目过程中也会经常遇到,下面来介绍一下这两种获取方式..
一、需要裁剪
1.定义相关常量以及照片的名称和路径
private static final int REQUEST_CODE_PICK_IMAGE = 1;
private static final int REQUEST_CODE_CAPTURE_CAMEIA = 2;
private static final int PHOTO_REQUEST_CUT = 3;
private File tempFile = new File(Environment.getExternalStorageDirectory(),
getPhotoFileName());
// 使用系统当前日期加以调整作为照片的名称
private String getPhotoFileName() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat(
"'IMG'_yyyyMMdd_HHmmss");
return dateFormat.format(date) + ".jpg";
}
2.从本地相册获取照片:
一般就是写出这个方法
protected void getImageFromAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");// 相片类型
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}
3.从照相机获取照片
一般就是写出这个方法
protected void getImageFromCamera() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
Intent getImageByCamera = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(tempFile));
startActivityForResult(getImageByCamera,
REQUEST_CODE_CAPTURE_CAMEIA);
} else {
Toast.makeText(getApplicationContext(), "请确认已经插入SD卡",
Toast.LENGTH_LONG).show();
}
}
4.写完这个方法后,一般我们还需要通过响应这个方法去获取图片
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
{
switch (requestCode) {
case REQUEST_CODE_PICK_IMAGE:// 当选择从本地获取图片时
// 做非空判断,当我们觉得不满意想重新剪裁的时候便不会报异常,下同
if (data != null)
startPhotoZoom(data.getData());
break;
case REQUEST_CODE_CAPTURE_CAMEIA:// 当选择拍照时调用
startPhotoZoom(Uri.fromFile(tempFile));
break;
case PHOTO_REQUEST_CUT:// 返回的结果
if (data != null)
// setPicToView(data);
sentPicToNext(data);
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
}
5.实现startPhotoZoom(Uri uri)方法,调整图片大小并且裁剪。
private void startPhotoZoom(Uri uri) {
// TODO Auto-generated method stub
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
// crop为true是设置在开启的intent中设置显示的view可以剪裁
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX,outputY 是剪裁图片的宽高
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 300);
intent.putExtra("return-data", true);
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, PHOTO_REQUEST_CUT);
}
6.实现setToImg(Intent data)方法
private void setToImg(Intent data) {
// TODO Auto-generated method stub
Bundle bundle = data.getExtras();
ImageView img = (ImageView) findViewById(viewId);
if (bundle != null) {
Bitmap photo = bundle.getParcelable("data");
if (photo == null) {
img.setImageResource(R.drawable.ic_launcher);
} else {
img.setImageBitmap(photo);
// 设置文本内容为 图片绝对路径和名字
// text.setText(tempFile.getAbsolutePath());
}
}
}
二、不需要裁剪
1.定义相关常量以及照片的名称和路径
private static final int REQUEST_CODE_PICK_IMAGE = 1;
private static final int REQUEST_CODE_CAPTURE_CAMEIA = 2;
private File tempFile = new File(Environment.getExternalStorageDirectory(),
getPhotoFileName());
// 使用系统当前日期加以调整作为照片的名称
private String getPhotoFileName() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat(
"'IMG'_yyyyMMdd_HHmmss");
return dateFormat.format(date) + ".jpg";
}
2.从本地相册获取照片:
protected void getImageFromAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");// 相片类型
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}
3.从照相机获取照片
protected void getImageFromCamera() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
Intent getImageByCamera = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(tempFile));
startActivityForResult(getImageByCamera,
REQUEST_CODE_CAPTURE_CAMEIA);
} else {
Toast.makeText(getApplicationContext(), "请确认已经插入SD卡",
Toast.LENGTH_LONG).show();
}
}
4.写完这个方法后,一般我们还需要通过响应这个方法去获取图片
@Override
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
{
Uri uri = null;
Bitmap photo = null;
ImageView img = null;
switch (requestCode) {
case REQUEST_CODE_PICK_IMAGE:// 当选择从本地获取图片时
// 做非空判断,当我们觉得不满意想重新剪裁的时候便不会报异常,下同
if (data != null) {
uri = data.getData();
String[] proj = { MediaStore.Images.Media.DATA };
Cursor actualimagecursor = managedQuery(uri, proj, null,
null, null);
int actual_image_column_index = actualimagecursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
actualimagecursor.moveToFirst();
String img_path = actualimagecursor
.getString(actual_image_column_index);
// File file = new File(img_path);
photo = BitmapFactory.decodeFile(img_path);
img = (ImageView) findViewById(viewId);
if (photo == null) {
img.setImageResource(R.drawable.ic_launcher);
} else {
img.setImageBitmap(photo);
}
}
break;
case REQUEST_CODE_CAPTURE_CAMEIA:// 当选择拍照时调用
photo = BitmapFactory.decodeFile(tempFile.getAbsolutePath());
img = (ImageView) findViewById(viewId);
if (photo == null) {
img.setImageResource(R.drawable.ic_launcher);
} else {
img.setImageBitmap(photo);
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
}
图片传递
//把位图压缩到输出流中,然后把输出流转换成字节数组,然后再放入Intent中作为数据传递
Bitmap photo = bundle.getParcelable("data");
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] photodata = baos.toByteArray();
System.out.println(photodata.toString());
Intent intent = new Intent();
intent.setClass(RegisterActivity.this, ShowActivity.class);
intent.putExtra("photo", photodata);
startActivity(intent);
finish();
} catch (Exception e) {
e.getStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
但是,有时候我们会发现用相机拍摄获取照片的时候,得到的 uri 是 null 的,这是因为android把拍摄的图片封装到bundle中传递回来,但是根据不同的机器获得相片的方式不太一样,可能有的相机能够通过
inten.getData()获取到uri
然后再根据uri获取数据的路径,在封装成bitmap,但有时候有的相机获取到的是null的,这时候我们该怎么办呢?
其实这时候我们就应该从bundle中获取数据,通过
(Bitmap) bundle.get("data")
获取到相机图片的bitmap数据。
为了能够同时适应上述两种情况,我们这时候就应该在获取图片时做判断了。我们可以在响应的时候做一个判断:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_PICK_IMAGE) {
Uri uri = data.getData();
//to do find the path of pic by uri
} else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA ) {
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转化成相应的图片文件了。不过得到最终的图片是被压缩了的。
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();
}
}
这样就能解决照相机取到的图片uri为空的状态了。但是在获取到uri为null情况下,如果想得到没有被压缩过的照片,也就是说得到的是直接从相机拍摄到的照片怎么做呢?
其实方式很简单,在
Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");
之后我们直接讲文件先保存到指定的路径filepath,然后直接在
onActivityResult(int requestCode, int resultCode, Intent data)
中把filepath传递过去就行了。
private String capturePath = null;
protected void getImageFromCamera() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");
String out_file_path = Constant.SAVED_IMAGE_DIR_PATH;
File dir = new File(out_file_path);
if (!dir.exists()) {
dir.mkdirs();
}
capturePath = Constant.SAVED_IMAGE_DIR_PATH + System.currentTimeMillis() + ".jpg";
getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(capturePath)));
getImageByCamera.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(getImageByCamera, Constant.REQUEST_CODE_CAPTURE_CAMEIA);
}
else {
Toast.makeText(getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
}
}
在onActivityResult(int requestCode, int resultCode, Intent data)中我们只要把路径filepath定义为全局的变量传送过来就行了。
这样得到的图片是直接从相机中拍摄得到的照片,不会被压缩了。
上一篇: 【Oracle】cursor游标