.setPreviewDisplay(holder) throwing null pointer exception - android

I am developing a custom camera application.Given below is my Activity class.
public class MyCustomCam extends Activity {
private Camera mCamera;
private CameraPreview mPreview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
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)
}
return c; // returns null if camera is unavailable}
}
}
Given below is my main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
<Button android:id="#+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/></LinearLayout>
And this is my CameraPreview class
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(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);
}
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("", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
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 // start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d("", "Error starting camera preview: " + e.getMessage());
}
}
}
Here
mCamera.setPreviewDisplay(holder);
code is throwing null pointer exception...i cant fix that.please tell me why it is throwing exception and how can i fix that?

Release the camera in your surfaceDestroyed function
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
and make sure you add camera permission in your manifest file.
<uses-permission android:name="android.permission.CAMERA" />

I was having the same bug.
I used this Q&A to help solve my issue. Specifically, reference the adding of the function getBestPreviewSize(...) invoked prior to params.setPreviewSize(...) being set in surfaceChanged.
Android - cam.setPreviewDisplay(holder) running into IOError
As a side note (because this was my next bug), if you start doing any more customization of the Layout (e.g. removing the title bar), any "requests" to the UI to make changes should be made prior to setContentView(...), noted in the link below.
requestFeature() must be called before adding content

Most probably your problem would be that your emulator's camera settings. Go to AVD manager, edit your emulator and set your camera , may be to emulated. restart the emulator and launch your app.

Related

How to prevent Camera app to change orientation to landscape in Android?

I've used the camera native app through my app for taking picture. I've used the below code for display the camera app in portrait mode only.
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
takePictureIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
startActivityForResult(takePictureIntent, actionCode);
But, it's not working with the above code.
Any suggestions will be appreciated :-)
You can't control the orientation of an external application that you launch, so there is no way to do this.
But you could create your own camera activity.
considering your mCamera as your Camera, you can create your camera activity, set à cameraPReview and set the preview in protrait mode by adding mCamera.setDisplayOrientation(90); before starting preview
here is an example for camera preview in a FrameLayout in potrait mode:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(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);
}
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.setDisplayOrientation(90);
mCamera.startPreview();}
} catch (IOException e) {
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
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
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
}
}
and you set the preview from your MainActivity like below :
mPreview = new CameraPreview(getApplicationContext(), camera);
preview.addView(mPreview);

Zbar scanner and autofocus

I have used zbar scanner for android and it captures the barcodes quite easily.
But the problem is that on phones which have autofocus, it captures the barcodes too quickly to detect it correctly.
If only it could wait for a few milliseconds more, it could then be able to capture more clearer image and thereby not show "not found" page.
How can I solve this problem?
Is there a provision to delay the focus on the barcode?
Maybe a delay in capturing the image?
Are you talking about the example code, CameraTestActivity.java?
Implement a counter that counts for similar scanning results. If the scanning result remains the same (e.g. for 10 times in a row), we can assume the result is quite reliable.
I really like #Juuso_Ohtonen's reply, and actually just used it in my own reader, however if you want an AutoFocus delay you can create a Camera.AutoFocusCallback object and implement its onAutoFocus method with a .postDelayed. This object is then used on your Camera camera.autoFocus() method.
// Mimic continuous auto-focusing
Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
autoFocusHandler.postDelayed(doAutoFocus, 1000);
}
};
This section is used in the class that extends SurfaceView, which then implements surfaceChanged();
public CameraPreview(Context context, Camera camera,
PreviewCallback previewCb,
AutoFocusCallback autoFocusCb) {
super(context);
mCamera = camera;
previewCallback = previewCb;
autoFocusCallback = autoFocusCb;
// 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);
}
public 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;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCallback);
} catch (Exception e) {
Log.d("DBG", "Error starting camera preview: " + e.getMessage());
}
}

QR code scanning without fullscreen camera

I need to continuously scan QR codes in my Android app while the main View of the app is on the screen. The main view should contain a window with camera preview, but not a fullscreen camera preview.
An example of usage: Main view containing a list of scanned QR codes and a camera preview. When new QR code is scanned, it is added to the list.
Is it possible?
I don't have an fully working example, but I can give you snippets from an project of mine where I also put the camera previews in an smaller view than the full screen. I just want to convey the idea.
What you need is a FrameLayout which will hold the camera preview
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/absoluteLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/transparent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="200dp"
android:layout_height="200dip" >
</FrameLayout>
</RelativeLayout>
Now we need a PreviewListener which is also an View
import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/** A basic Camera preview class */
public class CameraPreviewListener extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreviewListener(Context context, Camera camera) {
super(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);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Take care of releasing the Camera preview in your activity.
Log.d("camera", "surfaceDestroyed");
if(holder.equals(mHolder)){
holder.removeCallback(this);
}else{
holder.removeCallback(this);
mHolder.removeCallback(this);
}
}
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){
e.printStackTrace();
// 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);
mCamera.startPreview();
} catch (Exception e){
Log.d("camera", "Error starting camera preview: " + e.getMessage());
}
}
public void removeCallback(){
mHolder = getHolder();
mHolder.removeCallback(this);
}
}
Finally you need to assemble everything in you activity
import android.hardware.Camera;
Camera mCamera = = getCameraInstance();
CameraPreviewListener cpl = new CameraPreviewListener(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(cpl);
To get the camera you can use the following method
/** A safe way to get an instance of the Camera object. */
public Camera getCameraInstance() {
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
Parameters p = c.getParameters();
List<Size> sizes = p.getSupportedPictureSizes();
Size x = null;
if (sizes.size() < 1) {
throw new Exception("there are not supported picture sizes at all !!!");
}
for (Size s : sizes) {
if (s.width == 640 && s.height == 480) {
x = s;
}
}
if (x == null) {
x = sizes.get(0);
p.setPictureSize(x.width, x.height);
} else {
p.setPictureSize(640, 480);
}
p.setJpegQuality(20);
p.setGpsLatitude(MapViewer.latitude);
p.setGpsLongitude(MapViewer.longitude);
c.setParameters(p);
} catch (Exception e) {
// Camera is not available (in use or does not exist)
Log.d(TAG + "(getCameraInstance)", e.getMessage());
}
return c; // returns null if camera is unavailable
}
Hope this work with you, You can capture image from background without opening camera app
https://stackoverflow.com/a/24849344/1312796

