第三讲 ------- 从系统中选择图片(拍照或从相册中取)

从系统中取图片这个是写安卓非常常见的一个功能,但是很多时候我们每次我们都去写一个还是比较麻烦的。

下面我就介绍我写的一个已经封装好的一个类,先看截图

从截图上看,功能很清晰,点击获取图片按钮,出来一个半透明的界面,具有用相机拍照获取图片和从相册中选择两种途径去获取图片。

看完截图直接上代码

package com.yixuan;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.example.handlertest.R;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

/**
 *
 * <p>
 * 描 述:由于很多时候获取照片是从fragment中过来的,所以不好用activity的onResult
 * 方式解决,在一个静态类里面设置一个变量存放获取到的图片路径
 *
 * <p>
 * 创 建 人:ztt
 * </p>
 * <p>
 * 创建时间:2015-2-4下午1:45:21
 * </p>
 */
public abstract class PickPhotoActivity extends Activity implements
		OnClickListener {
	/* activity返回的回调类型 */
	public static final int PHOTO_PICKED_WITH_GALLERY = 9001;
	public static final int PHOTO_PICKED_WITH_CAMERA = 9002;
	public static final int CROPED_PHOTO = 9003;
	private final int cropWidth = 160;
	private final int cropHeight = 160;
	private Activity act;
	private boolean doCrop = true;
	protected int width;
	protected int height;
	protected int DEFAULT_WIDTH = 480;
	protected int DEFAULT_HEIGHT = 480;
	protected Context ctx;
	private int dpi;
	private int screenWidth;
	protected static String picPath;/* 取得的图片路径 */

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_pick_photo);
		ctx = this;
		Intent intent = getIntent();
		DisplayMetrics metric = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metric);
		float density = metric.density;
		dpi = (int) (metric.densityDpi * density);
		DEFAULT_WIDTH = metric.widthPixels;
		DEFAULT_HEIGHT = metric.heightPixels;
		// String path = intent.getStringExtra("tempPath");
		doCrop = intent.getBooleanExtra("doCrop", true);
		width = intent.getIntExtra("width", DEFAULT_WIDTH);
		height = intent.getIntExtra("height", DEFAULT_HEIGHT);
		File picturePathFile = new File(getPicPath());
		if (!picturePathFile.exists()) {
			picturePathFile.mkdirs();
		}
		screenWidth = metric.widthPixels;
		// DEFAULT_WIDTH = getScale() * 2;
		// DEFAULT_HEIGHT = getScale() * 2;
		System.out.println(getScale() * 2);
		initView();
	}

	private int getScale() {
		Double val = 4d * dpi / screenWidth;
		val = val * 100d;
		return val.intValue();
	}

	private void initView() {
		findViewById(R.id.pick_photo_from_camera).setOnClickListener(this);
		findViewById(R.id.pick_photo_from_gallery).setOnClickListener(this);
		findViewById(R.id.cancel).setOnClickListener(this);
		act = this;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case PHOTO_PICKED_WITH_CAMERA:
				if (doCrop) {
					doCropPhoto(new File(getFullPath()), cropWidth, cropHeight);

				} else {
					savePicture(picPath, null);
				}
				break;
			case PHOTO_PICKED_WITH_GALLERY:
				picPath = getPathFromURI(data.getData().toString());
				if (doCrop) {
					doCropPhoto(new File(picPath), cropWidth, cropHeight);
				} else {
					savePicture(picPath, null);
				}
				break;
			case CROPED_PHOTO:
				Bitmap img = data.getParcelableExtra("data");
				// ImageTools.savePhotoToSDCard(img, getPicPath(),
				// getTempImageName());
				savePicture(null, img);
				break;
			default:
				break;
			}

		} else {
			clearFullPath();
		}
	}

	public static void clearFullPath() {
		picPath = null;
	}

	public String getPicPath() {
		return Environment.getExternalStorageDirectory().toString() + "/";
	}

	private void savePicture(String picturePath, Bitmap bitmap) {
		Bitmap photo = null;
		try {
			if (bitmap == null) {
				photo = decodeBitmap(picturePath, width, height);
			} else {
				photo = bitmap;
			}
			savePictrue(photo);
			if (photo != null && !photo.isRecycled()) {
				photo.recycle();
			}
			picPath = getPicPath() + getTempImageName();
			afterSavePhoto(getFullPath());
			File file = new File(getFullPath());
			if (file.exists()) {
				file.delete();
			}
		}

		catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String getFullPath() {
		return picPath;
	}

	protected abstract void afterSavePhoto(String picPath);

	private void savePictrue(Bitmap newBitmap) {
		savePhotoToSDCard(newBitmap, getPicPath(), getTempImageName());
	}

	public static void savePhotoToSDCard(Bitmap photoBitmap, String path,
			String photoName) {
		if (checkSDCardAvailable()) {
			File dir = new File(path);
			if (!dir.exists()) {
				dir.mkdirs();
			}

			File photoFile = new File(path, photoName);
			FileOutputStream fileOutputStream = null;
			try {
				fileOutputStream = new FileOutputStream(photoFile);
				if (photoBitmap != null) {
					if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100,
							fileOutputStream)) {
						fileOutputStream.flush();
					}
				}
			} catch (FileNotFoundException e) {
				photoFile.delete();
				e.printStackTrace();
			} catch (IOException e) {
				photoFile.delete();
				e.printStackTrace();
			} finally {
				try {
					fileOutputStream.close();
					photoBitmap.recycle();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.pick_photo_from_camera) {
			takePickture();
		} else if (v.getId() == R.id.pick_photo_from_gallery) {
			getPicktureFromGallery();
		} else {
			finish();
		}
		// switch(v.getId()){
		// case R.id.pick_photo_from_camera:
		// break;
		// }
		// switch (v.getId()) {
		// case R.id.pick_photo_from_camera:
		// takePickture();
		// break;
		// case R.id.pick_photo_from_gallery:
		// getPicktureFromGallery();
		// break;
		// case R.id.cancel:
		// finish();
		// break;
		// }
	}

	public static boolean checkSDCardAvailable() {
		return android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED);
	}

	private void getPicktureFromGallery() {
		Intent openAlbumIntent = new Intent(Intent.ACTION_PICK);
		openAlbumIntent.setType("image/*");
		startActivityForResult(openAlbumIntent, PHOTO_PICKED_WITH_GALLERY);
	}

	private void takePickture() {
		Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		picPath = getPicPath() + getTempImageName();
		Uri imageUri = Uri.fromFile(new File(picPath));
		openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
		if (doCrop) {
			openCameraIntent.putExtra("return-data", true);
		}
		startActivityForResult(openCameraIntent, PHOTO_PICKED_WITH_CAMERA);
	}

	protected static String getTempImageName() {
		return "IMG_" + "TEMP" + ".png";
		// return FileUtil.getTempPath() + AppConstants.DEFAULT_PIC_NAME;
	}

	@SuppressWarnings("deprecation")
	public String getPathFromURI(String stringExtra) {
		Uri uri = Uri.parse(stringExtra);
		String[] proj = { MediaStore.Images.Media.DATA };
		android.database.Cursor actualimagecursor = PickPhotoActivity.this
				.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);
		return img_path;
	}

	public Bitmap decodeBitmap(String path, int width, int height) {
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		// 通过这个bitmap获取图片的宽和高       
		Bitmap bitmap = BitmapFactory.decodeFile(path, options);
		if (bitmap == null) {
			System.out.println("bitmap为空");
		}
		float realWidth = options.outWidth;
		float realHeight = options.outHeight;
		System.out.println("真实图片高度:" + realHeight + "宽度:" + realWidth);
		int scale = Math.max((int) (realWidth / width),
				(int) (realHeight / height));
		if (scale <= 1) {
			scale = 1;
		}
		options.inSampleSize = scale;
		options.inJustDecodeBounds = false;
		// 注意这次要把options.inJustDecodeBounds 设为 false,这次图片是要读取出来的。  
		//    
		bitmap = BitmapFactory.decodeFile(path, options);
		int w = bitmap.getWidth();
		int h = bitmap.getHeight();
		System.out.println("缩略图高度:" + h + "宽度:" + w);
		return bitmap;
	}

	private void doCropPhoto(File f, int outWith, int outHeight) {
		try {
			// 启动gallery去剪辑这个照片
			final Intent intent = getCropImageIntent(Uri.fromFile(f), outWith,
					outHeight);
			if (act != null)
				act.startActivityForResult(intent, CROPED_PHOTO);
			else
				act.startActivityForResult(intent, CROPED_PHOTO);
		} catch (Exception e) {
			Toast.makeText(act, act.getString(R.string.get_picture_failed),
					Toast.LENGTH_LONG).show();
		}
	}

	private Intent getCropImageIntent(Uri photoUri, int cropWidth,
			int cropHeight) {
		Intent intent = new Intent("com.android.camera.action.CROP")
				.setDataAndType(photoUri, "image/*").putExtra("crop", "true")
				.putExtra("return-data", true);
		intent.putExtra("aspectX", cropWidth);
		intent.putExtra("aspectY", cropHeight);
		intent.putExtra("outputX", cropWidth);
		intent.putExtra("outputY", cropHeight);
		return intent;

	}

}

