I can display a preview of the camera video properly with a TextureView:
package com.example.camerasurfacetexture;
import java.io.IOException;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.FrameLayout;
public class MainActivity extends Activity implements SurfaceTextureListener
{
private Camera mCamera = null;
private TextureView mTextureView = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height)
{
Log.i("onSurfaceTextureAvailable", "onSurfaceTextureAvailable");
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try
{
mCamera.setPreviewTexture(surface);
}
catch (IOException t)
{
}
mCamera.startPreview();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height)
{
// Ignored, the Camera does all the work for us
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
Log.i("onSurfaceTextureDestroyed", "onSurfaceTextureDestroyed");
mCamera.stopPreview();
mCamera.release();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
// Update your view here!
}
}
and with a SurfaceView:
package com.example.cameratest;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class MainActivity extends Activity
{
private SurfaceView preview = null;
private SurfaceHolder previewHolder = null;
private Camera camera = null;
private boolean inPreview = false;
private boolean cameraConfigured = false;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preview = (SurfaceView) findViewById(R.id.cpPreview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume()
{
super.onResume();
camera = Camera.open();
startPreview();
}
#Override
public void onPause()
{
if (inPreview)
{
camera.stopPreview();
}
camera.release();
camera = null;
inPreview = false;
super.onPause();
}
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 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(MainActivity.this, t.getMessage(),
Toast.LENGTH_LONG).show();
}
if (!cameraConfigured)
{
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null)
{
parameters.setPreviewSize(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
}
};
}
but if I try to do both at the same time:
package com.example.multiplecamerapreviewtest;
import java.io.IOException;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.FrameLayout;
import android.widget.Toast;
public class MainActivity extends Activity implements SurfaceTextureListener
{
private SurfaceView svPreview = null;
private SurfaceHolder previewHolder = null;
private Camera mCamera = null;
private boolean inPreview = false;
private boolean cameraConfigured = false;
private TextureView tvPreview = null;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
svPreview = (SurfaceView) findViewById(R.id.svPreview);
previewHolder = svPreview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// mTextureView = new TextureView(this);
tvPreview = (TextureView) findViewById(R.id.tvPreview);
tvPreview.setSurfaceTextureListener(this);
// setContentView(mTextureView);
}
#Override
public void onResume()
{
super.onResume();
mCamera = Camera.open();
startPreview();
}
#Override
public void onPause()
{
if (inPreview)
{
mCamera.stopPreview();
}
mCamera.release();
mCamera = null;
inPreview = false;
super.onPause();
}
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 void initPreview(int width, int height)
{
if (mCamera != null && previewHolder.getSurface() != null)
{
try
{
mCamera.setPreviewDisplay(previewHolder);
}
catch (Throwable t)
{
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(MainActivity.this, t.getMessage(),
Toast.LENGTH_LONG).show();
}
if (!cameraConfigured)
{
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null)
{
parameters.setPreviewSize(size.width, size.height);
mCamera.setParameters(parameters);
cameraConfigured = true;
}
}
}
}
private void startPreview()
{
if (cameraConfigured && mCamera != null)
{
mCamera.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
}
};
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height)
{
Log.i("onSurfaceTextureAvailable", "onSurfaceTextureAvailable");
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
tvPreview.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try
{
mCamera.setPreviewTexture(surface);
}
catch (IOException t)
{
}
mCamera.startPreview();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height)
{
// Ignored, the Camera does all the work for us
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
Log.i("onSurfaceTextureDestroyed", "onSurfaceTextureDestroyed");
mCamera.stopPreview();
mCamera.release();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
// Update your view here!
}
}
I get a "Fail to connect to camera service" exception when calling mCamera.setPreviewTexture().
According to the documentation (http://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay%28android.view.SurfaceHolder%29), this is the expected behavior:
setPreviewDisplay()
Setting a preview surface will un-set any preview surface texture that was set via setPreviewTexture(SurfaceTexture).
(and vice-versa). Is there anything I can do to get these both displaying at the same time?
Send the Camera output to a SurfaceTexture, then render the texture wherever you like using GLES.
See e.g. the "texture from camera" activity in Grafika.
This requires some EGL management and a basic familiarity with GLES, though you can get pretty far just using the code in Grafika. This approach will get you much better performance than manipulating pixels with the NDK, because the GPU does all the work.
Camera is a shared hardware resource. I don't think you can access it (Camera.open()) more than once even within the same application i.e even within the same process with same user id. How about accessing the buffers for camera preview natively and then reading bytes from those buffers to render them on as many TextureViews or SurfaceViews or VideoViews as you wish?
Edited:
NDK Resource:
How do I get the raw Android camera buffer in C using JNI?
Related
I downloaded the project for qr and bar code scanner from git hub and facing difficulty in changing scanner from landscape mode to portrait mode and i checked many stackoverflow links but didn't get proper solution and i am using zxing 2.1 jar in my code.Here is my code please check the code and please do some helpful to solve this problem.Thanks in advance!!
Error:"java.lang.IllegalArgumentException: Crop rectangle does not fit within image data."
//BarcodeReader
package com.dynamsoft.barcodereader;
import android.app.Activity;
import android.os.Bundle;
import android.view.Display;
import android.widget.FrameLayout;
public class BarcodeReader extends Activity {
private CameraPreview mPreview;
private CameraManager mCameraManager;
private HoverView mHoverView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Display display = getWindowManager().getDefaultDisplay();
mHoverView = (HoverView)findViewById(R.id.hover_view);
mHoverView.update(display.getWidth(), display.getHeight());
mCameraManager = new CameraManager(this);
mPreview = new CameraPreview(this, mCameraManager.getCamera());
mPreview.setArea(mHoverView.getHoverLeft(), mHoverView.getHoverTop(), mHoverView.getHoverAreaWidth(), display.getWidth());
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
getActionBar().hide();
}
#Override
protected void onPause() {
super.onPause();
mPreview.onPause();
mCameraManager.onPause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mCameraManager.onResume();
mPreview.setCamera(mCameraManager.getCamera());
}
}
//CameraManager .java
package com.dynamsoft.barcodereader;
import android.content.Context;
import android.hardware.Camera;
import android.widget.Toast;
public class CameraManager {
private Camera mCamera;
private Context mContext;
public CameraManager(Context context) {
mContext = context;
// Create an instance of Camera
mCamera = getCameraInstance();
}
public Camera getCamera() {
return mCamera;
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
public void onPause() {
releaseCamera();
}
public void onResume() {
if (mCamera == null) {
mCamera = getCameraInstance();
}
Toast.makeText(
mContext,
"preview size = "
+ mCamera.getParameters().getPreviewSize().width + ", "
+ mCamera.getParameters().getPreviewSize().height,
Toast.LENGTH_LONG).show();
}
/** A safe way to get an instance of the Camera object. */
private 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)
}
return c; // returns null if camera is unavailable
}
}
//HoverView .java
package com.dynamsoft.barcodereader;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class HoverView extends View {
private Paint mPaint;
private int mLeft, mTop, mRight, mBottom;
public HoverView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
}
public void update(int width, int height) {
int centerX = width / 2;
int centerY = height / 2;
mLeft = centerX - 200;
mRight = centerX + 200;
mTop = centerY - 200;
mBottom = centerY + 200;
invalidate();
}
public int getHoverLeft() {
return mLeft;
}
public int getHoverTop() {
return mTop;
}
public int getHoverAreaWidth() {
return mRight - mLeft;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawRect(mLeft, mTop, mRight, mBottom, mPaint);
}
}
//CameraPreview.java
package com.dynamsoft.barcodereader;
import java.io.IOException;
import android.app.AlertDialog;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private static final String TAG = "camera";
private int mWidth, mHeight;
private Context mContext;
private MultiFormatReader mMultiFormatReader;
private AlertDialog mDialog;
private int mLeft, mTop, mAreaWidth, mAreaHeight;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mContext = context;
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Parameters params = mCamera.getParameters();
mWidth = 640;
mHeight = 480;
params.setPreviewSize(mWidth, mHeight);
mCamera.setParameters(params);
mMultiFormatReader = new MultiFormatReader();
mDialog = new AlertDialog.Builder(mContext).create();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
}
try {
mCamera.setPreviewCallback(mPreviewCallback);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
public void setCamera(Camera camera) {
mCamera = camera;
}
public void onPause() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
}
}
private Camera.PreviewCallback mPreviewCallback = new PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
if (mDialog.isShowing())
return;
LuminanceSource source = new PlanarYUVLuminanceSource(data, mWidth,
mHeight, mLeft, mTop, mAreaWidth, mAreaHeight, false);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result;
try {
result = mMultiFormatReader.decode(bitmap, null);
if (result != null) {
mDialog.setTitle("Result");
mDialog.setMessage(result.getText());
mDialog.show();
}
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
public void setArea(int left, int top, int areaWidth, int width) {
double ratio = width / mWidth;
mLeft = (int) (left / (ratio + 1));
mTop = (int) (top / (ratio + 1));
mAreaHeight = mAreaWidth = mWidth - mLeft * 2;
}
}
It does not work on portrait mode. You need to limit your barcode activity to landscape mode.
<activity
android:name=".BarcodeReader"
android:screenOrientation="landscape" />
I have some troubles with camera. I test my code on Xiaomi Mi2a and preview was distorted.
I have this line in manifest: android:screenOrientation="portrait"
I use camera with this fragment:
import android.app.Fragment;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.*;
import android.widget.
import java.io.IOException;
import java.util.List;
public class CameraFragment extends Fragment implements SurfaceHolder.Callback, Camera.PictureCallback, Camera.PreviewCallback, Camera.AutoFocusCallback, View.OnClickListener {
private Camera mCamera;
private SurfaceHolder mSurfaceHolder;
private SurfaceView mPreview;
private ImageButton mTakePicture;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.camera_fragment, container, false);
mPreview = (SurfaceView) v.findViewById(R.id.svCameraView);
mSurfaceHolder = mPreview.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mTakePicture = (ImageButton) v.findViewById(R.id.ibTakePicture);
mTakePicture.setOnClickListener(takePictureOnClickListener);
ImageButton switchCameraButton = (ImageButton) v.findViewById(R.id.ibSwitchCamera);
switchCameraButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
return v;
}
View.OnClickListener takePictureOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
}
};
#Override
public void onResume() {
super.onResume();
mCamera = Camera.open();
}
#Override
public void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(this);
} catch (IOException e) {
e.printStackTrace();
return;
}
Camera.Parameters parameters = mCamera.getParameters();
List<String> flashModes = parameters.getSupportedFlashModes();
/*if (flashModes != null && flashModes.contains(Camera.Parameters.FLASH_MODE_OFF))
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);*/
List<String> whiteBalance = parameters.getSupportedWhiteBalance();
if (whiteBalance != null && whiteBalance.contains(Camera.Parameters.WHITE_BALANCE_AUTO))
parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
/*if (sizes != null && sizes.size() > 0) {
Camera.Size size = sizes.get(0);
parameters.setPictureSize(size.width, size.height);
}*/
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
/*if (previewSizes != null) {
Camera.Size previewSize = previewSizes.get(previewSizes.size() - 1);
parameters.setPreviewSize(previewSize.width, previewSize.height);
}*/
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
float aspect = (float) previewSize.width / previewSize.height;
int previewSurfaceWidth = mPreview.getWidth();
int previewSurfaceHeight = mPreview.getHeight();
ViewGroup.LayoutParams lp = mPreview.getLayoutParams();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
mCamera.setDisplayOrientation(90);
lp.height = previewSurfaceHeight;
lp.width = (int) (previewSurfaceHeight / aspect);
} else {
mCamera.setDisplayOrientation(0);
lp.width = previewSurfaceWidth;
lp.height = (int) (previewSurfaceWidth / aspect);
}
mPreview.setLayoutParams(lp);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void onClick(View v) {
if (v == mTakePicture) {
//mCamera.takePicture(null, null, null, this);
mCamera.autoFocus(this);
}
}
#Override
public void onPictureTaken(byte[] paramArrayOfByte, Camera paramCamera) {
paramCamera.startPreview();
}
#Override
public void onAutoFocus(boolean paramBoolean, Camera paramCamera) {
if (paramBoolean) {
paramCamera.takePicture(null, null, null, this);
}
}
#Override
public void onPreviewFrame(byte[] paramArrayOfByte, Camera paramCamera) {
}
I don't know how about resulting image, because I'm not need it at the moment. But preview is distorted. For example:
http://habrastorage.org/files/fc5/cd1/6fb/fc5cd16fb80f41f6ac7a8a800e0348b6.png
http://habrastorage.org/files/968/cd4/850/968cd48505564f93b0258a07fe48a545.png
What do I wrong? How to keep preview in normal state, without stretching? Or, maybe, is it problem with miui?
How to keep preview in normal state, without stretching?
Your SurfaceView needs to be in the same aspect ratio as is the camera preview. Otherwise, the camera preview will be stretched in one direction to fit the SurfaceView.
Take Video Size or Picture Size Available on Device
check in preview constructor-
List<Camera.Size> sizes = mCamera.getParameters()
.getSupportedVideoSizes();
if (sizes != null)
for (Camera.Size size : sizes) {
int h = size.height;
int w = size.width;
System.out.println("h=" + h + " w=" + w);
}
then decide what resolution you want for you requirment then make frame layout of same resoultion
abc.xml file
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="288dp"
android:layout_height="352dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
>
</FrameLayout>
preview in surface created-
if(mCamera!=null)
{
Parameters params=mCamera.getParameters();
params.setPictureSize(288, 352);
mCamera.setParameters(params);
}
please make change according to your need if you need any help then ask.
Set Camera Parameter as
Camera.Parameters params = mCamera.getParameters();
params.set("orientation", "portrait");
mCamera.setParameters(params);
this will help you..
I am developing a camera app and the problem is that the camera i am making shows a distorted preview.
The picture it takes is clear but the preview is messed up.
Complete camera preview code is below just in case:
import java.io.IOException;
import java.util.List;
import com.glass.cuxtomcam.constants.CuxtomIntent.CAMERA_MODE;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.OnZoomChangeListener;
import android.hardware.Camera.Parameters;
import android.util.Log;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback, OnZoomChangeListener {
private SurfaceHolder mHolder;
private Camera mCamera;
private Context mContext;
private static String TAG = "CAMERA PREVIEW";
private int zoomOffset;
private CameraListener mCallback;
private int cameraMode;
public CameraPreview(Context context, Camera camera, int cameraMode) {
super(context);
mContext = context;
mCamera = camera;
mHolder = getHolder();
this.cameraMode = cameraMode;
mHolder.addCallback(this);
mHolder.setKeepScreenOn(true);
}
public void setCameraListener(CameraListener listener) {
mCallback = listener;
}
#Override
public synchronized void surfaceChanged(SurfaceHolder holder, int format,
int width, 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;
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.stopPreview();
if (mCamera.getParameters().isZoomSupported()) {
mCamera.setZoomChangeListener(this);
zoomOffset = mCamera.getParameters().getMaxZoom() / 5;
}
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
mCamera.lock();
} catch (IOException e) {
Log.e("Error starting preview", e.getMessage());
}
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
// release the camera
mCamera.release();
// unbind the camera from this object
mCamera = null;
}
}
public synchronized void zoomIn() {
if (mCamera != null && mCamera.getParameters().isZoomSupported()
&& mCamera.getParameters().isSmoothZoomSupported()) {
int zoomvalue = mCamera.getParameters().getZoom() + zoomOffset;
if (zoomvalue <= mCamera.getParameters().getMaxZoom()) {
mCamera.startSmoothZoom(zoomvalue);
}
} else {
Toast.makeText(mContext, "Zoom In is not supported",
Toast.LENGTH_LONG).show();
}
}
public synchronized void zoomOut() {
if (mCamera != null && mCamera.getParameters().isZoomSupported()
&& mCamera.getParameters().isSmoothZoomSupported()) {
int zoomvalue = mCamera.getParameters().getZoom() - zoomOffset;
if (zoomvalue >= 0) {
mCamera.startSmoothZoom(zoomvalue);
}
} else {
Toast.makeText(mContext, "Zoom Out is not supported",
Toast.LENGTH_LONG).show();
}
}
#Override
public void onZoomChange(int zoomValue, boolean stopped, Camera camera) {
// Log.i("Camera Zoom Value", zoomValue + "");
}
}
Can anyone guide me on why is this happening?
Not sure if it is still relevant (after 2 months without an answer). But this is a solution I used when my camera was like you showed.
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewFpsRange(30000, 30000);
parameters.setPreviewSize(640,360);
camera.setParameters(parameters);
It sets the frames per second to 30fps, the problem you are experiencing is a too high framerate (most likely)
MainActivity
public class MainActivity extends Activity implements TextureView.SurfaceTextureListener{
private Camera mCamera;
private TextureView mTextureView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
mCamera = Camera.open(0);
try {
mCamera.setPreviewTexture(surface);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
mCamera.stopPreview();
mCamera.release();
return true;
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,
int arg2) {
// TODO Auto-generated method stub
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
// TODO Auto-generated method stub
}
}
The live preview is flipped to left side. On searching I found that setTransform is a solution, but I am not sure how to use it. Can anyone give me a code example?
NB: It is to flip the live preview not an image.
Follows a minimal example that uses SurfaceTexture to display front facing camera without mirroring. Note that error checking is mostly dropped for brevity. Also, in this example I do not follow the recommendation to open camera in a background thread (on some devices this may freeze the UI for too long).
import java.io.IOException;
import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Surface;
import android.view.TextureView;
import android.widget.FrameLayout;
public class SurfaceTextureActivity extends Activity implements TextureView.SurfaceTextureListener{
private Camera mCamera;
private TextureView mTextureView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
int cameraId = 0;
Camera.CameraInfo info = new Camera.CameraInfo();
for (cameraId = 0; cameraId < Camera.getNumberOfCameras(); cameraId++) {
Camera.getCameraInfo(1, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
break;
}
mCamera = Camera.open(cameraId);
Matrix transform = new Matrix();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
int rotation = getWindowManager().getDefaultDisplay()
.getRotation();
Log.i("onSurfaceTextureAvailable", " CameraOrientation(" + cameraId + ")" + info.orientation + " " + previewSize.width + "x" + previewSize.height + " Rotation=" + rotation);
switch (rotation) {
case Surface.ROTATION_0:
mCamera.setDisplayOrientation(90);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.height, previewSize.width, Gravity.CENTER));
transform.setScale(-1, 1, previewSize.height/2, 0);
break;
case Surface.ROTATION_90:
mCamera.setDisplayOrientation(0);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
transform.setScale(-1, 1, previewSize.width/2, 0);
break;
case Surface.ROTATION_180:
mCamera.setDisplayOrientation(270);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.height, previewSize.width, Gravity.CENTER));
transform.setScale(-1, 1, previewSize.height/2, 0);
break;
case Surface.ROTATION_270:
mCamera.setDisplayOrientation(180);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
transform.setScale(-1, 1, previewSize.width/2, 0);
break;
}
try {
mCamera.setPreviewTexture(surface);
} catch (IOException t) {
}
mTextureView.setTransform(transform);
Log.i("onSurfaceTextureAvailable", "Transform: " + transform.toString());
mCamera.startPreview();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, the Camera does all the work for us
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Update your view here!
}
}
I have been getting a set of very specific errors when developing a very basic camera application. The code is almost identical to that on the android website.
The Galaxy SII is the only phone giving me the error which appears as follows in my LogCat console:
06-28 16:28:40.098: E/Surface(1650): Surface::init token -2 identity 18
The number that follows "identity" changes (42, 38, etc) but the error persists.
I think this may be related to the following class, but am still unsure as to its meaning:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
What about the Galaxy SII might cause this error? I am also testing on an HTC Vivid and Pantech Burst. I fear this may be leading to larger problems. I am just trying to understand what this error may be about.
Here is the source:
package com.basicam.android;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class CamActivity extends Activity {
private SurfaceView preview=null;
private SurfaceHolder previewHolder=null;
private Camera camera=null;
private boolean inPreview=false;
private boolean cameraConfigured=false;
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d("crap","oncreated");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview=(SurfaceView)findViewById(R.id.preview);
previewHolder=preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume() {
super.onResume();
camera=Camera.open();
startPreview();
}
#Override
public void onPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera cam) {
Camera.Size result=null;
Log.d("crap", "can haz preview sizes?");
int i = 0;
for (Camera.Size size : cam.getParameters().getSupportedPictureSizes()) {
Log.d("sizew", ""+size.width);
if (size.width<=width && size.height<=height) {
Log.d("sizew", ""+size.width);
Log.d("sizeh", ""+size.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 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);
}
if (!cameraConfigured) {
Camera.Parameters parameters=camera.getParameters();
Camera.Size size=getBestPreviewSize(width, height,
camera);
if (size!=null) {
parameters.setPreviewSize(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
}
};
}