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
}