Null pointer for a camera object in onSurfaceCreared method - java

I'm having trouble getting my camera to work (I mean, it does work, but in the meantime I get a NullPointerException). It is thrown at the onSurfaceCreated method:
public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraView(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);
Log.i("xcamerx", String.valueOf(mCamera));
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
Log.i("xcamera", String.valueOf(mCamera));
Log.i("xcamera", String.valueOf(holder));
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("CameraError", "Error starting 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("CameraError", "Error starting camera preview: " + e.getMessage());
}
}
public void pause()
{
mHolder.removeCallback(this);
}
public void resume()
{
mHolder.addCallback(this);
}
}
which is implemented in my SurfaceView. In the activity of this view, I get a Camera instance:
public class CameraActivity extends Activity {
private Camera mCamera;
private CameraView mPreview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraView(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_view);
preview.addView(mPreview);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
mPreview.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mPreview.resume();
}
/** 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)
}
return c; // returns null if camera is unavailable
}
}
which is then passed to the SurfaceView constructor as an argument. In the LogCat, when I print the Camera object (like in the first code block I posted), I get several times a valid Camera object, but now and then there are some nulls which appear for reasons beyond my comprehension. Any ideas?

Related

Implementing a separate Class into Activity

The problem
In cleaning up my code I want to move my Android camera methods to a separate class, in line with what I believe are best practices. After searching all day, I'm still struggling to figure out how to do this exactly. Main problem is that the differences in implementation methods and moving from camera API to camera2 API lead to solutions found online which I can't replicate. Please note that I am quite a beginner in Java and as such, it is probably a very rookie mistake which I can't solve due to the variety of info on the web.
Current code
My main problem is that SurfaceTexture texture = surfaceView.getSurfaceTexture(); in startCamera() says Cannot resolve method 'getSurfaceTexture()' and that previewBuilder.addTarget(texture); complains about addTarget (android.view.surface) in Builder cannot be applied to (android.graphics.SurfaceTexture).
public class CameraView extends TextureView implements TextureView.SurfaceTextureListener{
private Size previewsize;
private CameraDevice cameraDevice;
private CaptureRequest.Builder previewBuilder;
private CameraCaptureSession previewSession;
private final Context context;
public SurfaceView surfaceView;
public TextureView textureView;
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
// Once the surface is created, simply open a handle to the camera hardware.
openCamera();
}
public void onSurfaceTextureUpdated(SurfaceTexture texture) {
}
public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
try {
//cameraDevice.setPreviewDisplay(holder);
//cameraDevice.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
// stopPreview();
cameraDevice.close();
return true;
}
public void openCamera()
{
CameraManager manager = (CameraManager) context.getSystemService (Context.CAMERA_SERVICE);
try
{
String cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics=manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
previewsize = map.getOutputSizes(SurfaceTexture.class)[0];
try {
manager.openCamera(cameraId, stateCallback, null);
} catch (SecurityException e){
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(CameraDevice camera) {
cameraDevice = camera;
startCamera();
}
#Override
public void onClosed(CameraDevice camera) {
// nothing
}
#Override
public void onDisconnected(CameraDevice camera) {
}
#Override
public void onError(CameraDevice camera, int error) {
}
};
void startCamera()
{
if (cameraDevice == null || previewsize==null)
{
return;
}
SurfaceTexture texture = surfaceView.getSurfaceTexture();
texture.setDefaultBufferSize(previewsize.getWidth(),previewsize.getHeight());
Surface surface = new Surface(texture);
try
{
// add all the standard stuff to the previewBuilder
previewBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
} catch (Exception e) {}
previewBuilder.addTarget(texture);
try
{
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
previewSession = session;
getChangedPreview();
}
#Override
public void onConfigureFailed(CameraCaptureSession session{
}
},null);
} catch (Exception e) {}
}
void getChangedPreview()
{
previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
HandlerThread thread = new HandlerThread("changed Preview");
thread.start();
Handler handler = new Handler(thread.getLooper());
try
{
previewSession.setRepeatingRequest(previewBuilder.build(), null, handler);
}catch (Exception e){}
}
}
The goal
To keep my code clean and understandable I would like to limit the MainActivity class to switching between views instead of having tons of methods in there. I would like to activate my camera view in my app by switching the following object from INVISIBLE to VISIBLE. Other suggestions are appreciated.
cameraView = (CameraView) findViewById(R.id.camera);
MainActivity.java would then look like:
public class MainActivity extends AppCompatActivity {
private TextView mTextMessage;
private CameraView cameraView;
private MainSurfaceView mGLView;
private TextureView textureView;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
return true;
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextMessage = (TextView) findViewById(R.id.message);
cameraView = (CameraView) findViewById(R.id.camera);
mGLView = (MainSurfaceView) findViewById(R.id.glSurfaceView);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
}
Your help is appreciated!
SurfaceTexture texture = surfaceView.getSurfaceTexture(); in startCamera() says Cannot resolve method 'getSurfaceTexture()'
You call the method getSurfaceTexture of surfaceView. surfaceView is a SurfaceView. Let's take a look at the documentation:
https://developer.android.com/reference/android/view/SurfaceView.html
Apparently SurfaceView has no method called "getSurfaceTexture()". However, searching on Google for "getSurfaceTexture() Android" shows us that the method belongs to the TextureView class. Your class CameraView has a field called "textureView", so (I don't know what you want to achieve exactly) can call the method on that field if you want. Additionally your class CameraView is a TextureView itself (do you want that), so you could also just call getSurfaceTexture() if you want to invoke it on the class itself.
previewBuilder.addTarget(texture); complains about addTarget (android.view.surface) in Builder cannot be applied to (android.graphics.SurfaceTexture).
Let's have a look at the documentation again: https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.Builder.html
Apparently CaptureRequest.builder (the type of previewBuilder) has a method called addTarget, but that method only accepts a Surface! You're passing a texture. You probably want to change texture to surface

Taking picture without using camera application - Android

I understand how to capture an image using intents and launching the camera app using intents, however I would like to know how to do so in the following steps:
display surfaceview showing preview of camera to user
when user presses capture, display captured image on screen to user and hide surfaceview with camera preview (exact same behaviour as snapchat).
NP - I do not want the camera app to be launched at anytime during this process, I want it all to be done within my own app. The problem with my current code is that it launches the camera app when the capture button is pressed. Also, it does not display the taken photo properly, a white screen is shown instead. I currently have this code created:
ANDROID ACTIVITY:
public class CameraScreen extends Activity {
private Camera mCamera = null;
private SessionManager session;
private String rand_img;
private ImageView preview_pic;
private CameraPreview mCameraView = null;
static final int CAM_REQUEST = 1;
private RandomString randomString = new RandomString(10);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_screen);
session = new SessionManager(getApplicationContext());
try{
mCamera = Camera.open();//you can use open(int) to use different cameras
} catch (Exception e){
Log.d("ERROR", "Failed to get camera: " + e.getMessage());
}
if(mCamera != null) {
mCameraView = new CameraPreview(this, mCamera);//create a SurfaceView to show camera data
FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
camera_view.addView(mCameraView);//add the SurfaceView to the layout
}
//btn to close the application
Button imgClose = (Button)findViewById(R.id.imgClose);
imgClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
System.exit(0);
}
});
//btn to logout
Button logout = (Button)findViewById(R.id.imgOpen);
logout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
session.logOut();
Intent a = new Intent(CameraScreen.this, MainActivity.class);
startActivity(a);
finish();
}
});
//CAPTURE BUTTON
Button snap = (Button) findViewById(R.id.snap);
snap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent capture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
capture.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getFile()));
startActivityForResult(capture,CAM_REQUEST);
}
});
}
#Override
protected void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCameraView.getHolder().removeCallback(mCameraView);
mCamera.release();
}
}
#Override
public void onResume() {
super.onResume();
// Get the Camera instance as the activity achieves full user focus
if (mCamera == null) {
initializeCamera(); // Local method to handle camera initialization
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String path = "sdcard/city_life_pic/" + rand_img;
preview_pic = (ImageView) findViewById(R.id.picturedisplay);
FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
camera_view.setVisibility(View.GONE);
preview_pic.setVisibility(View.VISIBLE);
preview_pic.setImageDrawable(Drawable.createFromPath(path));
}
protected void initializeCamera(){
// Get an instance of Camera Object
try{
mCamera = Camera.open();//you can use open(int) to use different cameras
} catch (Exception e){
Log.d("ERROR", "Failed to get camera: " + e.getMessage());
}
if(mCamera != null) {
mCameraView = new CameraPreview(this, mCamera);//create a SurfaceView to show camera data
FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);
camera_view.addView(mCameraView);//add the SurfaceView to the layout
}
}
private File getFile() {
File folder = new File("sdcard/city_life_pic");
if (!folder.exists()) {
folder.mkdir();
}
rand_img = randomString.nextString() + ".jpg";
File image = new File(folder,rand_img);
return image;
}
}
CAMERA 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;
mCamera.setDisplayOrientation(90);
//get the holder and set this class as the callback, so we can get camera data here
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);;
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try{
//when the surface is created, we can set the camera to draw images in this surfaceholder
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR", "Camera error on surfaceCreated " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
//before changing the application orientation, you need to stop the preview, rotate and then start it again
if(mHolder.getSurface() == null)//check if the surface is ready to receive camera data
return;
try{
mCamera.stopPreview();
} catch (Exception e){
//this will happen when you are trying the camera if it's not running
}
//now, recreate the camera preview
try{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("ERROR", "Camera error on surfaceChanged " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
//our app has only one screen, so we'll destroy the camera in the surface
//if you are unsing with more screens, please move this code your activity
mCamera.stopPreview();
mCamera.release();
}
}
You are opening the device's camera app by using this code
Intent a = new Intent(CameraScreen.this, MainActivity.class);
startActivity(a);
finish();
Instead, to take a picture using your custom camera, use Camera#takePicture method instead
That would make your code
snap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(....) //set parameters based on what you need
}
});

How to invert the image when the camera is initialized in Android?

When the camera is initialized, if the device is vertically, image upside down and backwards on the front, and if device horizontally, image upside down. How to make the right conclusion pictures?
**Code hire **
package com.example.aleksey.camera;
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
// create the surface and start camera preview
if (mCamera == null) {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (Exception e) {
Toast.makeText(getContext(), "Error setting camera preview", Toast.LENGTH_SHORT).show();
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
refreshCamera(mCamera);
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
}
mCamera = camera;
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Toast.makeText(getContext(), "Error starting camera preview:", Toast.LENGTH_SHORT).show();
}
}
#Override`enter code here
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.release();
}
// camera.setDisplayOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
At the end of the code have uncommented function like it should work, but I've tried all the options and without success.
Try to set
camera.setDisplayOrientation(90);
With correct orientation.
Different devices may have different sensor orientations, so you may should calculate the final orientation yourself, depending on Devise's orientation and sensor's orientation. To get sensor orientation use
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraIndex, cameraInfo);
int sensorOrientation = cameraInfo.orientation;

Fail to connect to camera service (RuntimeException) without any good reason

So my Manifest.xml is correct:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus"/>
<application>
...
I also release the camera in the onPause and onDestroy functions, using this function:
private void releaseCamera() {
// stop and release camera
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
//mPreview instance of CameraPreview (referenced below)
if (mPreview != null) {
mPreview.setCamera(null);
}
}
I call mCamera = Camera.open(); only once, during on onResume.
Even though I do everything exactly as specified by every example I have found on Stack Overflow and other sources, Camera.open() would occasionally fail.
Some use cases:
Open Camera Activity with WiFi enabled (Camera Works)
Open Camera Activity with no network connection (Camera Fails) //Bizarre
On catching RuntimeException, then calling mCamera.takePicture(), activity crashes and reloads. (Camera Works)
So I am completely stumped... Any ideas would be greatly appreciated :D
As requested, find the relevant code below:
CameraPreiview
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
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) {
try {
// create the surface and start camera preview
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void refreshCamera(Camera camera) {
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
setCamera(camera);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
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.
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
}
}
SampleActivity
public class CameraActivity extends Activity {
private static final String TAG = "CameraActivity";
private Camera mCamera;
private CameraPreview mPreview;
private Camera.PictureCallback mPicture;
private ImageButton capture;
private Context myContext;
private LinearLayout cameraPreview;
// Required to remove the camera if onPause did not
#Override
public void onDestroy() {
releaseCamera();
super.onDestroy();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_test);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
myContext = this;
initialize();
}
//Code to find the id for the traditional back facing camera
private int findBackFacingCamera() {
int cameraId = -1;
//Search for the back facing camera
//get the number of cameras
int numberOfCameras = Camera.getNumberOfCameras();
//for every camera check
for (int i = 0; i < numberOfCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
cameraFront = false;
break;
}
}
return cameraId;
}
#Override
public void onResume() {
super.onResume();
//If there is no camera on the device, inform the user.
if (!hasCamera(myContext)) {
Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG);
toast.show();
}
//release the camera if it's in use.
releaseCamera();
if (mCamera == null) {
//if the back facing camera does not exist
if (findBackFacingCamera() < 0) {
Toast.makeText(this, "No back facing camera found.", Toast.LENGTH_LONG).show();
} else {
try {
//Open the back facing camera, note that Camera.open() gives the same error.
mCamera = Camera.open(findBackFacingCamera());
mCamera.setDisplayOrientation(90); //Show in Portrait
mPicture = getPictureCallback();
mPreview.refreshCamera(mCamera);
} catch (RuntimeException e) {
e.printStackTrace();
Toast.makeText(this, "Could not connect to camera.", Toast.LENGTH_LONG).show();
}
}
}
}
public void initialize() {
cameraPreview = (LinearLayout) findViewById(R.id.camera_preview);
mPreview = new CameraPreview(myContext, mCamera);
cameraPreview.addView(mPreview);
capture = (ImageButton) findViewById(R.id.button_capture);
capture.setOnClickListener(captureListener);
}
#Override
protected void onPause() {
super.onPause();
//when on Pause, release camera in order to be used from other applications
releaseCamera();
}
private void captureComplete() {
//...
}
private Camera.PictureCallback getPictureCallback() {
Camera.PictureCallback picture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//make a new picture file
mFile = ImageUtility.getOutputMediaFile(ImageUtility.MEDIA_TYPE_IMAGE);
Log.i(TAG, (mFile == null) + ": ");
if (mFile == null) {
return;
}
mPreview.refreshCamera(mCamera);
mBackgroundHandler.post(new ImageUtility.ImageSaver(getApplicationContext(), data, mFile, new Callable() {
#Override
public Object call() throws Exception {
captureComplete();
return null;
}
}));
}
};
return picture;
}
View.OnClickListener captureListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mCamera != null) {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
mPicture = getPictureCallback();
mPreview.refreshCamera(camera);
camera.takePicture(null, null, mPicture);
}
});
} else {
throw new NullPointerException();
}
}
};
private void releaseCamera() {
// stop and release camera
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
if (mPreview != null) {
mPreview.setCamera(null);
}
}
}
Some changes you can do, since i had also been working on Camera api since 3 months..
In your CameraPreview Constructor, add this line
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) // add this
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
In your surfaceDestroyed() method in CameraPreview you should remove the callback right after releasing camera resources:
this.getHolder().removeCallback(this);
Besides changing the above I couldn't figure much out of your CameraActivity since you've used AutoFocus and other features.... I used FrameLayout as the container to run the preview in.

Save Android CAMERA API without INTENT

Hello i have the whole code, but i want to save the snaps automatically and release camera to back preview. I don't know how to do that :/ It's taking the snapshot but don't save neither release camera.
Thanks for the hlep guys!!
package com.velcisribeiro.xcamera;
+imports
public class MainActivity extends Activity {
private Camera cameraObject;
private ShowCamera showCamera;
private ImageView pic;
public static Camera isCameraAvailiable(){
Camera object = null;
try {
object = Camera.open();
}
catch (Exception e){
}
return object;
}
private PictureCallback capturedIt = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data .length);
if(bitmap==null){
Toast.makeText(getApplicationContext(), "not taken", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(), "taken", Toast.LENGTH_SHORT).show();
}
cameraObject.release();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
cameraObject = isCameraAvailiable();
showCamera = new ShowCamera(this, cameraObject);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(showCamera);
}
public void snapIt(View view){
cameraObject.takePicture(null, null, capturedIt);
}
}
And the other one is:
public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holdMe;
private Camera theCamera;
public ShowCamera(Context context,Camera camera) {
super(context);
theCamera = camera;
holdMe = getHolder();
holdMe.addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
theCamera.setPreviewDisplay(holder);
theCamera.setDisplayOrientation(90);
theCamera.startPreview();
} catch (IOException e) {
}
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
}
}
When I was building my own camera implementation, I just used the code provided by the Zxing library. It works really well and you can easily modify it to do what you'd like:
https://github.com/zxing/zxing
You need to add following two lines in surfaceDestroyed callback for releasing camera.
theCamera.stopPreview();
theCamera.release();
And for saving image change onPictureTaken callback.
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data .length);
if(bitmap==null){
Toast.makeText(getApplicationContext(), "not taken", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(), "taken", Toast.LENGTH_SHORT).show();
}
//Add code to save image
cameraObject.release();
}
Also have a look on following URL for better understanding.
http://androidtrainningcenter.blogspot.in/2012/01/how-to-use-android-camera-to-take.html.

Categories