Camera is being used after Camera.release() was called after screen rotation - android

I have an app that takes pictures on a timer. Normally it works fine, except when the screen is rotated while the camera is sleeping. Can anybody tell me why it fails to take a picture after rotating in sleep?
Normally, when the camera goes to sleep and wakes up it executes...
#Override
protected void onPause() {
super.onPause();
camera.stopPreview();
camera.release();
//camera = null; //this give me a null object message
}
#Override
protected void onResume() {
super.onResume();
camera = Camera.open(cameraId);
setCameraDisplayOrientation();
startCameraPreview(surfaceHolder, surfaceView.getWidth(), surfaceView.getHeight());
}
However, when it wakes up after the camera has been rotated in sleep, it first executes onResume(), surfaceChanged(), onPause(), onStop(empty), onDestroy(empty), then the following:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView) findViewById(R.id.surface);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onResume() {
super.onResume();
camera = Camera.open(cameraId);
setCameraDisplayOrientation();
startCameraPreview(surfaceHolder, surfaceView.getWidth(), surfaceView.getHeight());
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
camera.stopPreview();
setCameraDisplayOrientation();
startCameraPreview(holder, w, h);
}
public void setCameraDisplayOrientation() {
deviceRotation = getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch(deviceRotation) {
case Surface.ROTATION_0: degrees=0; break;//vertical
case Surface.ROTATION_90: degrees=-90; break; //left side
case Surface.ROTATION_180: degrees=180; break; //upside-down
case Surface.ROTATION_270: degrees=90; break; //right side
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
displayRotation = info.orientation + degrees;
camera.setDisplayOrientation(displayRotation); //changes orientation of camera's display
}
public void startCameraPreview(SurfaceHolder holder, int w, int h) {
double targetRatio = 0;
switch(deviceRotation) {
case Surface.ROTATION_0: targetRatio = (double)w/(double)h; break; //vertical
case Surface.ROTATION_90: targetRatio = (double)h/(double)w; break; //left side
case Surface.ROTATION_180: targetRatio = (double)w/(double)h; break; //upside-down
case Surface.ROTATION_270: targetRatio = (double)h/(double)w; break; //right side
}
Camera.Parameters p = camera.getParameters();
List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
int optimal_h = 2; //always refers to short length in PreviewSizes
int optimal_w = 1; //always refers to long length in PreviewSizes
for(Camera.Size previewSize : previewSizes) {
if (Math.abs((double)previewSize.height/(double)previewSize.width - targetRatio) <
Math.abs((double)optimal_h/(double)optimal_w - targetRatio)) {
optimal_h = previewSize.height;
optimal_w = previewSize.width;
}
}
p.setPreviewSize(optimal_w, optimal_h); //defines ratio of image preview - sizes can be larger than actual display
p.set("rotation", displayRotation); //required to orient final jpeg file correctly
camera.setParameters(p);
ViewGroup.LayoutParams surfaceParams = surfaceView.getLayoutParams();
switch(deviceRotation) { //aligns ratio of surface view to ratio of image preview
case Surface.ROTATION_0:
surfaceParams.width=ViewGroup.LayoutParams.MATCH_PARENT;
surfaceParams.height=(int)(w*(double)optimal_w/(double)optimal_h);
break; //vertical
case Surface.ROTATION_90:
surfaceParams.width=(int)(h*(double)optimal_w/(double)optimal_h);
surfaceParams.height=ViewGroup.LayoutParams.MATCH_PARENT;
break; //left side
case Surface.ROTATION_180:
surfaceParams.width=ViewGroup.LayoutParams.MATCH_PARENT;
surfaceParams.height=(int)(w*(double)optimal_w/(double)optimal_h);
break; //upside-down
case Surface.ROTATION_270:
surfaceParams.width=(int)(h*(double)optimal_w/(double)optimal_h);
surfaceParams.height=ViewGroup.LayoutParams.MATCH_PARENT;
break; //right side
}
surfaceView.setLayoutParams(surfaceParams);
camera.setPreviewDisplay(holder); //required to startPreview
camera.startPreview();
}
This is not the complete code. This code does produce a few minor image formatting errors, but it still demonstrates the issue. I have stripped some things out for simplicity. The main issue is that when it tries to take a picture after been rotated in sleep it returns an error "Camera is being used after Camera.release() was called". Why is this?

This is really overdue but as I managed to solve a similar problem of mine a minute ago, I thought I'd contribute for the benefit of yourself and anyone else who might be desperately searching Stack.
So when you rotate the device, you are calling onPause and onDestroy, where you are releasing your camera. I noticed you do have camera.open() in your onResume, without a look at your surface-related code I cannot comment. Heres what worked for me.
Firstly, the cameraPreview
`
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
try {
this.mCamera.setPreviewDisplay(surfaceHolder);
this.mCamera.startPreview();
} catch (Exception e) {
}
}
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
//TODO we need this here too because on SurfaceCreated we always need to open the camera, in case its released
this.mCamera.setPreviewDisplay(surfaceHolder);
this.mCamera.setDisplayOrientation(90);
//this.mCamera.startPreview();
} catch (IOException e) {
}
}
Next, the CameraActivity's Lifecycle code
#Override
public void onResume() {
super.onResume();
try{
mCamera = openFrontFacingCameraGingerbread();
// Add to Framelayout
this.mCameraPreview = new CameraPreview(this, this.mCamera);
mImage.removeAllViews();
this.mImage.addView(this.mCameraPreview);
}catch (RuntimeException ex){
}
}
#Override
public void onPause() {
super.onPause();
captureButton.setText("Begin Capture");
if(CameraActivity.this.timer !=null) {
CameraActivity.this.timer.cancel();
CameraActivity.this.timer.purge();
CameraActivity.this.timer = null;
}
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCameraPreview.getHolder().removeCallback(mCameraPreview);
mCamera.release();
mCamera = null;
}
}
#Override
protected void onDestroy(){
super.onDestroy();
releaseCameraAndPreview();
}
private void releaseCameraAndPreview() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if(mCameraPreview != null){
mCameraPreview.destroyDrawingCache();
mCameraPreview.mCamera = null;
}
}

Related

FFMPEG Video Recording in Android getting overlay of Green latches

I have used, FFMPEG & OpenCV for integrating the Video Player into Android Application.
Build Gradle:-
compile('org.bytedeco:javacv-platform:1.4') {
exclude group: 'org.bytedeco.javacpp-presets'
}
compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.4.0-1.4'
compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.4.1-1.4'
compile files('libs/ffmpeg-android-arm.jar')
compile files('libs/ffmpeg-android-x86.jar')
compile files('libs/opencv-android-arm.jar')
compile files('libs/opencv-android-x86.jar')
I have included 'jniLibs' in the 'main' folder with 'armeabi,amreabi-v7a, x86' folder's.
I am able to open Camera and record the video.
The O/P of the video is not coming as expected, audio quality is fine. Please see the Image below.
The code I used for integration: https://github.com/CrazyOrr/FFmpegRecorder
Thanks in advance!!
I got the workaround using the SurfaceView. Check my Working code.
public class SurfaceViewVideo extends Activity implements MediaPlayer.OnPreparedListener{
private Camera myCamera;
private MyCameraSurfaceView myCameraSurfaceView;
private MediaRecorder mediaRecorder;
private int currentCameraId=1;
ImageView myButton,switchCamera;
SurfaceHolder surfaceHolder;
boolean recording;
boolean isVideoStopped;
private MediaPlayer mediaPlayer;
private SurfaceView playSurfaceView;
private SurfaceHolder playSurfaceHolder;
private FrameLayout videoView;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recording = false;
isVideoStopped = false;
setContentView(R.layout.activity_surface_view_video);
switchCamera = (ImageView)findViewById(R.id.switchCamera);
playSurfaceView = (SurfaceView)findViewById(R.id.playSurface);
playSurfaceHolder = playSurfaceView.getHolder();
videoView = (FrameLayout)findViewById(R.id.videoview);
//Get Camera for preview
myCamera = getCameraInstance();
if(myCamera == null){
Toast.makeText(this,
"Fail to get Camera",
Toast.LENGTH_LONG).show();
}
myCameraSurfaceView = new MyCameraSurfaceView(this, myCamera);
FrameLayout myCameraPreview = (FrameLayout)findViewById(R.id.videoview);
myCameraPreview.addView(myCameraSurfaceView);
myButton = (ImageView)findViewById(R.id.mybutton);
myButton.setOnClickListener(myButtonOnClickListener);
switchCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onCameraChange();
}
});
}
Button.OnClickListener myButtonOnClickListener
= new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!isVideoStopped) {
if (recording) {
// stop recording and release camera
mediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
myButton.setImageResource(R.drawable.ic_play);
isVideoStopped = true;
videoView.setVisibility(View.GONE);
myCameraSurfaceView.setVisibility(View.GONE);
playSurfaceView.setVisibility(View.VISIBLE);
} else {
//Release Camera before MediaRecorder start
releaseCamera();
if (!prepareMediaRecorder()) {
Toast.makeText(SurfaceViewVideo.this,
"Fail in prepareMediaRecorder()!\n - Ended -",
Toast.LENGTH_LONG).show();
}
mediaRecorder.start();
recording = true;
myButton.setImageResource(R.drawable.ic_stop_white_24px);
}
}else{
if(mediaPlayer==null) {
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDisplay(playSurfaceHolder);
mediaPlayer.setDataSource("/sdcard/myvideo.mp4");
mediaPlayer.prepare();
mediaPlayer.setOnPreparedListener(SurfaceViewVideo.this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
} catch (Exception e) {
e.printStackTrace();
}
}else{
mediaPlayer.start();
}
}
}};
private Camera getCameraInstance(){
// TODO Auto-generated method stub
Camera c = null;
try {
c = Camera.open(1); // attempt to get a Camera instance
c.setDisplayOrientation(90);
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
public void onCameraChange() {
myCamera.stopPreview();
myCamera.release();
if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
else {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
myCamera = Camera.open(currentCameraId);
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break; //Natural orientation
case Surface.ROTATION_90: degrees = 90; break; //Landscape left
case Surface.ROTATION_180: degrees = 180; break;//Upside down
case Surface.ROTATION_270: degrees = 270; break;//Landscape right
}
int rotate = (info.orientation - degrees + 360) % 360;
//STEP #2: Set the 'rotation' parameter
Camera.Parameters params = myCamera.getParameters();
params.setRotation(rotate);
try {
myCamera.setPreviewDisplay(myCameraSurfaceView.getHolder());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myCamera.setParameters(params);
myCamera.setDisplayOrientation(90);
myCamera.startPreview();
}
private boolean prepareMediaRecorder(){
myCamera = getCameraInstance();
mediaRecorder = new MediaRecorder();
myCamera.unlock();
mediaRecorder.setCamera(myCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P));
mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder().getSurface());
mediaRecorder.setOrientationHint(270);
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
return false;
} catch (IOException e) {
releaseMediaRecorder();
return false;
}
return true;
}
#Override
protected void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
releaseMediaPlayer();
}
private void releaseMediaRecorder(){
if (mediaRecorder != null) {
mediaRecorder.reset(); // clear recorder configuration
mediaRecorder.release(); // release the recorder object
mediaRecorder = null;
myCamera.lock(); // lock camera for later use
}
}
private void releaseCamera(){
if (myCamera != null){
myCamera.release(); // release the camera for other applications
myCamera = null;
}
}
public void releaseMediaPlayer(){
if(mediaPlayer!=null){
mediaPlayer.release();
mediaPlayer = null;
}
}
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
public MyCameraSurfaceView(Context context, Camera camera) {
super(context);
mCamera = camera;
// supported preview sizes
mSupportedPreviewSizes = myCamera.getParameters().getSupportedPreviewSizes();
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int weight,
int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
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 (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}

Android Camera won't take picture when screen off

I have a simple app that has an activity being called periodically by an alarm manager to display a preview frame and take a picture when the preview frame is built.After taking the picture, it is saved using a AsyncTask and the activity destroyed using finish().
The code works perfectly fine when I have the screen turned on.However it fails to take a picture with the screen off.I want to monitor a house and take pictures periodically using the app and in that case keeping the screen always on or turning it on manually is not a viable option.
Also the code for the camera activity has been copied from Commonsware library and works perfectly great.I am only having a problem with taking a picture with screen off.I can also see from the logs that the camera is opened by the activity.However the Runnable that is supposed to take picture when the preview frame is built, doesn't run and the camera goes to the pause state instead and stays there.
I have the necessary permissions set up perfectly as I am able to get the images with screen turned on.Maybe I am having trouble understanding the activity lifecylce when the screen is off and someone can shed light there.
I tried using the wakelocks to turn the screen on but that didnt do any good.
Below is the code for the Activity.
Also I am sorry but removing the comment for the license to make it short here.
package com.thopedia.snapper; /***
Copyright (c) 2008-2012 CommonsWare, LLC
*/
import all;
public class CameraActivity1 extends Activity {
private PreviewFrameLayout frame=null;
private SurfaceView preview=null;
private SurfaceHolder previewHolder=null;
private Camera camera=null;
private boolean inPreview=false;
private boolean cameraConfigured=false;
private PowerManager.WakeLock wakeLock;
private PowerManager powerManager;
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
/* powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass()
.getName());*/
Log.v(GlobalVariables.TAG,"CameraActivity On create called");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
frame=(PreviewFrameLayout)findViewById(R.id.frame);
preview=(SurfaceView)findViewById(R.id.preview);
previewHolder=preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
public void onResume() {
// wakeLock.acquire();
Log.v(GlobalVariables.TAG,"camera activity onResume called");
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
Camera.CameraInfo info=new Camera.CameraInfo();
for (int i=0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
try{
camera=Camera.open(i);
}catch (Exception e){
Log.v(GlobalVariables.TAG,"Camera Opening Exception");
if(!isFinishing()) {
finish();
}}}}}
if (camera == null) {
try{
camera=Camera.open();
}catch (Exception e){
if(!isFinishing()) {
finish();
}
Log.v(GlobalVariables.TAG,"Camera opening exception");
}
}
startPreview();
preview.post(new Runnable() {
#Override
public void run() {
if (inPreview) {
camera.takePicture(null, null, photoCallback);
inPreview=false;
}
}
});
}
#Override
public void onPause() {
super.onPause();
Log.v(GlobalVariables.TAG,"Camera activity onPause called");
if (inPreview) {
if(camera!=null) {
camera.stopPreview();
}
}
if(camera!=null) {
camera.release();
camera = null;
}
inPreview=false;
}
#Override
protected void onDestroy() {
Log.v(GlobalVariables.TAG,"Camera activity onDestroy called!");
super.onDestroy();
if(camera!=null){
camera.release();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.options, menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.camera) {
if (inPreview) {
camera.takePicture(null, null, photoCallback);
inPreview=false;
}
}
return(super.onOptionsItemSelected(item));
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters) {
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width <= width && size.height <= height) {
if (result == null) {
result=size;
}
else {
int resultArea=result.width * result.height;
int newArea=size.width * size.height;
if (newArea > resultArea) {
result=size;
}
}
}
}
return(result);
}
private Camera.Size getSmallestPictureSize(Camera.Parameters parameters) {
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPictureSizes()) {
if (result == null) {
result=size;
}
else {
int resultArea=result.width * result.height;
int newArea=size.width * size.height;
if (newArea < resultArea) {
result=size;
}
}
}
return(result);
}
private void initPreview(int width, int height) {
if (camera != null && previewHolder.getSurface() != null) {
try {
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(CameraActivity1.this, t.getMessage(),
Toast.LENGTH_LONG).show();
}
if (!cameraConfigured) {
Camera.Parameters parameters=camera.getParameters();
Camera.Size size=getBestPreviewSize(width, height, parameters);
Camera.Size pictureSize=getSmallestPictureSize(parameters);
if (size != null && pictureSize != null) {
parameters.setPreviewSize(size.width, size.height);
parameters.setPictureSize(pictureSize.width,
pictureSize.height);
parameters.setPictureFormat(ImageFormat.JPEG);
frame.setAspectRatio((double)size.width / size.height);
camera.setParameters(parameters);
cameraConfigured=true;
}
}
}
}
private void startPreview() {
if (cameraConfigured && camera != null) {
camera.startPreview();
inPreview=true;
}
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// no-op
}
};
Camera.PictureCallback photoCallback=new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
new SavePhotoTask().execute(data);
camera.startPreview();
inPreview=true;
if(!isFinishing()) {
finish();
}
}
};
I use the following piece of code to click a picture after the preview surface is properly created in onResume().
preview.post(new Runnable() {
#Override
public void run() {
if (inPreview) {
camera.takePicture(null, null, photoCallback);
inPreview=false;
}
}
});
Any help is appreciated.Thanks
I think you can use WakeLock to make sure that Screen-Off does not occur. Below is the sample code/algorithm by which you can turn on screen whenever it goes off. Hope This Helps!
Register a broadcast receiver on Intent.ACTION_SCREEN_OFF.
Whenever you get screen off broadcast intent, wake-up by using below code.
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
wakeLock.acquire();
android:keepScreenOn="true"
you can use above line to your parent layout in XML which you are calling through activity
it will keep your screen on always so you will not get any issue hope it will match your requirement
I figured out what the problem was after making extensive use of the LogCat :).
It seems that when the screen is kept on, the onPause() is not called instantly which is the case with the SCREEN_OFF.When the screen is ON, the Runnable is executed before the onPause() method executed and as such the pictures are taken perfectly fine.However in case when the screen is OFF, the Runnable is being executed after the Activity has completed the onPause() method.By this time we have already released the camera in onPause() and so we don't get a picture.
It started working after I figured out the flow and moved the camera release to the onDestroy() which might not be ideal for all situations but works just fine for mine because the only purpose of my Activity is to take a picture and then destroy itself.
Also the WAKELOCKS didn;t change the behaviour of the code.I would expect the Activity to not execute without the WAKE_LOCK but its working perfectly fine.
Hope this helps someone stuck in a similar situation.

how do i set android camera view port always landscape?

I have to solve a problem with android hardware camera. I want my device always record landscape video even when its orientation is vertical. I'd drawn some pics to support my issue:
This is what I get: http://joxi.ru/9IHbU_3JTJDrRyVH-XA
This is what I want: http://joxi.ru/IYLbU4wyTJC1LhQcd4Q
I can't say is it even possible (I think it's not, because of hardware matrix can't rotate). But my client thinks it is. Please, judge us.
Update: there's my code.
//..import...
public class MainActivity extends Activity {
SurfaceView surfaceView;
Camera camera;
MediaRecorder mediaRecorder;
//...public and private variables...
#Override
protected void onCreate(Bundle savedInstanceState) {
//......
SurfaceHolder holder = surfaceView.getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
setCameraDisplayOrientation(CAM_ID);
camera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
}
#Override
protected void onResume() {
super.onResume();
camera = Camera.open(this.CAM_ID);
}
#Override
protected void onPause() {
super.onPause();
releaseMediaRecorder();
if (camera != null)
camera.release();
camera = null;
}
public void setListeners() {/*....*/}
public void onClickStartRecord(View view) {
if (prepareVideoRecorder()) {
mediaRecorder.start();
} else releaseMediaRecorder();
}
public void onClickStopRecord(View view) {
if (mediaRecorder != null) {
mediaRecorder.stop();
releaseMediaRecorder();
}
}
private boolean prepareVideoRecorder() {
camera.unlock();
mediaRecorder = new MediaRecorder();
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile profile = CamcorderProfile.get(this.CAM_ID, CamcorderProfile.QUALITY_LOW);
mediaRecorder.setProfile(profile);
if(this.orientation == 270 || this.orientation == 90 )
mediaRecorder.setOrientationHint(90);
mediaRecorder.setOutputFile(videoFile.getAbsolutePath());
mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface());
try {
mediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
releaseMediaRecorder();
return false;
}
return true;
}
private void releaseMediaRecorder() {
if (mediaRecorder != null) {
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
camera.lock();
}
}
private void setCameraDisplayOrientation(int cameraId) {
// определяем насколько повернут экран от нормального положения
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result = 0;
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(cameraId, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
result = ((360 - degrees) + info.orientation);
} else
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
result = ((360 - degrees) - info.orientation);
result += 360;
}
result = result % 360;
camera.setDisplayOrientation(result);
this.orientation = result;
}
}
I believe it is pretty easy to achieve what your customer wants. So, you hold the device in Portrait mode, and you record video at resolution 1280x720. Obviously, it is portrait oriented: 720 is width, and 1280 is height (note that probably the encoded frames are still 1280 width and 720 height, but the video has a special rotation flag so that a compliant decoder will show the output at correct orientation).
Now, crop the video so that the result is 406x720 (yes, you loose a lot of pixels this way). But the result will have the desired landscape orientation. 406 is height, 720 is width.
Now to technical details: you can crop either live or after recording. In the latter case, you can run ffmpeg either on a server or on the device.
In the former case, you must receive the camera callbacks, crop the arriving data, and pass it to encoder. You can do it completely in Java, using the modern MediaCodec API. If you choose to write some native code, you can use ffmpeg libraries to perform the necessary operations.
You can even resize the resulting frames, such that video decoders will play the 406x720 originals at 1280x720 resolution. The quality will never be as the original (portrait) video.
Why I am speaking about the weird 406 height? To keep the standard aspect ratio. You may choose 540x720 if you can use 4:3 aspect ratio.

Two SurfaceView with Thread - Camera Preview Cannot Resume

I am creating an app that shows a moving picture on top of camera preview. And the way I am doing it is adding two SurfaceView, one holding camera preview and one holding my moving picture, in a framelayout inside my main activity. So basically there are three public classes, and one inner thread class inside the moving picture class to control the animation.
It worked fine upon starting the app - camera is previewing and picture is moving. But then if I pause the activity, by going to home screen or by redirecting into another activity with clicking the picture, and resume, the camera preview would black out. The wierd part is if I rotate the phone into a different mode (landscape/portrait), thing comes back to normal.
I've read several post about camera not resuming, but the solutions were all about opening camera. I'm pretty much sure my problem is not about the camera instance after examining. And actually if I pause activity by going to home screen, when I resume the camera would appear for a second and then black out.
I've been trying all kinds of things including removing all views from my layout in OnPause() and specifying index number when adding the views. But the only method that kind of got a little progress was when I comment out the canvas lock in the following block. Without the lock, the picture would move randomly, but camera could resume and all. In fact, if I leave out all things about thread and just display a static picture, camera works fine too. So I am sensing something is wrong with my thread here but I couldn't figure out.
Here's the thread's run method:
public void run() {
Canvas canvas;
while (isRunning) { //When setRunning(false) occurs, isRunning is
canvas = null; //set to false and loop ends, stopping thread
try {
canvas = surfaceHolder.lockCanvas(null); //Lock
synchronized (surfaceHolder) {
//Insert methods to modify positions of items in onDraw()
animation();
postInvalidate();
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas); //Unlock
}
}
}
}
Here's the part starting the thread:
public void surfaceCreated(SurfaceHolder arg0) {
setWillNotDraw(false); //Allows us to use invalidate() to call onDraw()
thread = new BubbleThread(getHolder(), this); //Start the thread that
thread.setRunning(true); //will make calls to
thread.start(); //onDraw()
}
Here's the part finishing the thread:
public void surfaceDestroyed(SurfaceHolder arg0) {
try {
thread.setRunning(false); //Tells thread to stop
thread.join(); //Removes thread from mem.
} catch (InterruptedException e) {}
}
[UPDATE] main activity code:
public class MainActivity extends Activity {
... // Declarations
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Adjust app settings */
...
//Load();
}
public void Load(){
/* Try to get the camera */
Camera c = getCameraInstance();
/* If the camera was received, create the app */
if (c != null){
// Create the parent layout to layer the
// camera preview and bubble layer
parentLayout = new FrameLayout(this);
parentLayout.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
// Create a new camera view and add it to the layout
cameraPreview = new CameraPreview(this, c);
parentLayout.addView(cameraPreview, 0);
// Create a new draw view and add it to the layout
bubbleLayer = new BubbleLayer(this);
parentLayout.addView(bubbleLayer, 1);
// Set the layout as the apps content view
setContentView(parentLayout);
}
/* If the camera was not received, close the app */
else {
Toast toast = Toast.makeText(getApplicationContext(),
"Unable to find camera. Closing.", Toast.LENGTH_SHORT);
toast.show();
finish();
}
}
/** A safe way to get an instance of the Camera object. */
/** This method is strait from the Android API */
public static Camera getCameraInstance(){
Camera c = null;
try {
// Attempt to get a Camera instance
c = Camera.open();
}
catch (Exception e){
// Camera is not available (in use or does not exist)
e.printStackTrace();
}
return c;
}
/* Override the onPause method so that we
* can release the camera when the app is closing.
*/
#Override
protected void onPause() {
super.onPause();
if (cameraPreview != null){
cameraPreview.onPause();
cameraPreview = null;
}
}
/* We call Load in our Resume method, because
* the app will close if we call it in onCreate
*/
#Override
protected void onResume(){
super.onResume();
Load();
}
}
[/UPDATE]
[UPDATE2] camera preview code:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
... // Declarations
public CameraPreview(Context context, Camera camera) {
super(context);
this.context = context;
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
Camera.Parameters parameters = mCamera.getParameters();
Size bestSize = getBestSize(parameters.getSupportedPreviewSizes(),
width,height);
parameters.setPreviewSize(bestSize.width, bestSize.height);
mCamera.setParameters(parameters);
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
setCameraDisplayOrientation();
mCamera.startPreview();
} catch (Exception e){
Log.d("CameraView", "Error starting camera preview: "
+ e.getMessage());
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the
// camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("CameraView", "Error setting camera preview: "
+ e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
/* Find the best size for camera */
private Size getBestSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size bestSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
bestSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (bestSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
bestSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return bestSize;
}
private void setCameraDisplayOrientation() {
if (mCamera == null) return;
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(0, info);
WindowManager winManager = (WindowManager)
context.getSystemService(Context.WINDOW_SERVICE);
int rotation = winManager.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
}
else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(result);
}
public void onPause() {
if (mCamera == null) return;
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
[/UPDATE2]
Another thing I found out was that when I paused the activity, the unlock was seldom executed. Though when it was executed camera still didn't come back, but this behavior seemed wierd to me because the thread.join() was executed so I assume the finally block should have been executed as well.
Sorry I couldn't desribe my question with less words, but please leave any clue you have. Thanks in advance!
I still don't know exactly what was wrong with my program. But after researching, I found it seemed to be something tricky with SurfaceView's z order not following normal rules. So instead of using two SurfaceViews, one for camera and one for drawing, I switched to using one SurfaceView for both and it works fine now.
But according to my experiments, with either implementation, drawing on screen with camera preview on is anyways a slow implementation because of all the switching between threads. So one should probably try to avoid doing so in the design...

Android API8 setDisplayOrientation does not affect at all

I worked with VIDEO ONLY. No pictures.
Noticed, that setDisplayOrientation does affect right display orientation only during preview.
But if to play any video captured either in landscape mode or portrait mode it is always in landscape mode.
I set in AndroidManifest.xml
But used to debug in 4.0.1 device. Maybe that is a problem.
However i noticed that default camera app works fine and capture portrait movies in portrait mode.
What do I miss?...
**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);
// Create an instance of Camera
mCamera = getCameraInstance();
if (mCamera == null) {
Log.e(TAG, "Camera is not available");
finish();
}
// Create our Preview view and set it as the content of our activity.
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) {
// TODO Auto-generated method stub
if (isRecording) {
mMediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mCamera.lock(); // take camera access back from MediaRecorder
// inform the user that recording has stopped
setCaptureButtonText("Capture");
isRecording = false;
} else {
// initialize video camera
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is
// prepared, now you can start recording
mMediaRecorder.start();
// inform the user that recording has started
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
}
}
}
};
File tempFile;
#Override
protected void onPause() {
super.onPause();
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
} catch (Exception e) {
// Camera is not available (in use or does not exist)
Log.d(TAG, "Fail to connect to camera service. Is it locked?");
}
}
return c; // returns null if camera is unavailable
}
private boolean prepareVideoRecorder() {
if (mCamera == null)
mCamera = getCameraInstance();
if (mMediaRecorder == null)
mMediaRecorder = new MediaRecorder();
Camera.Parameters p = mCamera.getParameters();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
CamcorderProfile profile = mPreview.getProfile();// CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
Size previewSize = mPreview.getPreviewSize();
if (previewSize != null) {
profile.videoFrameWidth = previewSize.width;
profile.videoFrameHeight = previewSize.height;
}
mMediaRecorder.setProfile(profile);
// Step 4: Set output file
mMediaRecorder.setOutputFile(MediaFile.getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
// Step 6: Prepare configured MediaRecorder
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(); // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
mCamera.lock(); // lock camera for later use
}
}
private void releaseCamera() {
if (mPreview != null) {
mPreview.surfaceDestroyed(null);
}
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
Log.d(TAG, "Camera released");
}
}
}
CameraPreview.java
/** A basic Camera preview class */
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);
// Set the camera to Auto Flash mode.
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) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
// mCamera.startPreview();
}
} 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) {
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
// mCamera.release();
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 your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
Camera.Parameters parameters = mCamera.getParameters();
Size previewSize = getPreviewSize();
if (previewSize != null)
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setParameters(parameters);
// start preview with new settings
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;
// Try to find an size match aspect ratio and size
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);
}
}
// 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;
}
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>
You should change android:screenOrientation="landscape" into android:screenOrientation="portrait"
Not sure if you encounter exactly the same problem with mine.
I've stuck with this problem before, too. I found that you can use the function setOrientationHint (API 9). Call this function before you call MediaRecorder.prepare(). You can setup the orientation degree for your output video.
Hope it helps, good luck!

Categories

Resources