调用系统相机,相册功能

一开始的思路是这一块的功能单独出去;这样处理又会碰见很多问题.

还是集成在Activity中可能效果更好些,

而且三星的手机调用系统相机会导致调用的Activity会重启生命周期,如果是在fragment中调用的,会碰见更多的问题,做外包的伤不起,想深入下这个问题都没时间,暂时记录下在Activity中解决问题的方法,方便后面使用时直接拿来用.

比如在Activity中点击某个按钮,弹出一个对话框,选择拍照还是选择图片

mButton.setOnClickListener(new OnClickListener() {	
    @Override
     public void onClick(View v) { 
     final CharSequence[] items = { "相册", "拍照", "取消" };
     dlg = new AlertDialog.Builder(RenZhengZPActivity.this)
         .setTitle("选择图片")
         .setItems(  items, 
                     new DialogInterface.OnClickListener() { 
                         public void onClick( DialogInterface dialog, int item) {
                             // 这里item是根据选择的方式,
                             // 在items数组里面定义了两种方式,拍照的下标为1所以就调用拍照方法 
                             if (item == 1) { 
                                 toGetPic(); 
                              } else if (item == 0) {
                                 // toTakePhoto(); 
                                 toGallery();
                              } else if (item == 2) { 
                                  dlg.dismiss(); 
                              } 
                          } 
                      }
                   ).create();
       dlg.show(); 
     } 
  }
);


在Activity中的2个跳转到系统相机和系统相册的方法
 /**
  * 跳转到系统相册, 
  */
private void toGallery() {
		Intent i = new Intent(Intent.ACTION_PICK, 
		                  android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
		startActivityForResult(i, 1);
		//采用下面被注释掉的方法去访问系统相册功能,在Nexus5上会导致崩溃
//		Intent getImage = new Intent(Intent.ACTION_GET_CONTENT);
//		getImage.addCategory(Intent.CATEGORY_OPENABLE);
//		getImage.setType("image/jpeg");
//		startActivityForResult(getImage, 1);
	}

	/**跳转到系统相机,同时指定保存的拍照图片的位置
	*/
	private void toGetPic() {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		// 下面这句指定调用相机拍照后的照片存储的路径
		intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(
				Environment.getExternalStorageDirectory(), "xiaoma.jpg")));
		startActivityForResult(intent, 2);
	}


复写Activity 的onActivityResult方法:

@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		// 如果是直接从相册获取
		case 1:
			Log.i(TAG, "相册获取图片之后回到RenZhengZPActivity,并启动裁剪");
			if (data != null) {
				startPhotoZoom(data.getData());
			}
			break;
		// 如果是调用相机拍照时
		case 2:
			Log.i(TAG, "调用相机拍照获取图片之后回到RenZhengZPActivity,并启动裁剪");
			File temp = new File(Environment.getExternalStorageDirectory()
					+ "/xiaoma.jpg");
			startPhotoZoom(Uri.fromFile(temp));
			break;
		// 取得裁剪后的图片
		case 3:
			Log.i(TAG, "裁剪图片之后,获取图片路径,并添加到集合中");
			if (data != null) {
				setPicToView(data);
			}
			break;
		default:
			break;

		}
		super.onActivityResult(requestCode, resultCode, data);
	}

调用系统的裁剪功能:

/**
	 * 裁剪图片方法实现
	 * 
	 * @param uri
	 */
	public void startPhotoZoom(Uri uri) {

		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", 200);
		intent.putExtra("outputY", 200);
		intent.putExtra("return-data", true);
		startActivityForResult(intent, 3);
	}

保存得到裁剪之后的图片

/**
	 * 保存裁剪之后的图片数据
	 * 
	 * @param picdata
	 */
	private void setPicToView(Intent picdata) {
		Bundle extras = picdata.getExtras();
		if (extras != null) {
			photo = extras.getParcelable("data");
			// 写到SD卡里面,photo就是个流数据: 创建一个文件夹写到SD卡后,创建个集合,保存所有图片路径
			// 3.写到SD卡中,把路径获取到,传过去
			String path = Environment.getExternalStorageDirectory() + "/project/";
			String photoName = Tools.createFileName();
			// 把bitmap以文件路径形式保存到sd卡上
			Tools.savePhotoToSDCard(path, photoName, photo);

			Log.i(TAG, "照片的路径名称:" + path + "/" + photoName);
			//TODO 得打照片路径之后的处理
		}
	}

Tools中的方法:

/**
	 *  获取当前时间给不同文件命名 	
	 * @return
	 */
		public static String createFileName() {
		    String fileName = "";
		    Date date = new Date(System.currentTimeMillis()); // 系统当前时间
		    SimpleDateFormat dateFormat = new SimpleDateFormat(
		            "'IMG'_yyyyMMdd_HHmmss");
		    fileName = dateFormat.format(date) + ".jpg"; 
		    return fileName;
		}
 /**
	  *   将Bitmap 以文件路径形式保存到SD卡上,取出时直接用这个文件路径就行了。
	  *   拿到文件路径就可以File file = new File(文件路径),然后就可以把这个File上传服务器 
	  * @param path
	  * @param photoName
	  * @param photoBitmap
	  */
	 public static void savePhotoToSDCard(String path, String photoName,
		            Bitmap photoBitmap) {
		        if (android.os.Environment.getExternalStorageState().equals(
		                android.os.Environment.MEDIA_MOUNTED)) {
		            File dir = new File(path);
		            if (!dir.exists()) {
		                dir.mkdirs();
		            }
		            File photoFile = new File(path, photoName); //在指定路径下创建文件
		            System.out.println(photoFile);
		            FileOutputStream fileOutputStream = null;
		            try {
		                fileOutputStream = new FileOutputStream(photoFile);
		                System.out.println(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 {
		                    if(fileOutputStream!=null){
		                        fileOutputStream.close();
		                    }
		                } catch (IOException e) {
		                    e.printStackTrace();
		                }
		                photoBitmap.recycle();
		            }
		        }
		    }


另外,在调用系统的拍照或者相册之后,如果不需要调用裁剪,也可以直接拿到intent.getData(),可以拿到图片在android系统中的uri,通过uri也可以拿到图片

/**
	 * 在Activity 的 onActivityResult() 中调用 本方法,  如果是从相册选取的照片, 
	 * 调用本方法, 获取照片的的路径
	 * @param activity
	 * @param data
	 * @return
	 */
	public static String loadImgFromGallery(Activity activity, Intent data) {
		if(data == null){
			return null;
		}	
		if (bitMap != null) {
			bitMap.recycle();
		}
		// 外界的程序访问ContentProvider所提供数据 可以通过ContentResolver接口
		ContentResolver resolver = activity.getContentResolver();
		// 此处的用于判断接收的Activity是不是你想要的那个
		try {
			Uri originalUri = data.getData(); // 获得图片的uri
			// 显得到bitmap图片
			//TODO
			Bitmap bitmap = getThumbnail(Uri uri,int size);
			
			// 这里开始的第二部分,获取图片的路径:
			String[] proj = { MediaStore.Images.Media.DATA };
			// 好像是android多媒体数据库的封装接口,具体的看Android文档
			Cursor cursor = activity.managedQuery(originalUri, proj, null, null, null);
			// 按我个人理解 这个是获得用户选择的图片的索引值
			int column_index = cursor
					.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			// 将光标移至开头 ,这个很重要,不小心很容易引起越界
			cursor.moveToFirst();
			return cursor.getString(column_index);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

通过uri 拿取到图片bitmap对象

(方法来源:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0826/1665.html)

/**
* size 宽和高的最大值
*/
public static Bitmap getThumbnail(Uri uri,int size) throws FileNotFoundException, IOException{
    //通过uri拿取到输入流
    InputStream input = this.getContentResolver().openInputStream(uri); 
    //拿到Option对象, 设置一些优化的属性
    BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
    onlyBoundsOptions.inJustDecodeBounds = true;
    onlyBoundsOptions.inDither=true;//optional
    onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
    BitmapFactory.decodeStream(input, null, onlyBoundsOptions);//从输入流中解码图片,得到图片的option
    input.close();//关闭输入流
    if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)){
        return null;
    }
    int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;//取款高的最大值
    //得到给定的大小和原始大小的比值
    double ratio = (originalSize > size) ? (originalSize / size) : 1.0;
    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
    bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
    bitmapOptions.inDither=true;//optional
    bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
    input = this.getContentResolver().openInputStream(uri);//再次得到输入流
    //根据缩放后的Option得到bitmap
    Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
    input.close();
    return bitmap;
}
private static int getPowerOfTwoForSampleRatio(double ratio){
    int k = Integer.highestOneBit((int)Math.floor(ratio));
    if(k==0) return 1;
    else return k;
}


拍照返回时,因为已经制定了保存相片的地址,所以直接通过地址在sd卡下拿到图片就行了

通过地址拿取图片的方法

/**
	 * 加载本地图片, 略缩图
	 * @param imgPath
	 * @return
	 */
	public static Bitmap getLoacalBitmap(String imgPath) {
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inPreferredConfig = Bitmap.Config.ARGB_8888;
		options.inPurgeable = true;
		options.inInputShareable = true;
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(imgPath);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return BitmapFactory.decodeStream(fis, null, options);
	}


另外一个写的比较好的调用系统相机的博文:(膜拜下)

http://blog.csdn.net/a497393102/article/details/8949727

转载于:https://my.oschina.net/wangxnn/blog/411176

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值