这个类很长,可能很多人不愿去看,如果觉得界面还凑合的就直接用吧,下面我再如何使用

这个类是一个抽象类,它有抽象方法afterSavePhoto(String picPath),这个方法是选择图片之后会执行的,picPath是选择后的图片所在的位置。所以要用的话,只要自己写一个类并实现该方法,在方法中写上选好图片要做的事就可以了

调用这个类也很简单,像下面这样

/**
	 * 不需要裁剪
	 */
	private void takePhoto() {
		Intent intent = new Intent(this, PhotoTestActicity.class);
		intent.putExtra("doCrop", false);
		this.startActivity(intent);
	}

	/**
	 * 选好图片后需要进行裁剪
	 */
	private void takePhotoCrop() {
		Intent intent = new Intent(this, PhotoTestActicity.class);

		this.startActivity(intent);
	}

在不需要裁剪的时候通过intent的bundle传递标识变量doCrop过去,这时候就不需要裁剪了

总结:这个网上有很多例子,但觉得方便的同学,欢迎使用

代码地址:http://download.csdn.net/detail/u010047390/8469665

时间: 2024-12-29 11:28:45

第三讲 ------- 从系统中选择图片(拍照或从相册中取)的相关文章

Android调用系统相册和相机选择图片并显示在imageview中

