Android Open Source - SpartanTimeLapseRecorder Preview Activity






From Project

Back to project page SpartanTimeLapseRecorder.

License

The source code is released under:

GNU General Public License

If you think the Android project SpartanTimeLapseRecorder 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

/*
 * Spartan Time Lapse Recorder - Minimalistic android time lapse recording app
 * Copyright (C) 2014  Andreas Rohner//from w  w  w.  ja  va  2 s .  c om
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package at.andreasrohner.spartantimelapserec;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import at.andreasrohner.spartantimelapserec.data.RecSettings;

public class PreviewActivity extends Activity implements ErrorCallback,
    AutoFocusCallback {
  private Preview mPreview;
  private Camera mCamera;
  private RecSettings mSettings;
  private boolean mUseAutoFocus;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Hide the window title.
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    mSettings = new RecSettings();
    mSettings.load(getApplicationContext(), PreferenceManager
        .getDefaultSharedPreferences(getApplicationContext()));

    // Create a RelativeLayout container that will hold a SurfaceView,
    // and set it as the content of our activity.
    mPreview = new Preview(this, mSettings);
    setContentView(mPreview);
  }

  private void releaseCamera() {
    if (mCamera == null)
      return;

    try {
      mCamera.reconnect();
      mCamera.release();
    } catch (Exception e) {
      e.printStackTrace();
    }
    mCamera = null;
  }

  private void setWhiteBalance(Camera.Parameters params, Set<String> suppModes) {
    if (suppModes.contains(Camera.Parameters.WHITE_BALANCE_AUTO)) {
      params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
    }
  }

  @SuppressLint("InlinedApi")
  private void setFocusMode(Camera.Parameters params, Set<String> suppModes) {
    if (suppModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
      params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
    } else if (suppModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
      params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
      mUseAutoFocus = true;
    }
  }

  private static void setCameraDisplayOrientation(Activity activity,
      int cameraId, Camera camera) {
    CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    int rotation = activity.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;
      break;
    }

    int result;
    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);
  }

  private void setCameraParams() throws IOException {
    Camera.Parameters params = mCamera.getParameters();

    List<String> suppList = params.getSupportedWhiteBalance();
    if (suppList != null) {
      Set<String> suppModes = new HashSet<String>();
      suppModes.addAll(suppList);

      setWhiteBalance(params, suppModes);
    }

    suppList = params.getSupportedFocusModes();
    if (suppList != null) {
      Set<String> suppModes = new HashSet<String>();
      suppModes.addAll(suppList);

      setFocusMode(params, suppModes);
    }

    mCamera.setParameters(params);

    setCameraDisplayOrientation(this, mSettings.getCameraId(), mCamera);

    mCamera.setErrorCallback(this);
  }

  private void preparePreview() throws IOException {
    releaseCamera();

    mCamera = Camera.open(mSettings.getCameraId());

    setCameraParams();

    mPreview.setCamera(mCamera);
  }

  private void startPreview() {
    try {
      if (mCamera == null)
        preparePreview();

      mCamera.startPreview();

      if (mUseAutoFocus)
        mCamera.autoFocus(this);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  @Override
  public void onResume() {
    super.onResume();

    startPreview();
  }

  @Override
  public void onPause() {
    super.onPause();

    // Because the Camera object is a shared resource, it's very
    // important to release it when the activity is paused.
    if (mCamera != null) {
      mPreview.setCamera(null);
      releaseCamera();
    }
  }

  @Override
  public void onAutoFocus(boolean arg0, Camera arg1) {
  }

  @Override
  public void onError(int error, Camera camera) {
    String msg;

    switch (error) {
    case Camera.CAMERA_ERROR_SERVER_DIED:
      msg = "Cameraserver died";
      break;
    default:
      msg = "Unkown error occured while recording";
      break;
    }

    final Context context = getApplicationContext();
    final String text = getClass().getSimpleName() + " Error: " + msg;

    mPreview.post(new Runnable() {
      @Override
      public void run() {
        Toast toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
        toast.show();
      }
    });
  }
}

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
/**
 * A simple wrapper around a Camera and a SurfaceView that renders a centered
 * preview of the Camera to the surface. We need to center the SurfaceView
 * because not all devices have cameras that support preview sizes at the same
 * aspect ratio as the device's display.
 */
class Preview extends ViewGroup implements SurfaceHolder.Callback {
  private final String TAG = "Preview";

  private SurfaceView mSurfaceView;
  private SurfaceHolder mHolder;
  private Camera mCamera;
  private RecSettings mSettings;
  private Size mPreviewSize;
  private List<Size> mSupportedPreviewSizes;

