Ответ 1
Это происходит потому, что вы запрашиваете нужные размеры, но не каждая камера способна к каждому измерению.
Кроме того, некоторые устройства работают с соотношением сторон камеры немного различаются, поэтому, если вы запрашиваете прямоугольник с неправильным соотношением или с размерами, отличающимися от поддерживаемых, он будет разбиваться на некоторых устройствах.
Что делать?
Шаг 1.
вам нужно проверить поддерживаемые размеры. Вы можете сделать это с помощью
Camera.Parameters p = myCamera.getParameters();
List<Size> previewsizes = p.getSupportedPreviewSizes();
List<Size> videosizes = p.getSupportedVideoSizes();
а затем вы можете выбрать один. Если вы хотите автоматизировать это, вы можете пойти дальше и следовать
Шаг 2
напишите функцию, чтобы выбрать наилучший доступный размер, который получит поддерживаемые размеры и желаемый размер, что-то вроде:
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
Log.d("Camera", "Checking size " + size.width + "w " + size.height
+ "h");
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the
// requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
И последний шаг, установите параметры
Шаг 3
private int desiredwidth=640, desiredheight=360;
Size optimalPreviewSize = getOptimalPreviewSize(previewsizes, desiredwidth, desiredheight);
Size optimalVideoSize = getOptimalPreviewSize(videosizes, desiredwidth, desiredheight);
p.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
mCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSize(optimalVideoSize.width, optimalVideoSize.height);
myCamera.setParameters(p);
При этом приложение вашей камеры будет работать на каждом устройстве с помощью камеры!
ОБНОВЛЕНИЕ
С getOptimalPreviewSize, который я написал, вы получаете размер, отношение которого ближе к желаемому, и если ни один из них не является достаточно хорошим, вы получаете ту, высота которой закрыта до желаемого. если вы хотите придавать большее значение размеру, вы можете легко изменить, что-то вроде
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
if ( you want ratio as closed to what i asked for)
{ for (Size size : sizes) {
Log.d("Camera", "Checking size " + size.width + "w " + size.height
+ "h");
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
if (you want height as closed to what i asked for) { //you can do other for width
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
if (you want the bigest one) {
minDiff = 0;
for (Size size : sizes) {
if ( size.height * size.width > minDiff ) {
optimalSize = size;
minDiff = size.height * size.width ;
}
}
}
return optimalSize;
}