Android自定义相机,简单实现切换前后摄像头,照相机拍照 

Ctrl +C  Ctrl+V 可以直接 run 起来,注释比较详细;源码下载


<?xml version="1.0" encoding="utf-8"?>                                                                                                                


android6.0及以上需要 动态申请相机权限:

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);        }

package com.tomorrow_p.camera_p;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.PixelFormat;import android.hardware.Camera;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.Toast;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;public class MainActivity extends Activity {    private static final String TAG = "ansen";    private View mRelativeLayout;    private Camera mCamera;    private Camera.Parameters mParameters = null;    private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头    private SurfaceHolder mHolder;    Bundle bundle = null; // 声明一个Bundle对象,用来存储数据    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);//        requestWindowFeature(Window.FEATURE_NO_TITLE);//没有标题//        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏//        this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//拍照过程屏幕一直处于高亮        setContentView(R.layout.activity_main);        mRelativeLayout = findViewById(R.id.relativeLayout);        SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);        surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        surfaceView.getHolder().setFixedSize(176, 144); //设置Surface分辨率        surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮        surfaceView.getHolder().addCallback(new SurfaceCallback());//为SurfaceView的句柄添加一个回调函数    }    public void takePhoto(View v) {        if (mCamera != null) {            // 获取到拍照的图片数据后回调PictureCallback,PictureCallback可以对相片进行保存或传入网络            mCamera.takePicture(null, null, new MyPictureCallback());        }    }    public void change(View v) {        //切换前后摄像头        int cameraCount = 0;        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();        cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数        for (int i = 0; i < cameraCount; i++) {            Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息            if (cameraPosition == 1) {                //现在是后置,变更为前置                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置                    mCamera.stopPreview();//停掉原来摄像头的预览                    mCamera.release();//释放资源                    mCamera = null;//取消原来摄像头                    mCamera = Camera.open(i);//打开当前选中的摄像头                    try {                        mCamera.setPreviewDisplay(mHolder);//通过surfaceview显示取景画面                    } catch (IOException e) {                        e.printStackTrace();                    }                    mCamera.startPreview();//开始预览                    cameraPosition = 0;                    break;                }            } else {                //现在是前置, 变更为后置                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置                    mCamera.stopPreview();//停掉原来摄像头的预览                    mCamera.release();//释放资源                    mCamera = null;//取消原来摄像头                    mCamera = Camera.open(i);//打开当前选中的摄像头                    try {                        mCamera.setPreviewDisplay(mHolder);//通过surfaceview显示取景画面                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    mCamera.startPreview();//开始预览                    cameraPosition = 1;                    break;                }            }        }    }    /**     * 图片被点击触发的时间     *     * @param v     */    public void imageClick(View v) {        if (bundle == null) {            Toast.makeText(getApplicationContext(), "没有数据", Toast.LENGTH_SHORT).show();        } else {            Intent intent = new Intent(this, PreviewImageActivity.class);            intent.putExtras(bundle);            startActivity(intent);        }    }    private final class MyPictureCallback implements Camera.PictureCallback {        @Override        public void onPictureTaken(byte[] data, Camera camera) {            try {                bundle = new Bundle();                bundle.putByteArray("bytes", data); //将图片字节数据保存在bundle当中,实现数据交换                saveToSDCard(data); // 保存图片到sd卡中                Toast.makeText(getApplicationContext(), "success", Toast.LENGTH_SHORT).show();//                camera.startPreview(); // 拍完照后,重新开始预览            } catch (Exception e) {                e.printStackTrace();            }        }    }    public void saveToSDCard(byte[] data) throws IOException {        Log.d(TAG, "saveToSDCard");        Date date = new Date();        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化时间        String filename = format.format(date) + ".jpg";        File fileFolder = new File(Environment.getExternalStorageDirectory() + "/ansen/");// Environment.getRootDirectory()        if (!fileFolder.exists()) {            fileFolder.mkdir();        }        File jpgFile = new File(fileFolder, filename);        FileOutputStream outputStream = new FileOutputStream(jpgFile); // 文件输出流        outputStream.write(data);        outputStream.close();        mCamera.startPreview(); // 拍完照后,重新开始预览        if (false) {            Bitmap b = byteToBitmap(data);            // 获取手机屏幕的宽高            WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);            int windowWidth = windowManager.getDefaultDisplay().getWidth();            int windowHight = windowManager.getDefaultDisplay().getHeight();            Bitmap bitmap = Bitmap.createBitmap(b, 0, 0, windowWidth, windowHight);            // 图片压缩            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);            outputStream.flush();        }    }    /**     * 把图片byte流转换成bitmap     */    private Bitmap byteToBitmap(byte[] data) {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        Bitmap b = BitmapFactory.decodeByteArray(data, 0, data.length, options);        int i = 0;        while (true) {            if ((options.outWidth >> i <= 1000)                    && (options.outHeight >> i <= 1000)) {                options.inSampleSize = (int) Math.pow(2.0D, i);                options.inJustDecodeBounds = false;                b = BitmapFactory.decodeByteArray(data, 0, data.length, options);                break;            }            i += 1;        }        return b;    }    /**     * 显示surfaceView 数据的接口     */    private class SurfaceCallback implements SurfaceHolder.Callback {        @Override        public void surfaceChanged(SurfaceHolder holder, int format, int width,                                   int height) {            Log.d(TAG, "surfaceChanged");            mParameters = mCamera.getParameters(); // 获取各项参数            mParameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式            mParameters.setPreviewSize(width, height); // 设置预览大小            mParameters.setPreviewFrameRate(5);  //设置每秒显示4帧            mParameters.setPictureSize(width, height); // 设置保存的图片尺寸            mParameters.setJpegQuality(80); // 设置照片质量        }        @Override        public void surfaceCreated(SurfaceHolder holder) {            Log.d(TAG, "surfaceCreated");            mHolder = holder;// SurfaceHolder是系统提供用来设置surfaceView的对象            try {                mCamera = Camera.open(); // 打开摄像头                mCamera.setPreviewDisplay(holder); //通过surfaceview显示取景画面                mCamera.setDisplayOrientation(getPreviewDegree(MainActivity.this));// 设置相机的方向                mCamera.startPreview(); // 开始预览            } catch (Exception e) {                e.printStackTrace();                Log.e(TAG, "surfaceCreated >>  Exception: " + e.getMessage());            }        }        @Override        public void surfaceDestroyed(SurfaceHolder holder) {            Log.d(TAG, "surfaceDestroyed");            if (mCamera != null) {                mCamera.release(); // 释放照相机                mCamera = null;            }        }    }    /**     * 点击手机屏幕是,显示两个按钮     */    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                mRelativeLayout.setVisibility(ViewGroup.VISIBLE); // 设置视图可见                break;        }        return true;    }    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        switch (keyCode) {            case KeyEvent.KEYCODE_CAMERA:                if (mCamera != null && event.getRepeatCount() == 0) {                    // 获取到拍照的图片数据后回调PictureCallback,PictureCallback可以对相片进行保存或传入网络                    mCamera.takePicture(null, null, new MyPictureCallback());                }        }        return super.onKeyDown(keyCode, event);    }    // 用于根据手机方向获得相机预览画面旋转的角度    public static int getPreviewDegree(Activity activity) {        int degree = 0;        // 获得手机的方向        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();        Log.d(TAG, "rotation : " + rotation);        // 根据手机的方向计算相机预览画面应该选择的角度        switch (rotation) {            case Surface.ROTATION_0:                degree = 90;                break;            case Surface.ROTATION_90:                degree = 0;                break;            case Surface.ROTATION_180:                degree = 270;                break;            case Surface.ROTATION_270:                degree = 180;                break;        }        return degree;    }}


<?xml version="1.0" encoding="utf-8"?>                

package com.tomorrow_p.camera_p;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.os.Bundle;import android.widget.ImageView;public class PreviewImageActivity extends Activity {    private ImageView ivPic = null; // 显示图片控件    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.preview_image);        ivPic = (ImageView) findViewById(R.id.imageView);        setImageBitmap(getImageFormBundle());    }    public void setImageBitmap(byte[] bytes) {        Bitmap cameraBitmap = byte2Bitmap();        // 根据拍摄的方向旋转图像(纵向拍摄时要需要将图像选择90度)        Matrix matrix = new Matrix();        matrix.setRotate(MainActivity.getPreviewDegree(this));        cameraBitmap = Bitmap                .createBitmap(cameraBitmap, 0, 0, cameraBitmap.getWidth(),                        cameraBitmap.getHeight(), matrix, true);        ivPic.setImageBitmap(cameraBitmap);    }    public byte[] getImageFormBundle() {        Intent intent = getIntent();        Bundle data = intent.getExtras();        byte[] bytes = data.getByteArray("bytes");        return bytes;    }    /**     * 将字节数组的图形数据转换为Bitmap     */    private Bitmap byte2Bitmap() {        byte[] data = getImageFormBundle();        // 将byte数组转换成Bitmap对象        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);        return bitmap;    }}




更多相关文章

  1. [转]Android(安卓)Audio简述
  2. android 动态设置Activity 的切换方向
  3. android之实现底部TabHost
  4. Android之进度条
  5. Android小知识积累
  6. Android(安卓)软键盘问题总结
  7. ExpandableListView设置选中child的背景
  8. Android中的AnimationDrawable的使用
  9. Android小问题解决办法记录

随机推荐

  1. Android(安卓)Studio 使用SVN check out
  2. android圆形旋转菜单,教你分分钟搞定它,Cir
  3. Android(安卓)RecyclerView异步更新数据
  4. 《Android(安卓)高性能编程》—— @IntDe
  5. android 记录崩溃日志
  6. Android(安卓)使用 Socket 连接阿里云服
  7. mac版android studio新建项目或导入项目
  8. Android(安卓)2.3 GingerBread for Virtu
  9. 【叨、校长】Android报表工具AChartEngin
  10. 在不使用 android:elevation 属性的情况