Android自定義照相機 預覽拍照 切換前後置攝像頭

Android提供了Camera來控制拍照,步驟如下:
(1)調用Camera的open()方法打開相機。
(2)調用Camera的getParameters()獲取拍照參數,該方法返回一個Cmera.Parameters對象。
(3)調用Camera.Parameters對象對照相的參數進行設置。
(4)調用Camera的setParameters(),並將Camera.Parameters對象作爲參數傳入,這樣就可以對拍照進行參數控制,Android2.3.3以後不用設置。
(5)調用Camerade的startPreview()的方法開始預覽取景,在之前需要調用Camera的setPreviewDisplay(SurfaceHolder holder)設置使用哪個SurfaceView來顯示取得的圖片。
(6)調用Camera的takePicture()方法進行拍照。
(7)程序結束時,要調用Camera的stopPreview()方法停止預覽,並且通過Camera.release()來釋放資源。

需要賦予Camera的權限:

1
2
3
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.CAMERA"/>

下面上代碼:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package com.lyj.camera;

import java.io.BufferedOutputStream;
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.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;

public class MyCameraActivity extends Activity implements SurfaceHolder.Callback {
    private ImageView back, position;//返回和切換前後置攝像頭
    private SurfaceView surface;
    private ImageButton shutter;//快門
    private SurfaceHolder holder;
    private Camera camera;//聲明相機
    private String filepath = "";//照片保存路徑
    private int cameraPosition = 1;//0代表前置攝像頭,1代表後置攝像頭

    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);//拍照過程屏幕一直處於高亮
        //設置手機屏幕朝向,一共有7種
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
        //SCREEN_ORIENTATION_BEHIND: 繼承Activity堆棧中當前Activity下面的那個Activity的方向
        //SCREEN_ORIENTATION_LANDSCAPE: 橫屏(風景照) ,顯示時寬度大於高度 
        //SCREEN_ORIENTATION_PORTRAIT: 豎屏 (肖像照) , 顯示時高度大於寬度 
        //SCREEN_ORIENTATION_SENSOR  由重力感應器來決定屏幕的朝向,它取決於用戶如何持有設備,當設備被旋轉時方向會隨之在橫屏與豎屏之間變化
        //SCREEN_ORIENTATION_NOSENSOR: 忽略物理感應器——即顯示方向與物理感應器無關,不管用戶如何旋轉設備顯示方向都不會隨着改變("unspecified"設置除外)
        //SCREEN_ORIENTATION_UNSPECIFIED: 未指定,此爲默認值,由Android系統自己選擇適當的方向,選擇策略視具體設備的配置情況而定,因此不同的設備會有不同的方向選擇
        //SCREEN_ORIENTATION_USER: 用戶當前的首選方向

        setContentView(R.layout.main);

        back = (ImageView) findViewById(R.id.camera_back);
        position = (ImageView) findViewById(R.id.camera_position);
        surface = (SurfaceView) findViewById(R.id.camera_surface);
        shutter = (ImageButton) findViewById(R.id.camera_shutter);
        holder = surface.getHolder();//獲得句柄
        holder.addCallback(this);//添加回調
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不維護自己的緩衝區,等待屏幕渲染引擎將內容推送到用戶面前

        //設置監聽
        back.setOnClickListener(listener);
        position.setOnClickListener(listener);
        shutter.setOnClickListener(listener);
    }

    //響應點擊事件
    OnClickListener listener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
            case R.id.camera_back:
                //返回
                MyCameraActivity.this.finish();
                break;

            case R.id.camera_position:
                //切換前後攝像頭
                int cameraCount = 0;
                CameraInfo cameraInfo = new 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後置  
                            camera.stopPreview();//停掉原來攝像頭的預覽
                            camera.release();//釋放資源
                            camera = null;//取消原來攝像頭
                            camera = Camera.open(i);//打開當前選中的攝像頭
                            try {
                                camera.setPreviewDisplay(holder);//通過surfaceview顯示取景畫面
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            camera.startPreview();//開始預覽
                            cameraPosition = 0;
                            break;
                        }
                    } else {
                        //現在是前置, 變更爲後置
                        if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表攝像頭的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK後置  
                            camera.stopPreview();//停掉原來攝像頭的預覽
                            camera.release();//釋放資源
                            camera = null;//取消原來攝像頭
                            camera = Camera.open(i);//打開當前選中的攝像頭
                            try {
                                camera.setPreviewDisplay(holder);//通過surfaceview顯示取景畫面
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            camera.startPreview();//開始預覽
                            cameraPosition = 1;
                            break;
                        }
                    }

                }
                break;

            case R.id.camera_shutter:
                //快門
                camera.autoFocus(new AutoFocusCallback() {//自動對焦
                    @Override
                    public void onAutoFocus(boolean success, Camera camera) {
                        // TODO Auto-generated method stub
                        if(success) {
                            //設置參數,並拍照
                            Parameters params = camera.getParameters();
                            params.setPictureFormat(PixelFormat.JPEG);//圖片格式
                            params.setPreviewSize(800, 480);//圖片大小
                            camera.setParameters(params);//將參數設置到我的camera
                            camera.takePicture(null, null, jpeg);//將拍攝到的照片給自定義的對象
                        }
                    }
                });
                break;
            }
        }
    };

    /*surfaceHolder他是系統提供的一個用來設置surfaceView的一個對象,而它通過surfaceView.getHolder()這個方法來獲得。
     Camera提供一個setPreviewDisplay(SurfaceHolder)的方法來連接*/

    //SurfaceHolder.Callback,這是個holder用來顯示surfaceView 數據的接口,他必須實現以下3個方法
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        //當surfaceview創建時開啓相機
        if(camera == null) {
            camera = Camera.open();
            try {
                camera.setPreviewDisplay(holder);//通過surfaceview顯示取景畫面
                camera.startPreview();//開始預覽
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        //當surfaceview關閉時,關閉預覽並釋放資源
        camera.stopPreview();
        camera.release();
        camera = null;
        holder = null;
        surface = null;
    }

    //創建jpeg圖片回調數據對象
    PictureCallback jpeg = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
            try {
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                //自定義文件保存路徑  以拍攝時間區分命名
                filepath = "/sdcard/Messages/MyPictures/"   new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())   ".jpg";
                File file = new File(filepath);
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//將圖片壓縮的流裏面
                bos.flush();// 刷新此緩衝區的輸出流
                bos.close();// 關閉此輸出流並釋放與此流有關的所有系統資源
                camera.stopPreview();//關閉預覽 處理數據
                camera.startPreview();//數據處理完後繼續開始預覽
                bitmap.recycle();//回收bitmap空間
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
}

聲明:eoe文章著作權屬於作者,受法律保護,轉載時請務必以超鏈接形式附帶如下信息

原文作者: lyj724929676

原文地址: http://my.eoe.cn/761385/archive/4226.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章