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 preview 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 sizes Supported camera preview sizes. 44 * @param w The width of the view. 45 * @param h The height of the view. 46 * @return Best match camera preview size to fit in the view. 47 */ 48 public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { 49 // Use a very small tolerance because we want an exact match. 50 final double ASPECT_TOLERANCE = 0.1; 51 double targetRatio = (double) w / h; 52 if (sizes == null) 53 return null; 54 55 Camera.Size optimalSize = null; 56 57 // Start with max value and refine as we iterate over available preview sizes. This is the 58 // minimum difference between view and camera height. 59 double minDiff = Double.MAX_VALUE; 60 61 // Target view height 62 int targetHeight = h; 63 64 // Try to find a preview size that matches aspect ratio and the target view size. 65 // Iterate over all available sizes and pick the largest size that can fit in the view and 66 // still maintain the aspect ratio. 67 for (Camera.Size size : sizes) { 68 double ratio = (double) size.width / size.height; 69 if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) 70 continue; 71 if (Math.abs(size.height - targetHeight) < minDiff) { 72 optimalSize = size; 73 minDiff = Math.abs(size.height - targetHeight); 74 } 75 } 76 77 // Cannot find preview size that matches the aspect ratio, ignore the requirement 78 if (optimalSize == null) { 79 minDiff = Double.MAX_VALUE; 80 for (Camera.Size size : sizes) { 81 if (Math.abs(size.height - targetHeight) < minDiff) { 82 optimalSize = size; 83 minDiff = Math.abs(size.height - targetHeight); 84 } 85 } 86 } 87 return optimalSize; 88 } 89 90 /** 91 * @return the default camera on the device. Return null if there is no camera on the device. 92 */ 93 public static Camera getDefaultCameraInstance() { 94 return Camera.open(); 95 } 96 97 98 /** 99 * @return the default rear/back facing camera on the device. Returns null if camera is not 100 * available. 101 */ 102 public static Camera getDefaultBackFacingCameraInstance() { 103 return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_BACK); 104 } 105 106 /** 107 * @return the default front facing camera on the device. Returns null if camera is not 108 * available. 109 */ 110 public static Camera getDefaultFrontFacingCameraInstance() { 111 return getDefaultCamera(Camera.CameraInfo.CAMERA_FACING_FRONT); 112 } 113 114 115 /** 116 * 117 * @param position Physical position of the camera i.e Camera.CameraInfo.CAMERA_FACING_FRONT 118 * or Camera.CameraInfo.CAMERA_FACING_BACK. 119 * @return the default camera on the device. Returns null if camera is not available. 120 */ 121 @TargetApi(Build.VERSION_CODES.GINGERBREAD) 122 private static Camera getDefaultCamera(int position) { 123 // Find the total number of cameras available 124 int mNumberOfCameras = Camera.getNumberOfCameras(); 125 126 // Find the ID of the back-facing ("default") camera 127 Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 128 for (int i = 0; i < mNumberOfCameras; i++) { 129 Camera.getCameraInfo(i, cameraInfo); 130 if (cameraInfo.facing == position) { 131 return Camera.open(i); 132 133 } 134 } 135 136 return null; 137 } 138 139 /** 140 * Creates a media file in the {@code Environment.DIRECTORY_PICTURES} directory. The directory 141 * is persistent and available to other applications like gallery. 142 * 143 * @param type Media type. Can be video or image. 144 * @return A file object pointing to the newly created file. 145 */ 146 public static File getOutputMediaFile(int type){ 147 // To be safe, you should check that the SDCard is mounted 148 // using Environment.getExternalStorageState() before doing this. 149 if (!Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) { 150 return null; 151 } 152 153 File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( 154 Environment.DIRECTORY_PICTURES), "CameraSample"); 155 // This location works best if you want the created images to be shared 156 // between applications and persist after your app has been uninstalled. 157 158 // Create the storage directory if it does not exist 159 if (! mediaStorageDir.exists()){ 160 if (! mediaStorageDir.mkdirs()) { 161 Log.d("CameraSample", "failed to create directory"); 162 return null; 163 } 164 } 165 166 // Create a media file name 167 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 168 File mediaFile; 169 if (type == MEDIA_TYPE_IMAGE){ 170 mediaFile = new File(mediaStorageDir.getPath() + File.separator + 171 "IMG_"+ timeStamp + ".jpg"); 172 } else if(type == MEDIA_TYPE_VIDEO) { 173 mediaFile = new File(mediaStorageDir.getPath() + File.separator + 174 "VID_"+ timeStamp + ".mp4"); 175 } else { 176 return null; 177 } 178 179 return mediaFile; 180 } 181 182 }