I figured this out a while back, and wanted to let others know how to fix this. What caused the crash was setting the preview size larger than the screen size of the device. This is why the Samsung Galaxy S3 would crash, but not the Nexus 4. Below is the relevant code I changed:
private Camera.Size getBestPreviewSize(List<Camera.Size> previewSizes, int width, int height) {
double targetAspect = (double)width / (double)height;
ArrayList<Camera.Size> matchedPreviewSizes = new ArrayList<Camera.Size>();
final double ASPECT_TOLERANCE = 0.1;
for(Size previewSize : previewSizes) {
double previewAspect = (double)previewSize.width / (double)previewSize.height;
// Original broken code.
//if(Math.abs(targetAspect - previewAspect) < ASPECT_TOLERANCE) {
// matchedPreviewSizes.add(previewSize);
//}
// Working code.
if(Math.abs(targetAspect - previewAspect) < ASPECT_TOLERANCE &&
previewSize.width <= width && previewSize.height <= height) {
matchedPreviewSizes.add(previewSize);
}
}
Camera.Size bestPreviewSize;
if(!matchedPreviewSizes.isEmpty()) {
bestPreviewSize = Collections.max(matchedPreviewSizes, sizeComparator);
} else {
bestPreviewSize = Collections.max(previewSizes, sizeComparator);
}
return bestPreviewSize;
}
private Comparator<Camera.Size> sizeComparator = new Comparator<Camera.Size>() {
@Override
public int compare(Size lhs, Size rhs) {
long lhsArea = lhs.height*lhs.width;
long rhsArea = rhs.height*rhs.width;
if(lhsArea > rhsArea) {
return 1;
} else if(lhsArea < rhsArea) {
return -1;
} else {
return 0;
}
}
};
In the above code, I show the original broken code along with the working code that caused my function to respect the maximum screen size of the device. Doing this fixed the crashes that were occurring on various devices.
Hope that helps!