I worked with VIDEO ONLY . No photos. Noticed that setDisplayOrientation affects the right orientation of the display only during preview. But if, to play back any video shot in landscape mode or portrait mode, it is always in landscape mode .
I installed in AndroidManifest.xml
But it is used for debugging in device 4.0.1. Perhaps this is a problem. However, I noticed that the default camera application works great and shoots portrait films in portrait mode.
What am I missing? ...
** CameraRecorder.java
public class CameraRecorder extends Activity {
private CameraPreview mPreview;
private Camera mCamera;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_surface);
mCamera = getCameraInstance();
if (mCamera == null) {
Log.e(TAG, "Camera is not available");
finish();
}
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
mPreview.setOnClickListener(startStopListener);
}
private void changeOrientation(int what) {
if (what != orientation) {
setRequestedOrientation(orientation = what);
}
}
OnClickListener startStopListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (isRecording) {
mMediaRecorder.stop();
releaseMediaRecorder();
mCamera.lock();
setCaptureButtonText("Capture");
isRecording = false;
} else {
if (prepareVideoRecorder()) {
mMediaRecorder.start();
isRecording = true;
} else {
releaseMediaRecorder();
}
}
}
};
File tempFile;
@Override
protected void onPause() {
super.onPause();
releaseMediaRecorder();
releaseCamera();
}
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
Log.d(TAG, "Fail to connect to camera service. Is it locked?");
}
}
return c;
}
private boolean prepareVideoRecorder() {
if (mCamera == null)
mCamera = getCameraInstance();
if (mMediaRecorder == null)
mMediaRecorder = new MediaRecorder();
Camera.Parameters p = mCamera.getParameters();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
CamcorderProfile profile = mPreview.getProfile();
Size previewSize = mPreview.getPreviewSize();
if (previewSize != null) {
profile.videoFrameWidth = previewSize.width;
profile.videoFrameHeight = previewSize.height;
}
mMediaRecorder.setProfile(profile);
mMediaRecorder.setOutputFile(MediaFile.getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
mCamera.lock();
}
}
private void releaseCamera() {
if (mPreview != null) {
mPreview.surfaceDestroyed(null);
}
if (mCamera != null) {
mCamera.release();
mCamera = null;
Log.d(TAG, "Camera released");
}
}
}
CameraPreview.java
public class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private SurfaceView mSurfaceView;
private Context mContext;
private final String TAG = "CameraPreview";
public CameraPreview(Context context, Camera camera) {
super(context);
mContext = context;
mCamera = camera;
setCamera(mCamera);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView, 0);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.setKeepScreenOn(true);
}
public SurfaceHolder getHolder() {
return mSurfaceView.getHolder();
}
private Size mPreviewSize;
private List<Size> mSupportedPreviewSizes;
private List<String> mSupportedFlashModes;
public Camera getCamera() {
return mCamera;
}
private CamcorderProfile mProfile;
public CamcorderProfile getProfile() {
return mProfile;
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
if (mSupportedFlashModes != null && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
mCamera.setParameters(parameters);
}
}
requestLayout();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
}
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, mProfile.videoFrameWidth, mProfile.videoFrameHeight);
}
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (changed) {
final View cameraView = getChildAt(0);
final int width = right - left;
final int height = bottom - top;
Camera.Parameters p = mCamera.getParameters();
@SuppressWarnings("unused")
int previewWidth = width;
@SuppressWarnings("unused")
int previewHeight = height;
if (mPreviewSize != null) {
Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation()) {
case Surface.ROTATION_0:
mCamera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
case Surface.ROTATION_180:
break;
case Surface.ROTATION_270:
mCamera.setDisplayOrientation(180);
break;
}
}
cameraView.layout(0, 0, width, height);
}
}
public void setSupportedPreviewSizes(List<Size> supportedPreviewSizes) {
mSupportedPreviewSizes = supportedPreviewSizes;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera = null;
Log.d(TAG, "Preview destroyed");
}
} catch (Exception e) {
Log.e(TAG, "Camera release failure.");
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
}
Camera.Parameters parameters = mCamera.getParameters();
Size previewSize = getPreviewSize();
if (previewSize != null)
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setParameters(parameters);
try {
previewCamera();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
public Size getPreviewSize() {
return mPreviewSize;
}
public static Size getOptimalPreviewSize(List<Size> sizes, int width, int height) {
double aspectTolerance = 0.05;
double targetRatio = (double) width / height;
if (sizes == null) {
return null;
}
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = height;
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > aspectTolerance)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
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;
}
public void previewCamera() {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Cannot start preview.", e);
}
}
}
Manifest.xml
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:name=".client.andi"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".activity.CameraRecorder"
android:label="@string/title_activity_main"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
** layout.xml **
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/RelativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</FrameLayout>
</RelativeLayout>