博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android自定义照相机实现(拍照、保存到SD卡,利用Bundle在Acitivity交换数据)
阅读量:5937 次
发布时间:2019-06-19

本文共 8775 字,大约阅读时间需要 29 分钟。

Android自定义照相机实现

近期小巫在学校有一个创新项目,也不是最近,是一个拖了很久的项目,之前一直没有去搞,最近因为要中期检查,搞得我跟小组成员一阵忙活,其实开发一款照相机软件并不太难,下面就是通过自定义的方式来实现手机照相的功能。

创建一个项目:FingerTakePicture

首先来搞一下界面:

界面效果(无法把预览给截屏下来滴):

权限设置少不了:

主Activity:

package com.wwj.finger;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import android.app.Activity;import android.content.Intent;import android.graphics.PixelFormat;import android.hardware.Camera;import android.hardware.Camera.PictureCallback;import android.os.Bundle;import android.os.Environment;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import android.view.View;import android.view.ViewGroup;import android.widget.Toast;/** * Android手指拍照 *  * @author wwj * @date 2013/4/29 */public class MainActivity extends Activity {    private View layout;    private Camera camera;    private Camera.Parameters parameters = null;    Bundle bundle = null; // 声明一个Bundle对象,用来存储数据    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // 显示界面        setContentView(R.layout.activity_main);        layout = this.findViewById(R.id.buttonLayout);        SurfaceView surfaceView = (SurfaceView) this                .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的句柄添加一个回调函数    }    /**     * 按钮被点击触发的事件     *      * @param v     */    public void btnOnclick(View v) {        if (camera != null) {            switch (v.getId()) {            case R.id.takepicture:                // 拍照                camera.takePicture(null, null, new MyPictureCallback());                break;            }        }    }    /**     * 图片被点击触发的时间     *      * @param v     */    public void imageClick(View v) {        if (v.getId() == R.id.scalePic) {            if (bundle == null) {                Toast.makeText(getApplicationContext(), R.string.takephoto,                        Toast.LENGTH_SHORT).show();            } else {                Intent intent = new Intent(this, ShowPicActivity.class);                intent.putExtras(bundle);                startActivity(intent);            }        }    }    private final class MyPictureCallback implements PictureCallback {        @Override        public void onPictureTaken(byte[] data, Camera camera) {            try {                bundle = new Bundle();                bundle.putByteArray("bytes", data);    //将图片字节数据保存在bundle当中,实现数据交换                saveToSDCard(data); // 保存图片到sd卡中                Toast.makeText(getApplicationContext(), R.string.success,                        Toast.LENGTH_SHORT).show();                camera.startPreview(); // 拍完照后,重新开始预览            } catch (Exception e) {                e.printStackTrace();            }        }    }    /**     * 将拍下来的照片存放在SD卡中     * @param data         * @throws IOException     */    public static void saveToSDCard(byte[] data) throws IOException {        Date date = new Date();        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化时间        String filename = format.format(date) + ".jpg";        File fileFolder = new File(Environment.getExternalStorageDirectory()                + "/finger/");        if (!fileFolder.exists()) { // 如果目录不存在,则创建一个名为"finger"的目录            fileFolder.mkdir();        }        File jpgFile = new File(fileFolder, filename);        FileOutputStream outputStream = new FileOutputStream(jpgFile); // 文件输出流        outputStream.write(data); // 写入sd卡中        outputStream.close(); // 关闭输出流    }    private final class SurfaceCallback implements Callback {        // 拍照状态变化时调用该方法        @Override        public void surfaceChanged(SurfaceHolder holder, int format, int width,                int height) {            parameters = camera.getParameters(); // 获取各项参数            parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式            parameters.setPreviewSize(width, height); // 设置预览大小            parameters.setPreviewFrameRate(5);    //设置每秒显示4帧            parameters.setPictureSize(width, height); // 设置保存的图片尺寸            parameters.setJpegQuality(80); // 设置照片质量        }        // 开始拍照时调用该方法        @Override        public void surfaceCreated(SurfaceHolder holder) {            try {                camera = Camera.open(); // 打开摄像头                camera.setPreviewDisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象                camera.setDisplayOrientation(getPreviewDegree(MainActivity.this));                camera.startPreview(); // 开始预览            } catch (Exception e) {                e.printStackTrace();            }        }        // 停止拍照时调用该方法        @Override        public void surfaceDestroyed(SurfaceHolder holder) {            if (camera != null) {                camera.release(); // 释放照相机                camera = null;            }        }    }    /**     * 点击手机屏幕是,显示两个按钮     */    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            layout.setVisibility(ViewGroup.VISIBLE); // 设置视图可见            break;        }        return true;    }        @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        switch (keyCode) {        case KeyEvent.KEYCODE_CAMERA: // 按下拍照按钮            if (camera != null && event.getRepeatCount() == 0) {                // 拍照                //注:调用takePicture()方法进行拍照是传入了一个PictureCallback对象——当程序获取了拍照所得的图片数据之后                //,PictureCallback对象将会被回调,该对象可以负责对相片进行保存或传入网络                camera.takePicture(null, null, new MyPictureCallback());            }        }        return super.onKeyDown(keyCode, event);    }    // 提供一个静态方法,用于根据手机方向获得相机预览画面旋转的角度    public static int getPreviewDegree(Activity activity) {        // 获得手机的方向        int rotation = activity.getWindowManager().getDefaultDisplay()                .getRotation();        int degree = 0;        // 根据手机的方向计算相机预览画面应该选择的角度        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;    }}

用来显示图片的Activity:

package com.wwj.finger;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 ShowPicActivity extends Activity {    private ImageView ivPic = null; // 显示图片控件    /**     * Activity在创建的时候回调的函数 主要用来初始化一些变量     */    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.showpic);        ivPic = (ImageView) findViewById(R.id.ivPic);        setImageBitmap(getImageFormBundle());    }    /**     * 将MainActivity传过来的图片显示在界面当中     *      * @param bytes     */    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);    }    /**     * 从Bundle对象中获取数据     *      * @return     */    public byte[] getImageFormBundle() {        Intent intent = getIntent();        Bundle data = intent.getExtras();        byte[] bytes = data.getByteArray("bytes");        return bytes;    }    /**     * 将字节数组的图形数据转换为Bitmap     *      * @return     */    private Bitmap byte2Bitmap() {        byte[] data = getImageFormBundle();        // 将byte数组转换成Bitmap对象        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);        return bitmap;    }}

这是小巫那个创新项目的一小部分,已经完美实现简单的照相机功能了,保存图片不会像有些网友提供的代码给定一个特定的文件名,不能保存多张图片,还特定把一些方法封装了一下,有需要的朋友好好看看吧。

 

你可能感兴趣的文章
Activiti6.0,spring5,SSM,工作流引擎,OA
查看>>
第十三章:SpringCloud Config Client的配置
查看>>
使用 GPUImage 实现一个简单相机
查看>>
CoinWhiteBook:区块链在慈善事业中的应用
查看>>
【二】express
查看>>
Mac上基于Github搭建Hexo博客
查看>>
What does corn harvester involve?
查看>>
阿里云服务器ECS开放8080端口
查看>>
前端常用排序详解
查看>>
Spring中实现监听的方法
查看>>
使用Tooltip会出现一个问题,如果行上出现复选框
查看>>
11.03T1 DP
查看>>
P2924 [USACO08DEC]大栅栏Largest Fence
查看>>
jQuery操作table tr td
查看>>
工作总结:MFC自写排序算法(升序)
查看>>
螺旋队列问题之二
查看>>
扩展运算符和解构赋值的理解
查看>>
焦点不在input或textarea中,屏蔽回格按钮
查看>>
后缀数组(suffix array)详解
查看>>
EF 通过DataAnnotations配置属性和类型
查看>>