一开始的思路是这一块的功能单独出去;这样处理又会碰见很多问题.
还是集成在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