Android Open Source - CamTimer Main Activity






From Project

Back to project page CamTimer.

License

The source code is released under:

GNU General Public License

If you think the Android project CamTimer listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.dozingcatsoftware.cameratimer;
/* w  w  w  . ja v a  2 s  .  c o m*/
import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.dozingcatsoftware.cameratimer.R;
import com.dozingcatsoftware.cameratimer.AboutActivity;

import com.dozingcatsoftware.util.ARManager;
import com.dozingcatsoftware.util.AndroidUtils;
import com.dozingcatsoftware.util.CameraUtils;
import com.dozingcatsoftware.util.ShutterButton;
import com.dozingcatsoftware.util.ShutterButton.OnShutterButtonListener;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import android.hardware.Camera;

public class MainActivity extends Activity implements Camera.PictureCallback, Camera.AutoFocusCallback, OnShutterButtonListener {
  
  static final List<Integer> DELAY_DURATIONS = Arrays.asList(0, 5, 15, 30);
  static final int DEFAULT_DELAY = 5;
  static final String DELAY_PREFERENCES_KEY = "delay";
  int pictureDelay = DEFAULT_DELAY;
  
  static final String FLASH_MODE_AUTO = "auto";
  static final String FLASH_MODE_ON = "on";
  static final String FLASH_MODE_OFF = "off";
  
  Map<String, String> flashButtonLabels = new HashMap<String, String>();
  
  ARManager arManager;
  SurfaceView cameraView;
  int[] maxCameraViewSize;
  
  ShutterButton shutterButton;
  Button pictureDelayButton;
  Button cancelPictureButton;
  Button switchCameraButton;
  Button flashButton;
  Button numberOfPicturesButton;
  TextView statusTextField;
  
  // only one beep type for now
  //int beepType;
  //int numBeepTypes = 3;
  //Random RAND = new Random();
  
  // assign ID when we start a timed picture, used in makeDecrementTimerFunction callback. If the ID changes, the countdown will stop.
  int currentPictureID = 0;
  
  // PictureView works, but for timed pictures it makes more sense to always go to ViewImageActivity
  // since the user may not be by the camera when it takes the picture
  //PictureView pictureView;
  Uri pictureURI;
  
  Handler handler = new Handler();
  int pictureTimer = 0;
  boolean hasMultipleCameras;
  
  List<String> flashModes = new ArrayList<String>();
  int selectedFlashMode;
  boolean flashButtonConfigured = false;
  
  int picturesToTake = 1;
  List<Uri> pictureURIs;
  
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
      setContentView(R.layout.main);
      
    flashButtonLabels.put(FLASH_MODE_AUTO, getString(R.string.flashButtonAutoLabel));
    flashButtonLabels.put(FLASH_MODE_ON, getString(R.string.flashButtonOnLabel));
    flashButtonLabels.put(FLASH_MODE_OFF, getString(R.string.flashButtonOffLabel));
      
      cameraView = (SurfaceView)findViewById(R.id.cameraView);
      arManager = ARManager.createAndSetupCameraView(this, cameraView, null);
      arManager.setCameraOpenedCallback(new Runnable() {public void run() {cameraOpened();}});
      arManager.setCameraStartedCallback(new Runnable() {public void run() {cameraPreviewStarted();}});
      
      shutterButton = (ShutterButton)findViewById(R.id.shutterButton);
      shutterButton.setOnShutterButtonListener(this);
      pictureDelayButton = (Button)findViewById(R.id.pictureDelayButton);
      
      cancelPictureButton = (Button)findViewById(R.id.cancelPictureButton);
      flashButton = (Button)findViewById(R.id.flashButton);
      numberOfPicturesButton = (Button)findViewById(R.id.numberOfPicturesButton);
      
      switchCameraButton = (Button)findViewById(R.id.switchCameraButton);
      hasMultipleCameras = (CameraUtils.numberOfCameras() > 1);
      switchCameraButton.setVisibility(hasMultipleCameras ? View.VISIBLE : View.GONE);
      
      statusTextField = (TextView)findViewById(R.id.statusText);
      
