很重要的是加入权限,很多人因为没加入拍照权限而导致运行不能成功。
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
大概的流程:
1.调用Intent,调用系统的相机。
2.在回调方法中获取返回的bitmap数据。
3.将bitmap数据写入图片文件中。
然后你就可以查看该图片了。
public class TestCamera extends Activity implements OnClickListener {
private Button button;
private ImageView imageView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.acy_testcamera);
button = (Button) findViewById(R.id.buttonPicture);
button.setOnClickListener(this);
imageView = (ImageView) findViewById(R.id.imageView1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
// 获取sdcard状态
String sdStatus = Environment.getExternalStorageState();
// 检测sd是否可用
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) {
return;
}
Bundle bundle = data.getExtras();
// 获取相机返回的数据,并转换为Bitmap图片格式
Bitmap bitmap = (Bitmap) bundle.get("data");
FileOutputStream b = null;
File file = null;
try {
// 创建指定位置的临时文件
file = File.createTempFile("testimg", ".jpg", new File(
Environment.getExternalStorageDirectory() + "/DCIM/"));
b = new FileOutputStream(file.getAbsolutePath());
// 将文件流数据写入图片文件中
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭流
b.flush();
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
imageView.setImageBitmap(bitmap);// 显示bitmap
}
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v == button) {
// 调用系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 1);
}
}
}
裁剪图片:
public class CramaActivity extends Activity {
private ImageView img = null;
private TextView text = null;
private File tempFile = new File(Environment.getExternalStorageDirectory(),
getPhotoFileName());
private static final int PHOTO_REQUEST_TAKEPHOTO = 1;// 拍照
private static final int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择
private static final int PHOTO_REQUEST_CUT = 3;// 结果
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
// TODO Auto-generated method stub
img = (ImageView) findViewById(R.id.img_creama);
text = (TextView) findViewById(R.id.text);
((Button) findViewById(R.id.btn_creama))
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent cameraintent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
// 指定调用相机拍照后照片的储存路径
cameraintent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(tempFile));
startActivityForResult(cameraintent,
PHOTO_REQUEST_TAKEPHOTO);
}
});
}
/**
* 回调
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case PHOTO_REQUEST_TAKEPHOTO:// 当选择拍照时调用
startPhotoZoom(Uri.fromFile(tempFile));
break;
case PHOTO_REQUEST_GALLERY:// 当选择从本地获取图片时
// 做非空判断,当我们觉得不满意想重新剪裁的时候便不会报异常,下同
if (data != null)
startPhotoZoom(data.getData());
break;
case PHOTO_REQUEST_CUT:// 返回的结果
if (data != null)
sentPicToNext(data);
break;
}
}
private 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", 300);
intent.putExtra("outputY", 300);
intent.putExtra("return-data", true);
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, PHOTO_REQUEST_CUT);
}
// 将进行剪裁后的图片传递到下一个界面上
private void sentPicToNext(Intent picdata) {
Bundle bundle = picdata.getExtras();
if (bundle != null) {
Bitmap photo = bundle.getParcelable("data");
if (photo == null) {
img.setImageResource(R.drawable.ic_launcher);
} else {
photo = toRoundCorner((Bitmap) bundle.getParcelable("data"), 50);
Drawable drawable = new BitmapDrawable(this.getResources(),
photo);
img.setImageDrawable(drawable);
// 设置文本内容为 图片绝对路径和名字
text.setText(tempFile.getAbsolutePath());
}
}
}
/**
* 圆角图片处理
*
* @param bitmap
* @param radius半径50
* @return
*/
public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
// 使用系统当前日期加以调整作为照片的名称
private String getPhotoFileName() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat dateFormat = new SimpleDateFormat(
"'IMG'_yyyyMMdd_HHmmss");
return dateFormat.format(date) + ".jpg";
}
}
布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/btn_creama"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="拍照"
tools:context=".CramaActivity" />
<ImageView
android:id="@+id/img_creama"
android:layout_width="150dip"
android:layout_height="150dip"
android:layout_below="@+id/btn_creama"
android:layout_centerHorizontal="true"
android:layout_margin="15dip"
android:background="@drawable/ic_launcher"
android:scaleType="fitXY" />
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/img_creama"
android:background="#22000000"
android:textSize="16sp" />
</RelativeLayout>
效果:
1.在这调用系统相机的时候,开始的因为有个cursor关闭了,结果导致了 不能连接相机服务。那个游标在底层跟相机服务相关,测试了半天才发现这个问题的!
2.data==null
对于小米或者三星等的手机,调用系统相机时切换屏幕,以前的数据会清空掉,请在调用相机之前保存好相关的数据。
这里给出其中一种方法:
/**
* 保存切换屏幕前的数据
*
* @return
*/
@Override
public Object onRetainNonConfigurationInstance() {
Uri data = mCameraImageUri;
return data;
}
然后在oncreate()中获取保存的数据:
//获取保存de数据
if (null == mCameraImageUri) {
mCameraImageUri = (Uri) getLastNonConfigurationInstance();
}
3.Canvas: trying to use a recycled bitmap android.graphics.Bitmap:
在回收之前加判断:
if (null != mBitmap) {
if (b != mBitmap && b != null && !mBitmap.isRecycled()) {
mImageView.setImageBitmapResetBase(b, true);
mBitmap.recycle();
}
mBitmap = b;
if (mImageView.getScale() == 1F) {
mImageView.center(true, true);
}
}
在onDestroy()中回收:
@Override
protected void onDestroy() {
super.onDestroy();
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
mBitmap = null;
}
}
3.intent.putExtra("return-data", true)
true :返回数据 ,不保存裁剪的图片到相册中
false :会将裁剪的图片保存到相册中。