android camera error 1001 - what the heck is that?

I've searched all over on the web and I can't find out what that 1001 error is. A few seconds after that I get the camera 100 error but I can't find out what the first error is. Does anyone have any ideas?
I encountered this error as well on my S3. I believe I tracked it down to how the camera preview surface was used by the MediaRecorder. In my case the preview display was getting reset when I was attempting to start recording. I solved it by cleaning out my code and just used the calls to set, start and stop the preview display in the SurfaceView implementation below (from the Android Camera developer guide):
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(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);
}
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(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
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
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
Just thought I would add a post here for future reference. This issue bothered me for a long time.
It turns out that my problem was caused by an incorrect preview size, although the resolution set was obtained from the getSupportedPictureSize method.
So for example you can get the sizes as follows:
//first entry in list is 1392x1392 for front facing camera on an S3
List<Camera.Size> supportedPictureSizes = params.getSupportedPictureSizes();
Setting this resolution or neglecting to set a picture size alltogether will cause the dreaded error 1001.
If you encounter this on any other device I would recommend trying different picture sizes.
So there was another reason for why I got it on my Galaxy S3. I was using a TextureView to show my camera preview and got this dreaded error when pressing the home button after a successful preview and then entering the app again. In the onResume() function I started up the preview again and found that I had not released the SurfaceTexture instance variable in the onSurfaceTextureDestroyed() function.
I added the release line to this function and it now looks like this and works perfectly:
#Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mSurfaceTexture = null; //This was the offending culprit.
releaseMediaPlayer();
releaseVideoRecorder();
releaseCamera();
return false;
}
In my case, in Samsung S3, the video-size parameter was not set and this led to the 1001 error. Setting the video size on the media recorder using preview size fixed the issue. However, this change may fail on other devices since the parameter may or may not be available/set in all devices. The following code addresses most of the devices:
if(params.get("video-size") != null && params.get("video-size").isEmpty()) {
int videoWidth = params.getPreviewSize().width;
int videoHeight = params.getPreviewSize().height;
mediaRecorder.setVideoSize(videoWidth, videoHeight);
} else {
mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
}

Android Camera Surface View

I am trying to create a surface view for a camera so it renders on the surface whenever is in the view of the camera. At the moment all I can see on my camera view is a black screen view. I have tried to look on Google and here but so far I haven't found what I am looking for. Anyone can suggest me some idea.
I have written a class that can help you.
public class Preview_can_work extends Activity {
private SurfaceView surface_view;
private Camera mCamera;
SurfaceHolder.Callback sh_ob = null;
SurfaceHolder surface_holder = null;
SurfaceHolder.Callback sh_callback = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
surface_view = new SurfaceView(getApplicationContext());
addContentView(surface_view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
if (surface_holder == null) {
surface_holder = surface_view.getHolder();
}
sh_callback = my_callback();
surface_holder.addCallback(sh_callback);
}
SurfaceHolder.Callback my_callback() {
SurfaceHolder.Callback ob1 = new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mCamera.startPreview();
}
};
return ob1;
}
}
in your manifest file copy this code for camera permission
<uses-permission android:name="android.permission.CAMERA"/>
Explanation:
SurfaceView is a type of View which contains a SurfaceHolder. SurfaceHolder holds the surface on which we can display our media (generally frames).
mCamera is a Camera object which will contains the camera instance.
When you want to hold default Camera instance then you can simply call Camera.open();
Camera mCamera = Camera.open();
Now you have an open camera or you are having default camera instance. Now you need to capture frames from the camera and display it on a surface. But you cannot display it without any
surface. Here the surfaceView provides surfaceHolder and surfaceHolder provides surface to display camera frames. Now when surface will be created three callback functions will be
called.
1. public void surfaceCreated(SurfaceHolder holder)
2. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
3. public void surfaceDestroyed(SurfaceHolder holder)
Note:- Surface will be destroyed when your application will go on pause.
surfaceCreated:
surfaceCreated is a callback function which will be called when your surface will be created. In this, you can open your camera and set other attributes.
surfaceChanged:
This will be called atleast one time when your surface will be created. After that it will be called whenever your surface will change(In device rotation). Here you can
start your preview because your surface have already created.
surfaceDestroyed:
This will be called every time when your surface will destroy. Now if you dont have surface then where you can display you camera frames so I have released camera by using
mCamera.release(). This is very important because if your activity will be on pause and any other activity tries to open camera then it will not able to open it as you have
already open camera. Camera is a shared resource so one time only one application can use it. So remember one thing whenever you open a camera then always release it.
stopPreview:
When you start preview then your camera starts capturing your frames and display it on a surface. Now if your surface have destroyed then you need to stop capturing frames
from camera so you have to call mCamera.stopPreview.
Make shure you added the permission :
<uses-permission android:name="android.permission.CAMERA"/>
Also these window properties:
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Post some code if that doesn't work in order to help you

Categories

Resources