[置顶] android本地图片选择(相册选取,相机拍摄)

作者: lcq5211314123
发布时间:2015-07-28 10:10:06

 最近由于项目的需要,要求用户可以上传自己拍的照片和图库中的已有照片,这是一个App比较基础性的功能,就索性将整个功能抽出来写成一个组件,以方面其它的App再实现此功能时可直接拿来使用.

 话不多说,先看一下效果图,弹出选择方式window :


 点击:Select from gallery,从本地机册中选择图片,如图:


点击:Take a photot就不再上传截图了.

下面将实现的主要代码出,如有需要可稍做修改即可做为一个组件使用,以下没布局文件.

public class TakePhoto
{
	protected Activity mActivity;
	protected Intent mIntent = null;
	
	protected static final int PHOTO_REQUEST_TAKEPHOTO = 0x00000001;
	
	protected static final int PHOTO_REQUEST_CUT = 0x00000002;
	
	protected Uri currentUri = null;
	
	protected TakePhotoListener mTakePhotoListener;
	
	protected View mDisplayView;
	
	private String sdcardPath = null;
	
	private String fileBasePath = null;
	private int aspectX = 1;
	private int aspectY = 1;
	private int outputX = 480;
	private int outputY = 480;

	public TakePhoto(Activity activity, View displayView, TakePhotoListener takePhotoListener)
	{
		this.mActivity = activity;
		this.mDisplayView = displayView;
		this.mTakePhotoListener = takePhotoListener;
		initLocalFilePath(mActivity);
		startSelectImage();
	}

	public TakePhoto(Activity activity, View displayView, int aspectX, int aspectY, int outputX, int outputY,
			TakePhotoListener takePhotoListener)
	{
		this.mActivity = activity;
		this.mDisplayView = displayView;
		this.aspectX = aspectX;
		this.aspectY = aspectY;
		this.outputX = outputX;
		this.outputY = outputY;
		this.mTakePhotoListener = takePhotoListener;
		initLocalFilePath(mActivity);
		startSelectImage();
	}

	
	private void initLocalFilePath(Activity activity)
	{
		sdcardPath = activity.getExternalCacheDir().toString() + "/capturePicture/";
		fileBasePath = "file://" + sdcardPath;
	}

	public void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		switch (requestCode)
		{
		case PHOTO_REQUEST_CUT:
			try
			{
				setDisplayViewImage();
			}
			catch (FileNotFoundException e)
			{
				mTakePhotoListener.onFail(TakePhotoFailReason.FileNotFound);
			}
			catch (OutOfMemoryError e)
			{
				mTakePhotoListener.onFail(TakePhotoFailReason.OutOfMemory);
			}
			break;
		}
	}


	protected void startSelectImage()
	{

	}


	protected Uri getCurrentUri()
	{
		Date date = new Date(System.currentTimeMillis());
		SimpleDateFormat dateFormat = new SimpleDateFormat("'IMG'_yyyyMMdd_HHmmss");
		Log.i("------currentImageUri--------", fileBasePath + dateFormat.format(date) + ".jpg");
		return Uri.parse(fileBasePath + dateFormat.format(date) + ".jpg");
	}

	
	protected void cropImageUri(Uri uri)
	{
		try
		{
			// ���òü�
			mIntent.putExtra("crop", "true");
			// aspectX aspectY �ǿ�ߵı���
			mIntent.putExtra("aspectX", aspectX);
			mIntent.putExtra("aspectY", aspectY);
			// outputX outputY �Dzü�ͼƬ���
			mIntent.putExtra("outputX", outputX);
			mIntent.putExtra("outputY", outputY);
			mIntent.putExtra("scale", true);
			mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
			mIntent.putExtra("return-data", false);
			mIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
			mIntent.putExtra("noFaceDetection", true); // no face detection
			mActivity.startActivityForResult(mIntent, PHOTO_REQUEST_CUT);
		}
		catch (ActivityNotFoundException e)
		{
			mTakePhotoListener.onFail(TakePhotoFailReason.ActivityNotFound);
		}
	}


	protected void setDisplayViewImage() throws FileNotFoundException
	{
		if (currentUri != null)
		{
			Bitmap bitmap = BitmapFactory.decodeFile(currentUri.getPath());
			if (bitmap == null)
			{
				throw new FileNotFoundException();
			}
			if (mDisplayView instanceof ImageView)
			{
				((ImageView) mDisplayView).setImageBitmap(bitmap);
			}
			else
			{
				Drawable drawable = new BitmapDrawable(mActivity.getResources(), bitmap);
				mDisplayView.setBackgroundDrawable(drawable);
			}
			mTakePhotoListener.onSuccess(currentUri.getPath(), mDisplayView, bitmap);
		}
	}

	
	protected boolean existSDCard()
	{
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
		{
			return true;
		}
		else return false;
	}

	
	protected void createPhotoDir()
	{
		File file = new File(sdcardPath);
		if (!file.exists())
		{
			file.mkdirs();
		}
	}

	
	public interface TakePhotoListener
	{
		
		public void onSuccess(String imagePath, View displayView, Bitmap bitmap);

		
		public void onFail(TakePhotoFailReason failReason);
	}


	public enum TakePhotoFailReason
	{
		ActivityNotFound, FileNotFound, OutOfMemory, SDCardNotFound
	}
}

//TakePhoto子类,实现从相机拍照生成图片
package com.focustech.capturepicture;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;
import android.view.View;

public class CameraTakePhoto extends TakePhoto
{
	/**
	 * 构造方法
	 * @param activity		页面对象
	 * @param displayView	图片显示对象
	 * @param takePhotoListener	图片回调
	 */
	public CameraTakePhoto(Activity activity, View displayView, TakePhotoListener takePhotoListener)
	{
		super(activity, displayView, takePhotoListener);
	}

