很重要的是加入权限,很多人因为没加入拍照权限而导致运行不能成功。
- <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;
- }
- //获取保存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);
- }
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (mBitmap != null && !mBitmap.isRecycled()) {
- mBitmap.recycle();
- mBitmap = null;
- }
- }
3.intent.putExtra("return-data", true)
true :返回数据 ,不保存裁剪的图片到相册中
false :会将裁剪的图片保存到相册中。