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}