TestingCamera.java revision b28605e5d09a08c915183772819cb1c7c53cdb34
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.testingcamera;
18
19import android.app.Activity;
20import android.app.Dialog;
21import android.graphics.Bitmap;
22import android.graphics.BitmapFactory;
23import android.hardware.Camera;
24import android.os.Bundle;
25import android.view.View;
26import android.view.SurfaceHolder;
27import android.view.SurfaceView;
28import android.widget.AdapterView;
29import android.widget.ArrayAdapter;
30import android.widget.Button;
31import android.widget.ImageView;
32import android.widget.LinearLayout.LayoutParams;
33import android.widget.Spinner;
34import android.widget.CompoundButton;
35import android.widget.TextView;
36import android.widget.ToggleButton;
37import android.util.Log;
38
39import java.io.IOException;
40import java.util.ArrayList;
41import java.util.Comparator;
42import java.util.List;
43import java.util.TreeSet;
44
45/**
46 * A simple test application for the camera API.
47 *
48 * The goal of this application is to allow all camera API features to be
49 * excercised, and all information provided by the API to be shown.
50 */
51public class TestingCamera extends Activity implements SurfaceHolder.Callback {
52
53    /** UI elements */
54    private SurfaceView mPreviewView;
55    private SurfaceHolder mPreviewHolder;
56
57    private Spinner mCameraSpinner;
58    private Spinner mPreviewSizeSpinner;
59    private ToggleButton mPreviewToggle;
60    private Button  mTakePictureButton;
61
62    private TextView mSnapshotText;
63    private ImageView mSnapshotImg;
64
65    /** Camera state */
66    private int mCameraId = 0;
67    private Camera mCamera;
68    private Camera.Parameters mParams;
69    private List<Camera.Size> mPreviewSizes;
70    private int mPreviewSize = 0;
71
72    private static final int CAMERA_UNINITIALIZED = 0;
73    private static final int CAMERA_OPEN = 1;
74    private static final int CAMERA_PREVIEW = 2;
75    private static final int CAMERA_TAKE_PICTURE = 3;
76    private int mState = CAMERA_UNINITIALIZED;
77
78    /** Misc variables */
79
80    private static final String TAG = "TestingCamera";
81
82    // Activity methods
83    @Override
84    public void onCreate(Bundle savedInstanceState) {
85        super.onCreate(savedInstanceState);
86
87        setContentView(R.layout.main);
88
89        mPreviewView = (SurfaceView)findViewById(R.id.preview);
90        mPreviewView.getHolder().addCallback(this);
91
92        mCameraSpinner = (Spinner) findViewById(R.id.camera_spinner);
93        mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
94
95        mPreviewSizeSpinner = (Spinner) findViewById(R.id.preview_size_spinner);
96        mPreviewSizeSpinner.setOnItemSelectedListener(mPreviewSizeListener);
97
98        mPreviewToggle = (ToggleButton) findViewById(R.id.start_preview);
99        mPreviewToggle.setOnClickListener(mPreviewToggleListener);
100
101        mTakePictureButton = (Button) findViewById(R.id.take_picture);
102        mTakePictureButton.setOnClickListener(mTakePictureListener);
103
104        int numCameras = Camera.getNumberOfCameras();
105        String[] cameraNames = new String[numCameras];
106        for (int i = 0; i < numCameras; i++) {
107            cameraNames[i] = "Camera " + i;
108        }
109
110        mCameraSpinner.setAdapter(
111                new ArrayAdapter<String>(this,
112                        R.layout.spinner_item, cameraNames));
113    }
114
115    @Override
116    public void onResume() {
117        super.onResume();
118        mPreviewHolder = null;
119        setUpCamera();
120    }
121
122    @Override
123    public void onPause() {
124        super.onPause();
125
126        mCamera.release();
127        mState = CAMERA_UNINITIALIZED;
128    }
129
130    protected Dialog onCreateDialog(int id) {
131        Dialog dialog = new Dialog(this);
132        dialog.setContentView(R.layout.snapshot_dialog);
133        dialog.setTitle("Snapshot");
134
135        mSnapshotText =
136                (TextView) dialog.findViewById(R.id.snapshot_text);
137        mSnapshotText.setText("Snapshot title");
138
139        mSnapshotImg =
140                (ImageView) dialog.findViewById(R.id.snapshot_image);
141
142        return dialog;
143    }
144
145    // SurfaceHolder.Callback methods
146    @Override
147    public void surfaceChanged(SurfaceHolder holder,
148            int format,
149            int width,
150            int height) {
151        if (mPreviewHolder != null) return;
152
153        Log.d(TAG, "Surface holder available: " + width + " x " + height);
154        mPreviewHolder = holder;
155        try {
156            mCamera.setPreviewDisplay(holder);
157        } catch (IOException e) {
158            Log.e(TAG, "Unable to set up preview!");
159        }
160        resizePreview(mPreviewSizes.get(mPreviewSize).width,
161                mPreviewSizes.get(mPreviewSize).height);
162    }
163
164    @Override
165    public void surfaceCreated(SurfaceHolder holder) {
166
167    }
168
169    @Override
170    public void surfaceDestroyed(SurfaceHolder holder) {
171
172    }
173
174    // UI listeners
175
176    private AdapterView.OnItemSelectedListener mCameraSpinnerListener =
177            new AdapterView.OnItemSelectedListener() {
178                public void onItemSelected(AdapterView<?> parent,
179                        View view, int pos, long id) {
180                    if (mCameraId != pos) {
181                        mCameraId = pos;
182                        setUpCamera();
183                    }
184                }
185
186                public void onNothingSelected(AdapterView parent) {
187
188                }
189            };
190
191    private AdapterView.OnItemSelectedListener mPreviewSizeListener =
192            new AdapterView.OnItemSelectedListener() {
193                public void onItemSelected(AdapterView<?> parent,
194                        View view, int pos, long id) {
195                    if (pos == mPreviewSize) return;
196                    Log.d(TAG, "Switching preview sizes");
197
198                    if (mState == CAMERA_PREVIEW) {
199                        mCamera.stopPreview();
200                    }
201
202                    mPreviewSize = pos;
203                    int width = mPreviewSizes.get(mPreviewSize).width;
204                    int height = mPreviewSizes.get(mPreviewSize).height;
205                    mParams.setPreviewSize(width, height);
206
207                    mCamera.setParameters(mParams);
208                    resizePreview(width, height);
209
210                    if (mState == CAMERA_PREVIEW) {
211                        mCamera.startPreview();
212                    }
213                }
214
215                public void onNothingSelected(AdapterView parent) {
216
217                }
218            };
219
220    private View.OnClickListener mPreviewToggleListener =
221            new View.OnClickListener() {
222        public void onClick(View v) {
223            if (mState == CAMERA_TAKE_PICTURE) {
224                Log.e(TAG, "Can't change preview state while taking picture!");
225                return;
226            }
227            if (mPreviewToggle.isChecked()) {
228                Log.d(TAG, "Starting preview");
229
230                mCamera.startPreview();
231                mState = CAMERA_PREVIEW;
232
233                mTakePictureButton.setEnabled(true);
234            } else {
235                Log.d(TAG, "Stopping preview");
236                mCamera.stopPreview();
237                mState = CAMERA_OPEN;
238
239                mTakePictureButton.setEnabled(false);
240            }
241        }
242    };
243
244    private View.OnClickListener mTakePictureListener =
245            new View.OnClickListener() {
246        public void onClick(View v) {
247            Log.d(TAG, "Taking picture");
248            if (mState == CAMERA_PREVIEW) {
249                mState = CAMERA_TAKE_PICTURE;
250
251                mTakePictureButton.setEnabled(false);
252                mPreviewToggle.setEnabled(false);
253                mPreviewToggle.setChecked(false);
254
255                mCamera.takePicture(mShutterCb, mRawCb, mPostviewCb, mJpegCb);
256            } else {
257                Log.e(TAG, "Can't take picture while not running preview!");
258            }
259        }
260    };
261
262    private Camera.ShutterCallback mShutterCb = new Camera.ShutterCallback() {
263        public void onShutter() {
264            Log.d(TAG, "Shutter cb fired");
265        }
266    };
267
268    private Camera.PictureCallback mRawCb = new Camera.PictureCallback() {
269        public void onPictureTaken(byte[] data, Camera camera) {
270            Log.d(TAG, "Raw cb fired");
271        }
272    };
273
274    private Camera.PictureCallback mPostviewCb = new Camera.PictureCallback() {
275        public void onPictureTaken(byte[] data, Camera camera) {
276            Log.d(TAG, "Postview cb fired");
277        }
278    };
279
280    private Camera.PictureCallback mJpegCb = new Camera.PictureCallback() {
281        public void onPictureTaken(byte[] data, Camera camera) {
282            Log.d(TAG, "JPEG cb fired");
283
284            showDialog(1);
285
286            Bitmap img = BitmapFactory.decodeByteArray(data, 0, data.length);
287            mSnapshotImg.setImageBitmap(img);
288
289            mPreviewToggle.setEnabled(true);
290
291            mState = CAMERA_OPEN;
292        }
293    };
294
295    // Internal methods
296
297    void setUpCamera() {
298        Log.d(TAG, "Setting up camera " + mCameraId);
299        if (mState >= CAMERA_OPEN) {
300            Log.d(TAG, "Closing old camera");
301            mCamera.release();
302            mState = CAMERA_UNINITIALIZED;
303        }
304        Log.d(TAG, "Opening camera " + mCameraId);
305        mCamera = Camera.open(mCameraId);
306        mState = CAMERA_OPEN;
307
308        mParams = mCamera.getParameters();
309        mPreviewSizes = mParams.getSupportedPreviewSizes();
310
311        String[] availableSizeNames = new String[mPreviewSizes.size()];
312        for (int i = 0; i < mPreviewSizes.size(); i++) {
313            availableSizeNames[i] =
314                    Integer.toString(mPreviewSizes.get(i).width) + " x " +
315                    Integer.toString(mPreviewSizes.get(i).height);
316        }
317        mPreviewSizeSpinner.setAdapter(
318            new ArrayAdapter<String>(
319                this, R.layout.spinner_item, availableSizeNames));
320
321        mPreviewSize = 0;
322
323        int width = mPreviewSizes.get(mPreviewSize).width;
324        int height = mPreviewSizes.get(mPreviewSize).height;
325        mParams.setPreviewSize(width, height);
326
327        mCamera.setParameters(mParams);
328
329        if (mPreviewHolder != null) {
330            try {
331                mCamera.setPreviewDisplay(mPreviewHolder);
332            } catch(IOException e) {
333                Log.e(TAG, "Unable to set up preview!");
334            }
335        }
336
337        mPreviewToggle.setEnabled(true);
338        mPreviewToggle.setChecked(false);
339        mTakePictureButton.setEnabled(false);
340
341        resizePreview(width, height);
342        if (mPreviewToggle.isChecked()) {
343            Log.d(TAG, "Starting preview" );
344             mCamera.startPreview();
345            mState = CAMERA_PREVIEW;
346        }
347    }
348
349    void resizePreview(int width, int height) {
350        if (mPreviewHolder != null) {
351            int viewHeight = mPreviewView.getHeight();
352            int viewWidth = (int)(((double)width)/height * viewHeight);
353
354            mPreviewView.setLayoutParams(
355                new LayoutParams(viewWidth, viewHeight));
356        }
357
358    }
359}