Android调用系统相册和相机选择图片并显示在imageview中,在系统调用相机拍摄中,直接返回的是经过压缩处理后的图像,当你直接把返还后的图片放在imageview中时 图片就会非常的模糊,所以要经过先存放在sd中,然后在处理并显示.当调用系统相册时,因为Android系统从4.4版本以后系统不再返回真实的uri路径,而是封装过后的uri路径,所以当你写代码时必须注意,4.4是一个分水岭,4.4以上的版本必须就通过解析和相应的处理才能获取到真实的uri路径. 先上程序运行的结果. 这个是调

Android 如何从系统图库中选择图片

这几天我都在做Android的App,同时学习它的API,我将分享一些我学到的东西,比如: 如何从系统图库中选择图片. 首先,让我们来看看如何将手机系统图库集成到你的App中,然后再从图库中选择图片来做一些事.例如,在Facebook的App,你就可以直接选择手机上的图片上传到你的个人资料. 让我们来做一个简单例子,要求: 屏幕上显示一个按钮和图片视图控件. 点击"载入图片"按钮,将用户重定向到Android的图片库,在那里可以选择一个图片. 一旦图片被选中,图片将在主屏幕上的图片视图

android开发——从相冊中选择图片不裁剪

转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46864777 问题: 在郭神的第一行代码中,第8章的从相冊中选择图片这块,从相冊选一张裁剪后显示到屏幕.可是执行后会发现从相冊选了图片后.没有弹出裁剪的界面,直接返回. 方案: 查找原因时,发现SD卡路径下的output_image.jpg是一个0字节文件.所以 这张图片没有生成.然后我认为是向系统发送选择照片的意图出了问题.我好奇的查看了下系统的图库应用(gallery)源代码

android 从相册中选择图片并判断图片是否旋转

今天在做图片合成时,首先从相册中选择图片,然后判断该图片是否旋转了,今天就讲下图片是否旋转,直接上代码 /** * 读取照片exif信息中的旋转角度 * * @param path * 照片路径 * @return角度 获取从相册中选中图片的角度 */ public static int readPictureDegree(String path) { if (TextUtils.isEmpty(path)) { return 0; } int degree = 0; try { ExifInt

从相册中选择图片进行压缩并用ImageView展示出来

从手机中选择照片这是几乎所有应用的功能之一,主要考虑到一点的就是如果图片太大了,可能会OOM,简单的处理就是对图片进行压缩! <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" and

新浪微博客户端(39)-从图库或相机中选择图片

DJComposeViewController.m #pragma mark - DJComposeToolbar 代理方法 - (void)composeToolbar:(DJComposeToolbar *)toolbar didClickBtnType:(DJComposeToolbarBtnType)btnType { switch (btnType) { case DJComposeToolbarBtnTypeCamera: [self openCameraSurface]; brea

android 选择图片拍照并剪切照片上传到服务器

界面调用方法: pickerPicture 和 pickerPictureOk 为父类方法, 父类方法中调用上传,界面中只需要处理这两个方法即可; 父类中处理打开照片,选择完成 和上传到服务器 调用 上传完成通知界面 选择图片并剪切,4.4的手机不同于其他 package com.idonoo.shareCar.ui.commom.activitys; import java.io.File; import android.app.Activity; import android.content

Android大图片裁剪之手机拍照和从相册中选择注意点

Intent("com.android.camera.action.CROP"):中data.MediaStore.EXTRA_OUTPUT以及return-data data:Parcelable类型 传入的数据类型 MediaStore.EXTRA_OUTPUT:Uri类型 自定义裁切输出的图片存储位置 return-data:boolean类型 是否有返回数据(有返回值,返回Bitmap,没有返回值是因为使用Uri与File相似,所有的操作如裁剪将数据都保存在了Uri中,已经持有

c# 点击按选择图片然后展示在richTextBox中

OpenFileDialog o = new OpenFileDialog(); o.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory; o.Title = "请选择图片"; o.Filter = "jpeg|*.jpeg|jpg|*.jpg|png|*.png|gif|*.gif"; if (o.ShowDialog() == DialogResult.OK) { picPath = o.FileNa