  @SuppressWarnings("deprecation")
  Preview(Context context, RecSettings settings) {
    super(context);

    mSettings = settings;

    mSurfaceView = new SurfaceView(context);
    addView(mSurfaceView);

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = mSurfaceView.getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  }

  public void setCamera(Camera camera) {
    mCamera = camera;
    if (mCamera != null) {
      mSupportedPreviewSizes = mCamera.getParameters()
          .getSupportedPreviewSizes();

      if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
            mSettings.getFrameWidth(), mSettings.getFrameHeight());
      }
      requestLayout();
    }
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    if (changed && getChildCount() > 0) {
      final View child = getChildAt(0);

      final int width = r - l;
      final int height = b - t;

      int previewWidth = width;
      int previewHeight = height;
      if (mPreviewSize != null) {
        previewWidth = mPreviewSize.width;
        previewHeight = mPreviewSize.height;
      }

      int rotation = ((Activity) getContext()).getWindowManager()
          .getDefaultDisplay().getRotation();
      switch (rotation) {
      case Surface.ROTATION_0:
      case Surface.ROTATION_180:
        if (mPreviewSize != null) {
          previewWidth = mPreviewSize.height;
          previewHeight = mPreviewSize.width;
        }
        break;
      }

      // Center the child SurfaceView within the parent.
      if (width * previewHeight > height * previewWidth) {
        final int scaledChildWidth = previewWidth * height
            / previewHeight;
        child.layout((width - scaledChildWidth) / 2, 0,
            (width + scaledChildWidth) / 2, height);
      } else {
        final int scaledChildHeight = previewHeight * width
            / previewWidth;
        child.layout(0, (height - scaledChildHeight) / 2, width,
            (height + scaledChildHeight) / 2);
      }
    }
  }

  private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null)
      return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    // Try to find an size match aspect ratio and size
    for (Size size : sizes) {
      double ratio = (double) size.width / size.height;
      if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
        continue;
      if (Math.abs(size.height - targetHeight) < minDiff) {
        optimalSize = size;
        minDiff = Math.abs(size.height - targetHeight);
      }
    }

    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
      minDiff = Double.MAX_VALUE;
      for (Size size : sizes) {
        if (Math.abs(size.height - targetHeight) < minDiff) {
          optimalSize = size;
          minDiff = Math.abs(size.height - targetHeight);
        }
      }
    }
    return optimalSize;
  }

  public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.
    try {
      if (mCamera != null) {
        mCamera.setPreviewDisplay(holder);
      }
    } catch (IOException exception) {
      Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
    }
  }

  public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
      mCamera.stopPreview();
    }
  }

  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    requestLayout();

    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

    mCamera.setParameters(parameters);

    mCamera.startPreview();
  }

}




Java Source Code List

at.andreasrohner.spartantimelapserec.BackgroundService.java
at.andreasrohner.spartantimelapserec.DeviceStatusReceiver.java
at.andreasrohner.spartantimelapserec.MainActivity.java
at.andreasrohner.spartantimelapserec.PowerSavingReceiver.java
at.andreasrohner.spartantimelapserec.PreviewActivity.java
at.andreasrohner.spartantimelapserec.ScheduleReceiver.java
at.andreasrohner.spartantimelapserec.SettingsActivity.java
at.andreasrohner.spartantimelapserec.SettingsCommon.java
at.andreasrohner.spartantimelapserec.SettingsFragment.java
at.andreasrohner.spartantimelapserec.data.RecMode.java
at.andreasrohner.spartantimelapserec.data.RecSettings.java
at.andreasrohner.spartantimelapserec.preference.DateTimePreference.java
at.andreasrohner.spartantimelapserec.preference.IconArrayAdapter.java
at.andreasrohner.spartantimelapserec.preference.IconListPreference.java
at.andreasrohner.spartantimelapserec.preference.NoKBEditTextPreference.java
at.andreasrohner.spartantimelapserec.preference.SeekBarPreference.java
at.andreasrohner.spartantimelapserec.recorder.ImageRecorder.java
at.andreasrohner.spartantimelapserec.recorder.PowerSavingImageRecorder.java
at.andreasrohner.spartantimelapserec.recorder.Recorder.java
at.andreasrohner.spartantimelapserec.recorder.VideoRecorder.java
at.andreasrohner.spartantimelapserec.recorder.VideoTimeLapseRecorder.java
at.andreasrohner.spartantimelapserec.sensor.CameraSettings.java
at.andreasrohner.spartantimelapserec.sensor.MuteShutter.java
at.andreasrohner.spartantimelapserec.sensor.OrientationSensor.java