183 lines
6.5 KiB
Java
183 lines
6.5 KiB
Java
/*
|
|
* Copyright (C) 2013 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.
|
|
*/
|
|
|
|
package com.example.android.common.media;
|
|
|
|
import android.annotation.TargetApi;
|
|
import android.hardware.Camera;
|
|
import android.os.Build;
|
|
import android.os.Environment;
|
|
import android.util.Log;
|
|
|
|
import java.io.File;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Camera related utilities.
|
|
*/
|
|
public class CameraHelper {
|
|
|
|
public static final int MEDIA_TYPE_IMAGE = 1;
|
|
public static final int MEDIA_TYPE_VIDEO = 2;
|
|
|
|
/**
|
|
* Iterate over supported camera preview sizes to see which one best fits the
|
|
* dimensions of the given view while maintaining the aspect ratio. If none can,
|
|
* be lenient with the aspect ratio.
|
|
*
|
|
* @param sizes Supported camera preview sizes.
|
|
* @param w The width of the view.
|
|
* @param h The height of the view.
|
|
* @return Best match camera preview size to fit in the view.
|
|
*/
|
|
public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
|
|
// Use a very small tolerance because we want an exact match.
|
|
final double ASPECT_TOLERANCE = 0.1;
|
|
double targetRatio = (double) w / h;
|
|
if (sizes == null)
|
|
return null;
|
|
|
|
Camera.Size optimalSize = null;
|
|
|
|
// Start with max value and refine as we iterate over available preview sizes. This is the
|
|
// minimum difference between view and camera height.
|
|
double minDiff = Double.MAX_VALUE;
|
|
|
|
// Target view height
|
|
int targetHeight = h;
|
|
|
|
// Try to find a preview size that matches aspect ratio and the target view size.
|
|
// Iterate over all available sizes and pick the largest size that can fit in the view and
|
|
// still maintain the aspect ratio.
|
|
for (Camera.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 preview size that matches the aspect ratio, ignore the requirement
|
|
if (optimalSize == null) {
|
|
minDiff = Double.MAX_VALUE;
|
|
for (Camera.Size size : sizes) {
|
|
if (Math.abs(size.height - targetHeight) < minDiff) {
|
|
optimalSize = size;
|
|
minDiff = Math.abs(size.height - targetHeight);
|
|
}
|
|
}
|
|
}
|
|
return optimalSize;
|
|
}
|
|
|
|
/**
|
|
* @return the default camera on the device. Return null if there is no camera on the device.
|
|
*/
|
|
public static Camera getDefaultCameraInstance() {
|
|
return Camera.open();
|
|
}
|
|
|
|
|
|
/**
|
|
* @return the default rear/back facing camera on the device. Returns null if camera is not
|
|
* available.
|
|
*/
|
|
public static Camera getDefaultBackFacingCameraInstance() {
|
|
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
|
|
}
|
|
|
|
/**
|
|
* @return the default front facing camera on the device. Returns null if camera is not
|
|
* available.
|
|
*/
|
|
public static Camera getDefaultFrontFacingCameraInstance() {
|
|
return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* @param position Physical position of the camera i.e Camera.CameraInfo.CAMERA_FACING_FRONT
|
|
* or Camera.CameraInfo.CAMERA_FACING_BACK.
|
|
* @return the default camera on the device. Returns null if camera is not available.
|
|
*/
|
|
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
|
|
private static Camera getDefaultCamera(int position) {
|
|
// Find the total number of cameras available
|
|
int mNumberOfCameras = Camera.getNumberOfCameras();
|
|
|
|
// Find the ID of the back-facing ("default") camera
|
|
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
|
|
for (int i = 0; i < mNumberOfCameras; i++) {
|
|
Camera.getCameraInfo(i, cameraInfo);
|
|
if (cameraInfo.facing == position) {
|
|
return Camera.open(i);
|
|
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Creates a media file in the {@code Environment.DIRECTORY_PICTURES} directory. The directory
|
|
* is persistent and available to other applications like gallery.
|
|
*
|
|
* @param type Media type. Can be video or image.
|
|
* @return A file object pointing to the newly created file.
|
|
*/
|
|
public static File getOutputMediaFile(int type){
|
|
// To be safe, you should check that the SDCard is mounted
|
|
// using Environment.getExternalStorageState() before doing this.
|
|
if (!Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) {
|
|
return null;
|
|
}
|
|
|
|
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
|
|
Environment.DIRECTORY_PICTURES), "CameraSample");
|
|
// This location works best if you want the created images to be shared
|
|
// between applications and persist after your app has been uninstalled.
|
|
|
|
// Create the storage directory if it does not exist
|
|
if (! mediaStorageDir.exists()){
|
|
if (! mediaStorageDir.mkdirs()) {
|
|
Log.d("CameraSample", "failed to create directory");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Create a media file name
|
|
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
|
File mediaFile;
|
|
if (type == MEDIA_TYPE_IMAGE){
|
|
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
|
"IMG_"+ timeStamp + ".jpg");
|
|
} else if(type == MEDIA_TYPE_VIDEO) {
|
|
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
|
"VID_"+ timeStamp + ".mp4");
|
|
} else {
|
|
return null;
|
|
}
|
|
|
|
return mediaFile;
|
|
}
|
|
|
|
}
|