/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.android; import totalcross.*; import java.io.*; import java.lang.reflect.Method; import android.app.*; import android.content.*; import android.content.pm.*; import android.graphics.*; import android.hardware.Camera.PictureCallback; import android.hardware.Camera; import android.media.*; import android.os.*; import android.view.*; import android.view.View.OnClickListener; import android.widget.*; import android.content.res.*; public class CameraViewer extends Activity // guich@tc126_34 { class Preview extends SurfaceView implements SurfaceHolder.Callback { Preview(Context context) { super(context); if (allowRotation) { switch (getResources().getConfiguration().orientation) { case Configuration.ORIENTATION_PORTRAIT: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; case Configuration.ORIENTATION_LANDSCAPE: AndroidUtils.debug("" + getWindowManager().getDefaultDisplay().getRotation()); if (getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_270) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } } else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. holder = getHolder(); holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // DON'T REMOVE THIS! 2.3 (LEVEL 10) STILL REQUIRES IT } // Called once the holder is ready public void surfaceCreated(SurfaceHolder holder) { startPreview(); } // Called when the holder is destroyed public void surfaceDestroyed(SurfaceHolder holder) { stopPreview(); stopRecording(); holder.removeCallback(this); } // Called when holder has changed public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (camera != null) { Camera.Parameters parameters = camera.getParameters(); Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int rotation = getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; } if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); parameters.setPictureFormat(PixelFormat.JPEG); if (Build.VERSION.SDK_INT >= 14 && getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_AUTOFOCUS) && !inFocusExclusionList()) parameters.setFocusMode("continuous-picture"); // FOCUS_MODE_CONTINUOUS_PICTURE if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); int ww = Math.max(width,height); int hh = Math.min(width,height); // parameters.setPreviewSize(ww,hh); parameters.setJpegQuality(stillQuality == 1 ? 75 : stillQuality == 2 ? 85 : 100); if (width != 0 && height != 0) parameters.setPictureSize(ww,hh); try { camera.setParameters(parameters); } catch (RuntimeException re) { AndroidUtils.handleException(re,false); } camera.startPreview(); } } private boolean inFocusExclusionList() { String id = Settings4A.deviceId; return id.indexOf("GT-S7580") != -1; } } SurfaceHolder holder; Camera camera; boolean isMovie; boolean allowRotation; String fileName; int stillQuality, width,height; Preview preview; MediaRecorder recorder; int cameraId; int result; private void startPreview() { if (camera == null) try { // The Surface has been created, acquire the camera and tell it where to draw. if ((camera = Camera.open()) == null) { Method getNumberOfCameras = android.hardware.Camera.class.getMethod("getNumberOfCameras"); if (getNumberOfCameras != null) { int i = (Integer) getNumberOfCameras.invoke(null, (Object[]) null); Method open = android.hardware.Camera.class.getMethod("open", int.class); if (open != null) while (--i >= 0) if ((camera = (Camera) open.invoke(null, i)) != null) { cameraId = i; break; } } } camera.setPreviewDisplay(holder); } catch (Exception e) { AndroidUtils.handleException(e,false); setResult(RESULT_CANCELED); finish(); } } private void stopPreview() { if (camera != null) { try {camera.stopPreview();} catch (Exception e) {e.printStackTrace();} try {camera.release();} catch (Exception e) {e.printStackTrace();} camera = null; } } private void startRecording() throws IllegalStateException, IOException { try {camera.stopPreview();} catch (Exception e) {e.printStackTrace();} // stop camera's preview recorder = new MediaRecorder(); camera.unlock(); recorder.setCamera(camera); recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setVideoEncoder (MediaRecorder.VideoEncoder.DEFAULT); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); recorder.setVideoSize(320,240); recorder.setOutputFile(fileName); recorder.setPreviewDisplay(holder.getSurface()); recorder.prepare(); recorder.start(); // Recording is now started } private void stopRecording() { if (recorder != null) { try {recorder.stop();} catch (Exception e) {e.printStackTrace();} try {recorder.reset();} catch (Exception e) {e.printStackTrace();} // You can reuse the object by going back to setAudioSource() step try {recorder.release();} catch (Exception e) {e.printStackTrace();} // Now the object cannot be reused recorder = null; camera.lock(); stopPreview(); } } /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Bundle b = getIntent().getExtras(); fileName = b.getString("file"); stillQuality = b.getInt("quality"); width = b.getInt("width"); height = b.getInt("height"); allowRotation = b.getBoolean("allowRotation"); isMovie = fileName.endsWith(".3gp"); preview = new Preview(this); ((FrameLayout) findViewById(R.id.preview)).addView(preview); final Button buttonExit = (Button) findViewById(R.id.buttonExit); buttonExit.setOnClickListener(new OnClickListener() { public void onClick(View v) { stopRecording(); setResult(RESULT_CANCELED); finish(); } }); final Button buttonClick = (Button) findViewById(R.id.buttonClick); if (isMovie) buttonClick.setText("Start"); buttonClick.setOnClickListener(new OnClickListener() { public void onClick(View v) { try { if (!isMovie) { if (camera == null) // guich@tc130: prevent NPE startPreview(); if (camera != null) { buttonClick.setClickable(false); camera.takePicture(null, null, jpegCallback); } else { setResult(RESULT_CANCELED); finish(); } } else { if (recorder == null) { buttonClick.setText("Stop"); startRecording(); } else { stopRecording(); setResult(RESULT_OK); finish(); } } } catch (Exception e) { AndroidUtils.handleException(e,false); stopPreview(); setResult(RESULT_CANCELED); finish(); } } }); } // Handles data for jpeg picture PictureCallback jpegCallback = new PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { try { FileOutputStream outStream = new FileOutputStream(fileName); outStream.write(data); outStream.close(); setResult(RESULT_OK); finish(); } catch (Exception e) { AndroidUtils.handleException(e,false); setResult(RESULT_CANCELED); finish(); } } }; }