| /* | |
| * 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; | |
| } | |
| } |