1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.common.media; 18 19 import android.annotation.TargetApi; 20 import android.hardware.Camera; 21 import android.os.Build; 22 import android.os.Environment; 23 import android.util.Log; 24 25 import java.io.File; 26 import java.text.SimpleDateFormat; 27 import java.util.Date; 28 import java.util.List; 29 30 /** 31 * Camera related utilities. 32 */ 33 public class CameraHelper { 34 35 public static final int MEDIA_TYPE_IMAGE = 1; 36 public static final int MEDIA_TYPE_VIDEO = 2; 37 38 /** 39 * Iterate over supported camera video sizes to see which one best fits the 40 * dimensions of the given view while maintaining the aspect ratio. If none can, 41 * be lenient with the aspect ratio. 42 * 43 * @param supportedVideoSizes Supported camera video sizes. 44 * @param previewSizes Supported camera preview sizes. 45 * @param w The width of the view. 46 * @param h The height of the view. 47 * @return Best match camera video size to fit in the view. 48 */ getOptimalVideoSize(List<Camera.Size> supportedVideoSizes, List<Camera.Size> previewSizes, int w, int h)49 public static Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes, 50 List<Camera.Size> previewSizes, int w, int h) { 51 // Use a very small tolerance because we want an exact match. 52 final double ASPECT_TOLERANCE = 0.1; 53 double targetRatio = (double) w / h; 54 55 // Supported video sizes list might be null, it means that we are allowed to use the preview 56 // sizes 57 List<Camera.Size> videoSizes; 58 if (supportedVideoSizes != null) { 59 videoSizes = supportedVideoSizes; 60 } else { 61 videoSizes = previewSizes; 62 } 63 Camera.Size optimalSize = null; 64 65 // Start with max value and refine as we iterate over available video sizes. This is the 66 // minimum difference between view and camera height. 67 double minDiff = Double.MAX_VALUE; 68 69 // Target view height 70 int targetHeight = h; 71 72 // Try to find a video size that matches aspect ratio and the target view size. 73 // Iterate over all available sizes and pick the largest size that can fit in the view and 74 // still maintain the aspect ratio. 75 for (Camera.Size size : videoSizes) { 76 double ratio = (double) size.width / size.height; 77 if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) 78 continue; 79 if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) { 80 optimalSize = size; 81 minDiff = Math.abs(size.height - targetHeight); 82 } 83 } 84 85 // Cannot find video size that matches the aspect ratio, ignore the requirement 86 if (optimalSize == null) { 87 minDiff = Double.MAX_VALUE; 88 for (Camera.Size size : videoSizes) { 89 if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) { 90 optimalSize = size; 91 minDiff = Math.abs(size.height - targetHeight); 92 } 93 } 94 } 95 return optimalSize; 96 } 97 98 /** 99 * @return the default camera on the device. Return null if there is no camera on the device. 100 */ getDefaultCameraInstance()101 public static Camera getDefaultCameraInstance() { 102 return Camera.open(); 103 } 104 105 106 /** 107 * @return the default rear/back facing camera on the device. Returns null if camera is not 108 * available. 109 */ getDefaultBackFacingCameraInstance()110 public static Camera getDefaultBackFacingCameraInstance() { 111 return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_BACK); 112 } 113 114 /** 115 * @return the default front facing camera on the device. Returns null if camera is not 116 * available. 117 */ getDefaultFrontFacingCameraInstance()118 public static Camera getDefaultFrontFacingCameraInstance() { 119 return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_FRONT); 120 } 121 122 123 /** 124 * 125 * @param position Physical position of the camera i.e Camera.CameraInfo.CAMERA_FACING_FRONT 126 * or Camera.CameraInfo.CAMERA_FACING_BACK. 127 * @return the default camera on the device. Returns null if camera is not available. 128 */ 129 @TargetApi(Build.VERSION_CODES.GINGERBREAD) getDefaultCamera(int position)130 private static Camera getDefaultCamera(int position) { 131 // Find the total number of cameras available 132 int mNumberOfCameras = Camera.getNumberOfCameras(); 133 134 // Find the ID of the back-facing ("default") camera 135 Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 136 for (int i = 0; i < mNumberOfCameras; i++) { 137 Camera.getCameraInfo(i, cameraInfo); 138 if (cameraInfo.facing == position) { 139 return Camera.open(i); 140 141 } 142 } 143 144 return null; 145 } 146 147 /** 148 * Creates a media file in the {@code Environment.DIRECTORY_PICTURES} directory. The directory 149 * is persistent and available to other applications like gallery. 150 * 151 * @param type Media type. Can be video or image. 152 * @return A file object pointing to the newly created file. 153 */ getOutputMediaFile(int type)154 public static File getOutputMediaFile(int type){ 155 // To be safe, you should check that the SDCard is mounted 156 // using Environment.getExternalStorageState() before doing this. 157 if (!Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) { 158 return null; 159 } 160 161 File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( 162 Environment.DIRECTORY_PICTURES), "CameraSample"); 163 // This location works best if you want the created images to be shared 164 // between applications and persist after your app has been uninstalled. 165 166 // Create the storage directory if it does not exist 167 if (! mediaStorageDir.exists()){ 168 if (! mediaStorageDir.mkdirs()) { 169 Log.d("CameraSample", "failed to create directory"); 170 return null; 171 } 172 } 173 174 // Create a media file name 175 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 176 File mediaFile; 177 if (type == MEDIA_TYPE_IMAGE){ 178 mediaFile = new File(mediaStorageDir.getPath() + File.separator + 179 "IMG_"+ timeStamp + ".jpg"); 180 } else if(type == MEDIA_TYPE_VIDEO) { 181 mediaFile = new File(mediaStorageDir.getPath() + File.separator + 182 "VID_"+ timeStamp + ".mp4"); 183 } else { 184 return null; 185 } 186 187 return mediaFile; 188 } 189 190 } 191