      AndroidUtils.bindOnClickListener(this, pictureDelayButton, "cycleDelay");
      AndroidUtils.bindOnClickListener(this, cancelPictureButton, "cancelSavePicture");
      AndroidUtils.bindOnClickListener(this, switchCameraButton, "switchCamera");
      AndroidUtils.bindOnClickListener(this, flashButton, "cycleFlashMode");
      AndroidUtils.bindOnClickListener(this, numberOfPicturesButton, "toggleNumberOfPictures");
      AndroidUtils.bindOnClickListener(this, findViewById(R.id.helpButton), "doHelp");
      AndroidUtils.bindOnClickListener(this, findViewById(R.id.libraryButton), "openLibrary");
      
      this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
      this.readDelayPreference();
    }

    @Override
    public void onPause() {
      if (pictureTimer > 0) {
        this.cancelSavePicture();
      }
      arManager.stopCamera();
      super.onPause();
    }
    
    @Override
    public void onResume() {
      super.onResume();
      arManager.startCameraIfVisible();
      AndroidUtils.setSystemUiLowProfile(cameraView);
    }
    
    // callback from ARManager
    public void cameraOpened() {
      if (maxCameraViewSize==null) {
        maxCameraViewSize = new int[] {cameraView.getWidth(), cameraView.getHeight()};
      }
      arManager.setPreferredPreviewSize(maxCameraViewSize[0], maxCameraViewSize[1]);
      CameraUtils.setLargestCameraSize(arManager.getCamera());
      //statusTextField.setText(arManager.getCamera().getParameters().getPictureSize().width+"");
      if (!flashButtonConfigured) {
        configureFlashButton();
        flashButtonConfigured = true;
      }
    }
    
    public void cameraPreviewStarted() {
      // resize camera view to scaled size of preview image
      Camera.Size size = arManager.getCamera().getParameters().getPreviewSize();
      int[] scaledWH = AndroidUtils.scaledWidthAndHeightToMaximum(
          size.width, size.height, maxCameraViewSize[0], maxCameraViewSize[1]);
      cameraView.setLayoutParams(new FrameLayout.LayoutParams(scaledWH[0], scaledWH[1], Gravity.CENTER));
    }
    
    void updateButtons(boolean allowSave) {
      this.findViewById(R.id.miscButtonBar).setVisibility(allowSave ? View.VISIBLE : View.GONE);
      this.findViewById(R.id.optionsButtonBar).setVisibility(allowSave ? View.VISIBLE : View.GONE);
      shutterButton.setVisibility(allowSave ? View.VISIBLE : View.GONE);
    cancelPictureButton.setVisibility(allowSave ? View.GONE : View.VISIBLE);
    }
    
    public void cancelSavePicture() {
      pictureTimer = 0;
      ++currentPictureID;
      statusTextField.setText("");
      Toast.makeText(this, getString(R.string.canceledPictureMessage), Toast.LENGTH_SHORT).show();
      updateButtons(true);
    }
    
    void updateTimerMessage() {
      String messageFormat = getString(R.string.timerCountdownMessageFormat);
      statusTextField.setText(String.format(messageFormat, pictureTimer));
    }
    
    Runnable makeDecrementTimerFunction(final int pictureID) {
      return new Runnable() {
        public void run() {decrementTimer(pictureID);}
      };
    }
    
    MediaPlayer.OnCompletionListener releaseMediaPlayerFunction = new MediaPlayer.OnCompletionListener() {
    public void onCompletion(MediaPlayer mp) {
      mp.release();
    }
  };
    
    void playTimerBeep() {
      int soundResource = R.raw.beep_sound0;
      MediaPlayer mp = MediaPlayer.create(this, soundResource);
      mp.start();
      mp.setOnCompletionListener(releaseMediaPlayerFunction);
    }
    
    public void decrementTimer(final int pictureID) {
      if (pictureID!=this.currentPictureID) {
        return;
      }
      boolean takePicture = (pictureTimer==1);
      --pictureTimer;
      if (takePicture) {
        savePictureNow();
        playTimerBeep();
      }
      else if (pictureTimer>0) {
        updateTimerMessage();
        handler.postDelayed(makeDecrementTimerFunction(pictureID), 1000);
        if (pictureTimer<3) playTimerBeep();
      }
    }
    
    public void savePicture() {
      if (this.pictureDelay==0) {
        savePictureNow();
      }
      else {
          savePictureAfterDelay(this.pictureDelay);
      }
    }
    
    void savePictureAfterDelay(int delay) {
      pictureTimer = delay;
      updateTimerMessage();
      currentPictureID++;
    handler.postDelayed(makeDecrementTimerFunction(currentPictureID), 1000);
    //beepType = RAND.nextInt(numBeepTypes);
    
    updateButtons(false);
    }
    
    public void savePictureNow() {
      pictureURIs = new ArrayList<Uri>();
    statusTextField.setText("Taking picture...");
    arManager.getCamera().autoFocus(this);
    }
    
    public void switchCamera() {
      flashButtonConfigured = false;
      arManager.switchToNextCamera();
    }
    
    void configureFlashButton() {
      flashModes.clear();
      if (CameraUtils.cameraSupportsFlash(arManager.getCamera())) {
        if (CameraUtils.cameraSupportsAutoFlash(arManager.getCamera())) {
          flashModes.add(FLASH_MODE_AUTO);
        }
        flashModes.add(FLASH_MODE_OFF);
        flashModes.add(FLASH_MODE_ON);
      }
      
      if (flashModes.size() > 0) {
        flashButton.setVisibility(View.VISIBLE);
        updateFlashMode(0);
        String mode = flashModes.get(selectedFlashMode);
        flashButton.setText(flashButtonLabels.get(mode));
        CameraUtils.setFlashMode(arManager.getCamera(), mode);
      }
      else {
        flashButton.setVisibility(View.GONE);
      }
    }
    
    public void cycleDelay() {
      int index = DELAY_DURATIONS.indexOf(this.pictureDelay);
      if (index<0) {
        this.pictureDelay = DEFAULT_DELAY;
      }
      else {
        this.pictureDelay = DELAY_DURATIONS.get((index+1) % DELAY_DURATIONS.size());
      }
      writeDelayPreference();
      updateDelayButton();
    }
    
    void writeDelayPreference() {
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
      SharedPreferences.Editor editor = prefs.edit();
      editor.putInt(DELAY_PREFERENCES_KEY, this.pictureDelay);
      editor.commit();
    }
    
    void readDelayPreference() {
      // reads picture delay from preferences, updates this.pictureDelay and delay button text
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
      int delay = prefs.getInt(DELAY_PREFERENCES_KEY, -1);
      if (!DELAY_DURATIONS.contains(delay)) {
        delay = DEFAULT_DELAY;
      }
      this.pictureDelay = delay;
      updateDelayButton();
    }
    
    void updateDelayButton() {
      if (pictureDelay==0) {
        pictureDelayButton.setText(getString(R.string.delayButtonLabelNone));
      }
      else {
          String labelFormat = getString(R.string.delayButtonLabelSecondsFormat);
          pictureDelayButton.setText(String.format(labelFormat, this.pictureDelay));
      }
    }
    
    public void cycleFlashMode() {
      if (flashModes.size() > 0) {
        selectedFlashMode = (selectedFlashMode + 1) % flashModes.size();
        updateFlashMode(selectedFlashMode);
      }
    }
    
    void updateFlashMode(int mode) {
      selectedFlashMode = mode;
      String modeString = flashModes.get(selectedFlashMode);
    flashButton.setText("Flash: " + modeString.substring(0,1).toUpperCase() + modeString.substring(1));
    CameraUtils.setFlashMode(arManager.getCamera(), modeString);
    }
    
    public void toggleNumberOfPictures() {
      picturesToTake = (picturesToTake==1) ? 4 : 1;
      numberOfPicturesButton.setText(picturesToTake==1 ? R.string.singleImageButtonLabel : R.string.multiImageButtonLabel);
    }
    
    public void doHelp() {
      AboutActivity.startIntent(this);
    }
    
  @Override
  public void onAutoFocus(boolean success, Camera camera) {
    camera.takePicture(null, null, this);
  }

  @Override
  public void onPictureTaken(byte[] data, final Camera camera) {
    int pictureNum = (picturesToTake > 1) ? pictureURIs.size() + 1 : 0;
    pictureURI = saveImageData(data, pictureNum);
    statusTextField.setText("");
    updateButtons(true);
    camera.startPreview();
    
    if (pictureURI!=null) {
      pictureURIs.add(pictureURI);
      if (pictureURIs.size() >= picturesToTake) {
        if (picturesToTake==1) {
          ViewImageActivity.startActivityWithImageURI(this, pictureURI, "image/jpeg");
        }
        else {
          ViewImageGridActivity.startActivityWithImageURIs(this, pictureURIs);
        }
      }
      else {
        // OG Droid and possibly other phones often hang if we call takePicture directly instead of autoFocus
        handler.postDelayed(new Runnable() {
          public void run() {
            camera.autoFocus(MainActivity.this);
          }
        }, 100);
      }
      // send the same NEW_PICTURE broadcast that the standard camera app does
      try {
          Intent newPictureIntent = new Intent("android.hardware.action.NEW_PICTURE");
          newPictureIntent.setDataAndType(pictureURI, "image/jpeg");
          this.sendBroadcast(newPictureIntent);
      }
      catch(Exception ex) {
          Log.e("CamTimer", "Error broadcasting new picture", ex);
      }
    }
  }
  
  String savedImageDirectory = Environment.getExternalStorageDirectory() + File.separator + "CamTimer";
  Format dateInFilename = new SimpleDateFormat("yyyyMMdd_HHmmss");
  
  Uri saveImageData(byte[] data, int pictureNum) {
    try {
        File dir = new File(savedImageDirectory);
        if (!dir.exists()) {
           dir.mkdirs();
        }
        if (!dir.isDirectory()) {
          Toast.makeText(this, "Error saving picture: can't create directory " + dir.getPath(), Toast.LENGTH_LONG).show();
          return null;
        }
      String filename = String.format("IMG_" + dateInFilename.format(new Date()));
      if (pictureNum > 0) filename += ("-" + pictureNum);
      filename += ".jpg";
      
      String path = savedImageDirectory + File.separator + filename;
      FileOutputStream out = new FileOutputStream(path);
      out.write(data);
      out.close();
      
      AndroidUtils.scanSavedMediaFile(this, path);
      Toast.makeText(this, getString(R.string.savedPictureMessage), Toast.LENGTH_SHORT).show();
      
      return Uri.fromFile(new File(path));
    }
    catch(Exception ex) {
      Toast.makeText(this, "Error saving picture: " + ex.getClass().getName(), Toast.LENGTH_LONG).show();
      return null;
    }
  }

  public void openLibrary() {
    startActivity(LibraryActivity.intentWithImageDirectory(this, savedImageDirectory));
  }
  
    @Override
    public void onShutterButtonFocus(boolean pressed) {
        shutterButton.setImageResource(pressed ? R.drawable.btn_camera_shutter_pressed_holo : 
                                                 R.drawable.btn_camera_shutter_holo);
    }

    @Override
    public void onShutterButtonClick() {
        savePicture();
    }
}




Java Source Code List

com.dozingcatsoftware.cameratimer.AboutActivity.java
com.dozingcatsoftware.cameratimer.LibraryActivity.java
com.dozingcatsoftware.cameratimer.MainActivity.java
com.dozingcatsoftware.cameratimer.PictureView.java
com.dozingcatsoftware.cameratimer.ViewImageActivity.java
com.dozingcatsoftware.cameratimer.ViewImageGridActivity.java
com.dozingcatsoftware.util.ARManager.java
com.dozingcatsoftware.util.AndroidUtils.java
com.dozingcatsoftware.util.AsyncImageLoader.java
com.dozingcatsoftware.util.CameraUtils.java
com.dozingcatsoftware.util.FrameRateManager.java
com.dozingcatsoftware.util.ScaledBitmapCache.java
com.dozingcatsoftware.util.ShutterButton.java