	/**
	 * 构造方法
	 * @param activity	页面对象
	 * @param displayView	图片显示对象
	 * @param aspectX	裁剪宽比例
	 * @param aspectY	裁剪高比例
	 * @param outputX	裁剪宽度
	 * @param outputY	裁剪高度
	 * @param takePhotoListener	图片回调
	 */
	public CameraTakePhoto(Activity activity, View displayView, int aspectX, int aspectY, int outputX, int outputY,
			TakePhotoListener takePhotoListener)
	{
		super(activity, displayView, aspectX, aspectY, outputX, outputY, takePhotoListener);
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		if (resultCode != Activity.RESULT_OK)
		{
			return;
		}
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode)
		{
		case PHOTO_REQUEST_TAKEPHOTO:
			cropCurrentImage(currentUri);
			break;
		}
	}

	private void cropCurrentImage(Uri currentUri)
	{
		mIntent = new Intent("com.android.camera.action.CROP");
		mIntent.setDataAndType(currentUri, "image/*");
		cropImageUri(currentUri);
	}

	@Override
	protected void startSelectImage()
	{
		try
		{
			if (existSDCard())
			{
				createPhotoDir();
				currentUri = getCurrentUri();
				Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
				intent.putExtra(MediaStore.EXTRA_OUTPUT, currentUri);
				mActivity.startActivityForResult(intent, PHOTO_REQUEST_TAKEPHOTO);
			}
			else
			{
				mTakePhotoListener.onFail(TakePhotoFailReason.SDCardNotFound);
			}
		}
		catch (ActivityNotFoundException e)
		{
			mTakePhotoListener.onFail(TakePhotoFailReason.ActivityNotFound);
		}
	}

}

//TakePhoto子类,实现从本地图册中选择图片
public class GalleryTakePhoto extends TakePhoto
{
    /**
     * 构造方法
     * @param activity        页面对象
     * @param displayView    图片显示对象
     * @param takePhotoListener    图片回调
     */
    public GalleryTakePhoto(Activity activity, View displayView, TakePhotoListener takePhotoListener)
    {
        super(activity, displayView, takePhotoListener);
    }

    /**
     * 构造方法
     * @param activity    页面对象
     * @param displayView    图片显示对象
     * @param aspectX    裁剪宽比例
     * @param aspectY    裁剪高比例
     * @param outputX    裁剪宽度
     * @param outputY    裁剪高度
     * @param takePhotoListener    图片回调
     */
    public GalleryTakePhoto(Activity activity, View displayView, int aspectX, int aspectY, int outputX, int outputY,
            TakePhotoListener takePhotoListener)
    {
        super(activity, displayView, aspectX, aspectY, outputX, outputY, takePhotoListener);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        if (resultCode != Activity.RESULT_OK)
        {
            return;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void startSelectImage()
    {
        if (existSDCard())
        {
            createPhotoDir();
            currentUri = getCurrentUri();
            mIntent = new Intent(Intent.ACTION_GET_CONTENT);
            mIntent.setType("image/*");
            cropImageUri(currentUri);
        }
        else
        {
            mTakePhotoListener.onFail(TakePhotoFailReason.SDCardNotFound);
        }
    }
}

测试Activity...

   

package com.focustech.capturepicture;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RelativeLayout;

import com.focustech.capturepicture.TakePhoto.TakePhotoFailReason;
import com.focustech.capturepicture.TakePhoto.TakePhotoListener;

public class TestActivity extends Activity implements OnClickListener
{
	private RelativeLayout img_btn;
	private Button btn1;
	private Button btn2;
	private TakePhoto takePhoto;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
	}

	// ��ʼ���ؼ�
	private void init()
	{
		img_btn = (RelativeLayout) findViewById(R.id.img_btn);
		btn1 = (Button) findViewById(R.id.btn1);
		btn2 = (Button) findViewById(R.id.btn2);

		// ΪImageButton��Button��Ӽ����¼�
		btn1.setOnClickListener(this);
		btn2.setOnClickListener(this);
	}

	// ����¼�
	@Override
	public void onClick(View v)
	{
		switch (v.getId())
		{
		case R.id.btn1:
			// ������õ�Activity,��ʾ�ؼ�����,��ȡͼƬ�ص�
			takePhoto = new CameraTakePhoto(this, img_btn, listener);
			break;
		case R.id.btn2:
			takePhoto = new GalleryTakePhoto(this, img_btn, listener);
			break;
		}
	}

	private TakePhotoListener listener = new TakePhotoListener()
	{
		@Override
		public void onSuccess(String imagePath, View displayView, Bitmap bitmap)
		{
			//���ݴ���Ŀؼ�ID����
			switch (displayView.getId())
			{
			case R.id.img_btn:
				Log.e("==========onSuccess=============", imagePath);
				break;
			}
		}

		@Override
		public void onFail(TakePhotoFailReason failReason)
		{
			Log.e("=======onFail===========", failReason.toString());
		}
	};

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		if (takePhoto != null)
		{
			takePhoto.onActivityResult(requestCode, resultCode, data);
		}
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig)
	{
		super.onConfigurationChanged(newConfig);
	}
}
思路:其实功能是没有什么复杂的,就是调用系统功能去实现自己想要的功能,主要想表达的一点就是组件化的编程,好处是非常之多的,只要一次编写,以后就可以直接拿来用了,也正是体现了Java封装的强大之处.组件整个工程上传到了我的资源里,有需要的请下载。

版权声明:本文为博主原创文章,未经博主允许不得转载。

标签: Android Droid
来源:http://blog.csdn.net/lcq5211314123/article/details/40664233

推荐: