developers/build: fb039d88ed8e9183cae9ce510bf9c907d23ecc50
developers/samples/android: 7c3c09dcf092593adb8c13f8e15260f4da0a799a
Note: This was previously committed on May 18 2016, but wasn't
automerged. Replaying commit to bring browseable back into sync
downstream.
(cherry picked from commit 8e7e496ae9)
Bug: 29127946
Change-Id: I6275f830532c3c6ce006756aecc3c2ae7e06873d
191 lines
6.9 KiB
Java
191 lines
6.9 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 video 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 supportedVideoSizes Supported camera video sizes.
|
|
* @param previewSizes Supported camera preview sizes.
|
|
* @param w The width of the view.
|
|
* @param h The height of the view.
|
|
* @return Best match camera video size to fit in the view.
|
|
*/
|
|
public static Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
|
|
List<Camera.Size> previewSizes, 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;
|
|
|
|
// Supported video sizes list might be null, it means that we are allowed to use the preview
|
|
// sizes
|
|
List<Camera.Size> videoSizes;
|
|
if (supportedVideoSizes != null) {
|
|
videoSizes = supportedVideoSizes;
|
|
} else {
|
|
videoSizes = previewSizes;
|
|
}
|
|
Camera.Size optimalSize = null;
|
|
|
|
// Start with max value and refine as we iterate over available video 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 video 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 : videoSizes) {
|
|
double ratio = (double) size.width / size.height;
|
|
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
|
|
continue;
|
|
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
|
|
optimalSize = size;
|
|
minDiff = Math.abs(size.height - targetHeight);
|
|
}
|
|
}
|
|
|
|
// Cannot find video size that matches the aspect ratio, ignore the requirement
|
|
if (optimalSize == null) {
|
|
minDiff = Double.MAX_VALUE;
|
|
for (Camera.Size size : videoSizes) {
|
|
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
|
|
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;
|
|
}
|
|
|
|
}
|