Pictures are not saved in the device [closed] - android

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Improve this question
I don't know that I'm doing wrong, everyrthings seems to be ok, but no picture is being saved in the telephone when I press capture.
the message picture has being save appears, but there's nothing on my gallery.
package com.mamlambo.mirror;
import java.io.File;
import java.io.FileOutputStream;
import com.mamlambo.mirror.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;
public class MirrorActivity extends Activity implements PictureCallback {
private final static String DEBUG_TAG = "MirrorActivity";
private Camera mCam;
private MirrorView mCamPreview;
private int mCameraId = 0;
private FrameLayout mPreviewLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// do we have a camera?
if (!getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera feature on this device",
Toast.LENGTH_LONG).show();
} else {
mCameraId = findFirstFrontFacingCamera();
if (mCameraId >= 0) {
mPreviewLayout = (FrameLayout) findViewById(R.id.camPreview);
mPreviewLayout.removeAllViews();
startCameraInLayout(mPreviewLayout, mCameraId);
Button takePic = (Button) findViewById(R.id.capture);
takePic.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mCam.takePicture(null, null, MirrorActivity.this);
}
});
} else {
Toast.makeText(this, "No front facing camera found.",
Toast.LENGTH_LONG).show();
}
}
}
#SuppressLint("NewApi")
private int findFirstFrontFacingCamera() {
int foundId = -1;
// find the first front facing camera
int numCams = Camera.getNumberOfCameras();
for (int camId = 0; camId < numCams; camId++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(camId, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
Log.d(DEBUG_TAG, "Found front facing camera");
foundId = camId;
break;
}
}
return foundId;
}
private void startCameraInLayout(FrameLayout layout, int cameraId) {
// TODO pull this out of the UI thread.
mCam = Camera.open(cameraId);
if (mCam != null) {
mCamPreview = new MirrorView(this, mCam);
layout.addView(mCamPreview);
}
}
#Override
protected void onResume() {
super.onResume();
if (mCam == null && mPreviewLayout != null) {
mPreviewLayout.removeAllViews();
startCameraInLayout(mPreviewLayout, mCameraId);
}
}
#Override
protected void onPause() {
if (mCam != null) {
mCam.release();
mCam = null;
}
super.onPause();
}
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"SimpleSelfCam");
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d(DEBUG_TAG, "Can't create directory to save image");
Toast.makeText(this, "Can't make path to save pic.",
Toast.LENGTH_LONG).show();
return;
}
String filename = pictureFileDir.getPath() + File.separator
+ "latest_mug.jpg";
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(this, "Image saved as latest_mug.jpg",
Toast.LENGTH_LONG).show();
} catch (Exception error) {
Log.d(DEBUG_TAG, "File not saved: " + error.getMessage());
Toast.makeText(this, "Can't save image.", Toast.LENGTH_LONG).show();
}
}
public class MirrorView extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public MirrorView(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 {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (Exception error) {
Log.d(DEBUG_TAG,
"Error starting mPreviewLayout: " + error.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceChanged(SurfaceHolder holder, int format, int w,
int h) {
if (mHolder.getSurface() == null) {
return;
}
// can't make changes while mPreviewLayout is active
try {
mCamera.stopPreview();
} catch (Exception e) {
}
try {
// set rotation to match device orientation
setCameraDisplayOrientationAndSize();
// start up the mPreviewLayout
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception error) {
Log.d(DEBUG_TAG,
"Error starting mPreviewLayout: " + error.getMessage());
}
}
public void setCameraDisplayOrientationAndSize() {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(mCameraId, info);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int degrees = rotation * 90;
/*
* // the above is just a shorter way of doing this, but could break
* if the values change 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;
} else {
result = (info.orientation - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(result);
Camera.Size previewSize = mCam.getParameters().getPreviewSize();
if (result == 90 || result == 270) {
// swap - the physical camera itself doesn't rotate in relation
// to the screen ;)
mHolder.setFixedSize(previewSize.height, previewSize.width);
} else {
mHolder.setFixedSize(previewSize.width, previewSize.height);
}
}
}
}

Pictures do not automatically save to the gallery even if you store them to the correct file directory. To make the pictures appeare in the gallery you need to have the android MediaScanner add them. You can access the MediaScanner either by Intent or with a method/callback that will notify you when the picture has been added. Here are some examples but a seach of S/O should turn up even more results.

Related

Android Camera+Gyroscope/Accelerometer app crashing when taking a photo

I have gone through many links looking for a solution, but this is my first official app in Android. I have made other small ones like Calculator, but none like this, so I am not able to understand the advice and solutions even if i read them.
The app basically does the following :-
take in Gyroscope and Accelerometer readings
calculate angle of motion as the user moves in a circle.
take images every 10 Degrees.
The first Class works on the surface view. And the second works on taking a picture and calculating sensor readings
I have worked out the first two parts. but the third part is the problem.
Every time I take an image, the app hangs and the surface view stops working. And nothing happens. When I rotate another 10 Degrees, the app crashes.
Can someone please tell me what I am doing wrong. Thank you in advance.
package com.example.mehta.accelerometerin;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.hardware.SensorEventListener;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import static android.content.ContentValues.TAG;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
import static java.lang.Math.sqrt;
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
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 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.setDisplayOrientation(90);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
class MainActivity extends AppCompatActivity implements SensorEventListener {
private Camera mCamera;
private CameraPreview mPreview;
private SensorManager senSensorManager;
private Sensor senAccelerometer;
private Sensor senGyroscope;
private long lastUpdate = 0;
private float last_x, last_y, last_z;
private static final int SHAKE_THRESHOLD = 600;
TextView tv1, tv2, tv3, tv4, tv5;
int j = 0;
int i = 1;
int l = 10;
int m = 0;
private float xg, yg, zg, xa, ya, za;
private float x1, y1;
float x2, y2;
private float xang, yang, zang;
private float zacc;
private float xacc;
private float yacc;
private int greset;
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
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an instance of Camera
mCamera = getCameraInstance();
// 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);
greset = 0;
senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
senGyroscope = senSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
senSensorManager.registerListener(this,senAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
senSensorManager.registerListener(this,senGyroscope,SensorManager.SENSOR_DELAY_NORMAL);
}
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Toast.makeText(getApplicationContext(), "on Picture Taken", Toast.LENGTH_SHORT).show();
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " );
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
protected void onPause() {
super.onPause();
senSensorManager.unregisterListener(this);
}
protected void onResume() {
super.onResume();
senSensorManager.registerListener(this,senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
senSensorManager.registerListener(this,senGyroscope,SensorManager.SENSOR_DELAY_NORMAL);
}
public void onSensorChanged(SensorEvent sensorEvent) {
Sensor mySensor = sensorEvent.sensor;
if (mySensor.getType() == Sensor.TYPE_GYROSCOPE) {
greset ++;
zg += sensorEvent.values[1];
xg +=sensorEvent.values[0];
yg +=sensorEvent.values[2];
if(zg>30)
{
zg=0;
}
if(xg>30)
{
xg=0;
}
if(yg>30)
{
yg=0;
}
xang = xg*12;
yang = yg*12;
zang = zg*12;
if(zang>=l) {
Toast.makeText(getApplicationContext(), "click="+i, Toast.LENGTH_SHORT).show();
mCamera.stopPreview();
mCamera.takePicture(null,null,mPicture);
mCamera.startPreview();
l += 10;
i++;}
if (greset >10)
{
xg +=0.1;
greset = 0;
}
}
if(mySensor.getType()==Sensor.TYPE_ACCELEROMETER)
{
xa = sensorEvent.values[0];
za = sensorEvent.values[1];
ya = sensorEvent.values[2];
zacc = (float)(za - (((90 - xang)/ 90) * 9.8));
}
if (l > 360) {
l = 10;
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public int returnvalue(){
return(i);
}
}
Don't call stopPreview() immediately before calling takePicture(): This method is only valid when preview is active (after startPreview()). Preview will be stopped after the image is taken.
You should call startPreview() from onPictureTaken(), not immediately after calling takePicture().
Open the camera on a separate handler thread, not on the main (UI) thread.
There may be other problems with your code, but let us start with fixing these three immediate issues.

Error direclty opening activity with Camera API SurfaceView from MainActivity

I have a MainActivity which is only used if phone number is not set in Shared Preference. After setting phone number once there is no need of MainActivity and everytime user opens app he should goto CameraActivity Activity which have Camera API working in SurfaceView in it.
There is no problem in opening CameraActivity using button on MainActivity but if I open CameraActivity from MainACtivity onCreate method then I am facing following Error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setDisplayOrientation(int)' on a null object reference
at com.vivertechnologies.camera.ShowCamera.refreshCamera(ShowCamera.java:208)
at com.vivertechnologies.camera.ShowCamera.surfaceChanged(ShowCamera.java:281)
at android.view.SurfaceView.updateWindow(SurfaceView.java:590)
at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:176)
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1983)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1081)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5818)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5234)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
My Code from Camera API is:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_show);
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// update TextView here!
Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String formattedDate = df.format(c.getTime());
TextView txtView = (TextView)findViewById(R.id.dateTime);
txtView.setText(formattedDate);
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
jpegCallback = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
new Thread(new SavePicThread(data)).start();
//
// Intent i = new Intent(ShowCamera.this, UploadActivity.class);
// i.putExtra("isImage", data);
// startActivity(i);
refreshCamera();
}
};
}
Refresh Camera Method which is generating error:
public void refreshCamera() {
if (surfaceHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
int rotation = ((WindowManager)ShowCamera.this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int degrees = 0;
// specifically for back facing camera
switch (rotation) {
case Surface.ROTATION_0:
degrees = 90;
break;
case Surface.ROTATION_90:
degrees = 0;
break;
case Surface.ROTATION_180:
degrees = 270;
break;
case Surface.ROTATION_270:
degrees = 180;
break;
}
camera.setDisplayOrientation(degrees);
setCamera(camera);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
Log.d("AAAAA", "Error starting camera preview: " + e.getMessage());
}
}
I am unable to identify how it can be solved.
Edit:
Complete Code:
package com.vivertechnologies.camera;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* Created by usman on 27/11/15.
*/
public class ShowCamera extends MainActivity implements SurfaceHolder.Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Camera.PictureCallback rawCallback;
Camera.ShutterCallback shutterCallback;
Camera.PictureCallback jpegCallback;
private Camera.Size mPreviewSize;
private List<Camera.Size> mSupportedPreviewSizes;
private Context mContext;
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
private final String TAG = "CameraSurfaceView";
private Camera mCamera;
private List<String> mSupportedFlashModes;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_show);
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// update TextView here!
Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String formattedDate = df.format(c.getTime());
TextView txtView = (TextView)findViewById(R.id.dateTime);
txtView.setText(formattedDate);
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
jpegCallback = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
new Thread(new SavePicThread(data)).start();
//
// Intent i = new Intent(ShowCamera.this, UploadActivity.class);
// i.putExtra("isImage", data);
// startActivity(i);
refreshCamera();
}
};
}
private void galleryAddPic(File file) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(file);
mediaScanIntent.setData(contentUri);
ShowCamera.this.sendBroadcast(mediaScanIntent);
}
public class SavePicThread implements Runnable {
byte[] data;
public SavePicThread(byte[] data) {
this.data = data;
}
public void run() {
// make a new picture file
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
// write to the file
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.flush();
fos.close();
ShowCamera.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// Toast toast = Toast.makeText(ShowCamera.this, "Picture saved", Toast.LENGTH_SHORT);
// toast.show();
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// make the picture visible to the rest of the device
galleryAddPic(pictureFile);
Intent i = new Intent(ShowCamera.this, UploadActivity.class);
i.putExtra("filePath", pictureFile.getPath());
startActivity(i);
}
}
// make picture and save to a folder
private File getOutputMediaFile() {
// make a new file directory inside the "sdcard" folder
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "imgCaptureApp");
// if the directory does not exist
if (!mediaStorageDir.exists()) {
// if you cannot make this directory return
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
// take the current timeStamp
String timeStamp = new SimpleDateFormat("dd-MM-yyyy_HH:mm:ss").format(new Date());
File mediaFile;
// and make a media file:
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
public void captureImage(View v) throws IOException {
camera.takePicture(null, null, jpegCallback);
}
public void refreshCamera() {
if (surfaceHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
int rotation = ((WindowManager)ShowCamera.this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int degrees = 0;
// specifically for back facing camera
switch (rotation) {
case Surface.ROTATION_0:
degrees = 90;
break;
case Surface.ROTATION_90:
degrees = 0;
break;
case Surface.ROTATION_180:
degrees = 270;
break;
case Surface.ROTATION_270:
degrees = 180;
break;
}
camera.setDisplayOrientation(degrees);
setCamera(camera);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
Log.d("AAAAA", "Error starting camera preview: " + e.getMessage());
}
}
public void setCamera(Camera camera)
{
Camera mCamera = camera;
if (mCamera != null)
{
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
// Set the camera to Auto Flash mode.
if (mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO))
{
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
mCamera.setParameters(parameters);
}
}
surfaceView.requestLayout();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();
}
catch (RuntimeException e) {
System.err.println(e);
return;
}
Camera.Parameters param;
param = camera.getParameters();
List<Camera.Size> sizes = param.getSupportedPictureSizes();
Camera.Size size = sizes.get(0);
for(int i=0;i<sizes.size();i++)
{
if(sizes.get(i).width > size.width)
size = sizes.get(i);
}
param.setPictureSize(size.width, size.height);
param.setRotation(90);
param.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
// param.setPreviewSize(352, 288);
camera.setParameters(param);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
}
catch (Exception e) {
System.err.println(e);
return;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
refreshCamera();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
}
From your description, your problem appears to be that ShowCamera is a subclass of MainActivity. Presumably, you have something similar to the following in MainActivity's onCreate() method:
SharedPreferences prefs = ...
if(prefs.getBoolean("phone_number_set", false)) {
startActivity(new Intent(this, ShowCamera.class));
}
Since ShowCamera is a subclass of MainActivity, calling super.onCreate(savedInstanceState); in ShowCamera's onCreate() method is executing MainActivity's onCreate() method again. When you open ShowCamera with the Button, you've not yet set the phone number, so the if conditional shown above is false, and the startActivity() method doesn't get called again.
However, after you've set the phone number, the conditional is true, and it starts ShowCamera again, which is calling MainActivity's onCreate(), which executes the if block, which starts ShowCamera, which calls MainActivity's onCreate(), which executes the if block, which starts ShowCamera... This is easily verified by adding a static int to the ShowCamera class, printing it to the Log in onCreate(), and then immediately incrementing it.
Eventually, one of the ShowCamera instances will layout its SurfaceView and call refreshCamera() from the surfaceChanged() callback, but it will have a null Camera object, because a previous Activity already has the camera.open, and it will throw the NullPointerException you're getting.
The solution is simple. Change the ShowCamera class to be a direct subclass of Activity. That is:
public class ShowCamera extends Activity implements SurfaceHolder.Callback {

How do I get back to the Viewfinder of the Camera after taking a picture?

I am making a Camera example on Android, currently it just takes a picture and saves it on the device's (internal) memory.
After taking a picture, the screen stays frozen on the last clicked picture and I have to exit the app and open it again to take another picture.
Here is my code:
MainActivity.java:
package com.example.camera;
import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.Surface;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends Activity
{
private Camera mCamera;
private ShowCamera showCamera;
public Camera isCameraAvailable()
{
Camera camera=null;
Log.d("isCameraAvailable","Camera object set to null.");
try
{
camera = Camera.open();
Log.d("isCameraAvailable","Camera opened.");
}
catch (Exception e)
{
Log.d("isCameraAvailable",e.toString());
}
return camera;
}
private static File getOutputMediaFile()
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"com.example.camera");
if (!mediaStorageDir.exists())
{
if (!mediaStorageDir.mkdirs())
{
Log.d("getOutputMediaFile","Failed to create directory.");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator+ "IMG_" + timeStamp + ".jpg");
Log.d("getOutputMediaFile","Filename created.");
return mediaFile;
}
private PictureCallback capturedIt = new PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
File pictureFile = getOutputMediaFile();
if (pictureFile == null)
{
Log.d("onPictureTaken","pictureFile=null");
return;
}
try
{
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
Log.d("onPictureTaken","File written.");
fos.close();
Log.d("onPictureTaken","File closed.");
Toast.makeText(MainActivity.this,pictureFile.toString()+" saved!", Toast.LENGTH_LONG).show();
return;
}
catch (FileNotFoundException e)
{
Log.e("onPictureTaken",e.toString());
}
catch (IOException e)
{
Log.d("onPictureTaken",e.toString());
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCamera = isCameraAvailable();
setCameraDisplayOrientation(this,0,mCamera);
Log.d("onCreate","Camera instance taken.");
showCamera = new ShowCamera(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.flCameraPreview);
preview.addView(showCamera);
Log.d("onCreate","Camera view in initialized");
preview.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
mCamera.takePicture(null, null, capturedIt);
Log.d("onClick","Button Clicked.");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
public static void setCameraDisplayOrientation(Activity activity,int cameraId, android.hardware.Camera camera)
{
android.hardware.Camera.CameraInfo info=new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId,info);
int rotation = activity.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;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
}
else
{
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
}
ShowCamera.java:
package com.example.camera;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder holdMe;
private Camera mCamera;
public ShowCamera(Context context,Camera camera)
{
super(context);
this.mCamera = camera;
this.holdMe = getHolder();
this.holdMe.addCallback(this);
this.holdMe.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format,int width, int height)
{
try
{
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
}
catch (Exception e)
{
Log.d("surfaceChanged",e.toString());
}
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
try
{
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
catch (IOException e)
{
Log.e("surfaceCreated",e.toString());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder)
{
mCamera.stopPreview();
mCamera.release();
}
}
After taking a picture and saving it to memory, if I click the screen once more, the app crashes.
You have stopPreview in surfaceDestroyed. but when it cames back. you have to restart the Camera in onResume . which is missing
public void onResume()
{
mCamera = getCameraInstance(); // i have created this i
// static method here
//mCamera.setPreviewCallback(previewCallback);//it depends on you need
try
{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
catch (IOException ioexception)
{
Log.e("MyCamera",
(new StringBuilder()).append("PreviewDisplay Error => ")
.append(ioexception.getMessage()).toString());
}
}
And
public static Camera getCameraInstance()
{
Camera camera1;
try
{
if (android.os.Build.VERSION.SDK_INT >= 9)
{
return Camera.open(cameraId);
}
camera1 = Camera.open();
}
catch (Exception exception)
{
Log.e("NightVision",
(new StringBuilder()).append("ErrorCameraInit: ")
.append(exception.getMessage()).toString());
return null;
}
return camera1;
}

android video recording with duration limit and low quality

I need to record video for 8 seconds in my app. I am using MediaStore.ACTION_VIDEO_CAPTURE intent for video recording and using these parameters (MediaStore.EXTRA_VIDEO_QUALITY,MediaStore.EXTRA_DURATION_LIMIT) to set quality and duration limit of video recording. but i encountered a very interesting bug i.e. when i set duration limit to 8 seconds and video quality to 1, its working fine and is recording video for 8 seconds but as soon i changes the video quality to 0 and keeping everything same, the video is now recorded for 21 seconds. I am using sony Xperia phone for testing, but when i shift to HTC, duration limit not working in any case neither on setting video quality to 1 nor on setting it to 0.
So i don't know what is happening right now. In severe need. please help. Thanks in advance.
Here is the code I am using..
private void recordVideo() {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
File f = null;
try {
f = setUpVideoFile();
filePath = f.getAbsolutePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
} catch (IOException e) {
e.printStackTrace();
f = null;
filePath = null;
}
objectGlobal.setFilepath(filePath);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 8);
startActivityForResult(intent, CAMERA_CAPTURE_VIDEO);
}
I know its bit late to answer this question, but i think i have to, so that if others are facing this problem, they can easily deal with it.
Actually the problem is when you lower the video quality via this
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
the camera intent no longer works as a video recorder. It actually creates a mms when we try lowering the quality. As far as time is concerned, I don't know whether it is a bug in Android or may be some memory constraints. So the solution I adopted is to make custom video recording class using SurfaceView.
So I am pasting the code of Video Recording from one of my projects.Also the video recorded is almost playable in all android/iOS devices, i have tested so far. Here is my Video Recording Class
package com.mukesh.videorecordingsample;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class RecordVideoPostsActivity extends Activity implements
SurfaceHolder.Callback, OnClickListener {
protected static final int RESULT_ERROR = 0x00000001;
private static final int MAX_VIDEO_DURATION = 8 * 1000;
private static final int ID_TIME_COUNT = 0x1006;
private SurfaceView mSurfaceView;
private ImageView iv_cancel, iv_ok, iv_record;
private TextView tv_counter;
private SurfaceHolder mSurfaceHolder;
private MediaRecorder mMediaRecorder;
private Camera mCamera;
private List<Size> mSupportVideoSizes;
private String filePath;
private boolean mIsRecording = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_recordvideo);
initView();
}
private void initView() {
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
iv_record = (ImageView) findViewById(R.id.iv_record);
iv_cancel = (ImageView) findViewById(R.id.iv_cancel);
iv_ok = (ImageView) findViewById(R.id.iv_ok);
iv_record.setImageResource(R.drawable.btn_video_start);
tv_counter = (TextView) findViewById(R.id.timer);
tv_counter.setVisibility(View.GONE);
iv_cancel.setOnClickListener(this);
iv_ok.setOnClickListener(this);
iv_record.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
private void exit(final int resultCode, final Intent data) {
if (mIsRecording) {
new AlertDialog.Builder(RecordVideoPostsActivity.this)
.setTitle("Video Recorder")
.setMessage("Do you want to exit?")
.setPositiveButton("yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
stopRecord();
if (resultCode == RESULT_CANCELED) {
if (filePath != null)
deleteFile(new File(filePath));
}
setResult(resultCode, data);
finish();
}
})
.setNegativeButton("no",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
}
}).show();
return;
}
if (resultCode == RESULT_CANCELED) {
if (filePath != null)
deleteFile(new File(filePath));
}
setResult(resultCode, data);
finish();
}
private void deleteFile(File delFile) {
if (delFile == null) {
return;
}
final File file = new File(delFile.getAbsolutePath());
delFile = null;
new Thread() {
#Override
public void run() {
super.run();
if (file.exists()) {
file.delete();
}
}
}.start();
}
private Handler mHandler = new Handler() {
#Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ID_TIME_COUNT:
if (mIsRecording) {
if (msg.arg1 > msg.arg2) {
// mTvTimeCount.setVisibility(View.INVISIBLE);
tv_counter.setText("00:00");
stopRecord();
} else {
tv_counter.setText("00:0" + (msg.arg2 - msg.arg1));
Message msg2 = mHandler.obtainMessage(ID_TIME_COUNT,
msg.arg1 + 1, msg.arg2);
mHandler.sendMessageDelayed(msg2, 1000);
}
}
break;
default:
break;
}
}
;
};
private void openCamera() {
try {
this.mCamera = Camera.open();
Camera.Parameters parameters = mCamera.getParameters();
parameters.setRotation(90);
System.out.println(parameters.flatten());
parameters.set("orientation", "portrait");
mCamera.setParameters(parameters);
mCamera.lock();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
try {
mCamera.setDisplayOrientation(90);
} catch (NoSuchMethodError e) {
e.printStackTrace();
}
}
mSupportVideoSizes = parameters.getSupportedVideoSizes();
if (mSupportVideoSizes == null || mSupportVideoSizes.isEmpty()) {
String videoSize = parameters.get("video-size");
Log.i(EmBazaarConstants.APP_NAME, videoSize);
mSupportVideoSizes = new ArrayList<Camera.Size>();
if (!RecordVideoPostsActivity.isEmpty(videoSize)) {
String[] size = videoSize.split("x");
if (size.length > 1) {
try {
int width = Integer.parseInt(size[0]);
int height = Integer.parseInt(size[1]);
mSupportVideoSizes.add(mCamera.new Size(width,
height));
} catch (Exception e) {
Log.e(EmBazaarConstants.APP_NAME, e.toString());
}
}
}
}
for (Size size : mSupportVideoSizes) {
Log.i(EmBazaarConstants.APP_NAME, size.width + "<>" + size.height);
}
} catch (Exception e) {
Log.e(EmBazaarConstants.APP_NAME, "Open Camera error\n" + e.toString());
}
}
private boolean initVideoRecorder() {
if (mCamera == null) {
mCamera = Camera.open();
mCamera.unlock();
} else {
mCamera.unlock();
}
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
} catch (Exception e) {
e.printStackTrace();
}
try {
CamcorderProfile lowProfile = CamcorderProfile
.get(CamcorderProfile.QUALITY_LOW);
CamcorderProfile hightProfile = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
if (lowProfile != null && hightProfile != null) {
lowProfile.audioCodec = MediaRecorder.AudioEncoder.AAC;
lowProfile.duration = hightProfile.duration;
lowProfile.videoCodec = MediaRecorder.VideoEncoder.H264;
lowProfile.videoFrameRate = hightProfile.videoFrameRate;
lowProfile.videoBitRate = 1500000 > hightProfile.videoBitRate ? hightProfile.videoBitRate
: 1500000;
if (mSupportVideoSizes != null && !mSupportVideoSizes.isEmpty()) {
int width = 640;
int height = 480;
Collections.sort(mSupportVideoSizes, new SizeComparator());
int lwd = mSupportVideoSizes.get(0).width;
for (Size size : mSupportVideoSizes) {
int wd = Math.abs(size.width - 640);
if (wd < lwd) {
width = size.width;
height = size.height;
lwd = wd;
} else {
break;
}
}
lowProfile.videoFrameWidth = width;
lowProfile.videoFrameHeight = height;
}
mMediaRecorder.setProfile(lowProfile);
}
} catch (Exception e) {
try {
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
} catch (Exception ex) {
ex.printStackTrace();
}
try {
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
} catch (Exception ex) {
ex.printStackTrace();
}
if (mSupportVideoSizes != null && !mSupportVideoSizes.isEmpty()) {
Collections.sort(mSupportVideoSizes, new SizeComparator());
Size size = mSupportVideoSizes.get(0);
try {
mMediaRecorder.setVideoSize(size.width, size.height);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
try {
mMediaRecorder.setVideoSize(640, 480);
} catch (Exception ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
}
File f = null;
try {
f = setUpVideoFile();
filePath = f.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
f = null;
filePath = null;
}
mMediaRecorder.setOutputFile(filePath);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
try {
mMediaRecorder.setOrientationHint(90);
} catch (NoSuchMethodError e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d("VideoPreview",
"IllegalStateException preparing MediaRecorder: "
+ e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d("VideoPreview",
"IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (Exception e) {
releaseMediaRecorder();
e.printStackTrace();
}
return true;
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
mCamera.lock();
}
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
private void startRecord() {
try {
if (initVideoRecorder()) {
mMediaRecorder.start();
iv_record.setImageResource(R.drawable.btn_video_stop);
} else {
releaseMediaRecorder();
iv_record.setImageResource(R.drawable.btn_video_start);
}
tv_counter.setVisibility(View.VISIBLE);
tv_counter.setText("00:0" + (MAX_VIDEO_DURATION / 1000));
Message msg = mHandler.obtainMessage(ID_TIME_COUNT, 1,
MAX_VIDEO_DURATION / 1000);
mHandler.sendMessage(msg);
mIsRecording = true;
} catch (Exception e) {
showShortToast("problem while capturing video");
e.printStackTrace();
exit(RESULT_ERROR, null);
}
}
private void stopRecord() {
try {
mMediaRecorder.stop();
} catch (Exception e) {
if (new File(filePath) != null
&& new File(filePath).exists()) {
new File(filePath).delete();
}
}
releaseMediaRecorder();
mCamera.lock();
iv_record.setImageResource(R.drawable.btn_video_start);
mIsRecording = false;
iv_record.setVisibility(View.GONE);
iv_cancel.setVisibility(View.VISIBLE);
iv_ok.setVisibility(View.VISIBLE);
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo(); // Since API level 9
Camera.getCameraInfo(cameraId, info);
int rotation = activity.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;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
#Override
protected void onResume() {
super.onResume();
openCamera();
}
#Override
protected void onPause() {
super.onPause();
releaseCamera();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (Exception e) {
}
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
try {
mCamera.stopPreview();
} catch (Exception e) {
}
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit(RESULT_CANCELED, null);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.iv_ok:
Intent data = new Intent();
if (filePath != null) {
data.putExtra("videopath", filePath);
}
exit(RESULT_OK, data);
break;
case R.id.iv_cancel:
exit(RESULT_CANCELED, null);
break;
case R.id.iv_record:
if (mIsRecording) {
stopRecord();
} else {
startRecord();
}
break;
default:
break;
}
}
protected void showShortToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
private File setUpVideoFile() throws IOException {
File videoFile = null;
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
File storageDir = new File(
EmBazaarConstants.LOCAL_STORAGE_BASE_PATH_FOR_POSTED_VIDEOS)
.getParentFile();
if (storageDir != null) {
if (!storageDir.mkdirs()) {
if (!storageDir.exists()) {
Log.d("CameraSample", "failed to create directory");
return null;
}
}
}
videoFile = File.createTempFile(EmBazaarConstants.MP4_FILE_PREFIX
+ System.currentTimeMillis() + "_",
EmBazaarConstants.MP4_FILE_SUFIX, storageDir);
} else {
Log.v(getString(R.string.app_name),
"External storage is not mounted READ/WRITE.");
}
return videoFile;
}
private class SizeComparator implements Comparator<Size> {
#Override
public int compare(Size lhs, Size rhs) {
return rhs.width - lhs.width;
}
}
public static boolean isEmpty(String str) {
return str == null || "".equals(str.trim());
}
}
and you can simply call this class in your Activity like this
if (isDeviceSupportCamera()) {
startActivityForResult(new Intent(PostStatusActivity.this,
yourActivity.class),
EmBazaarConstants.CAMERA_CAPTURE_VIDEO);
} else {
Toast.makeText(this, "Your device doesn't support camera",
Toast.LENGTH_LONG).show();
}
and here is isDeviceSupportCamera() function
private boolean isDeviceSupportCamera() {
if (getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
In your onActivityResult, you have to write this code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == EmBazaarConstants.CAMERA_CAPTURE_VIDEO
&& resultCode == RESULT_OK) {
if (data != null && data.getStringExtra("videopath") != null)
videoFilePath= data.getStringExtra("videopath");
}
}
Hope this helps.
** Although we have new Camera2 APIs in android lollipop, but this code still works in android lollipop as well.But still you can change to new Camera2 APIs,if you want.

GetCameraDisplayOrientation returns always 0

I'm trying to record a video in the correct orientation in Android. I've built my Activity, it works correctly, the only thing is that the saved video after being recorded is rotated. The preview of the camera works correctly so I can't understand why. To fix the rotation I use this code (the method I've found on Google Developers):
mMediaRecorder.setOrientationHint(getCameraDisplayOrientation());
private int getCameraDisplayOrientation()
{
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(CameraInfo.CAMERA_FACING_BACK,
info);
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;
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;
}
return result;
The Activity is defined in the manifest like that:
<activity android:name="pages.CameraPage"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="landscape"
>
</activity>
The problem is that getCameraDisplayOrientation always returns 0 degrees, no matter how I orient the screen.
I call the method just before the record starts so if I would be able to get the rotation of the screen with respect to the default landscape I'd be ok.
Thanks for your help!
Finally I was able to build successfully my own camera app without any orientation problem. The key was looking at the surfaceView for the rotation. I think it might help someone to have all the code posted here, just copy it and launch the Activity!
CameraPage.java
package pages;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import model.CameraView;
import com.controller.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.Toast;
public class CameraPage extends Activity
{
private Camera mCamera;
private CameraView mPreview;
private MediaRecorder mMediaRecorder;
private FrameLayout preview;
private ImageButton buttonRecordStop;
private boolean isRecording = false;
private String fileName;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Log.d("CameraPage-onCreate", "Called onCreate()");
setContentView(R.layout.camera_surface);
buttonRecordStop = (ImageButton) findViewById(R.id.camera_surface_buttonRecordStop);
buttonRecordStop.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN
|| event.getAction() == MotionEvent.ACTION_MOVE)
{
AlphaAnimation alpha = new AlphaAnimation(1.0F, 0.3F);
alpha.setDuration(100);
alpha.setFillAfter(true); // Tell it to persist after the animation ends
buttonRecordStop.startAnimation(alpha);
} else if (event.getAction() == MotionEvent.ACTION_UP
|| event.getAction() == MotionEvent.ACTION_CANCEL)
{
AlphaAnimation alpha = new AlphaAnimation(0.3F, 1.0F);
alpha.setDuration(100);
alpha.setFillAfter(true); // Tell it to persist after the animation ends
buttonRecordStop.startAnimation(alpha);
}
return false;
}
});
buttonRecordStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
if (!isRecording)
{
Log.d("CameraPage-buttonRecordStop-onClick", "Start Record");
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// initialize video camera
if (prepareVideoRecorder())
{
v.setVisibility(View.GONE);
((ImageButton) v)
.setImageResource(R.drawable.iconapause);
v.setVisibility(View.VISIBLE);
isRecording = true;
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
} else
{
// prepare didn't work, release the camera
releaseMediaRecorder();
// inform user
}
} else
{
Log.d("CameraPage-buttonRecordStop-onClick", "Stop Record");
getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
v.setVisibility(View.GONE);
((ImageButton) v).setImageResource(R.drawable.iconarecord);
v.setVisibility(View.VISIBLE);
isRecording = false;
stopRecording();
sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
}
}// end onClick
});
mCamera = getCameraInstance();
preview = (FrameLayout) findViewById(R.id.camera_preview);
}// end onCreate
#Override
protected void onResume()
{
super.onResume();
Log.d("CameraPage-onResume",
"Chiamato onResume ripristino le risorse se necessario");
if (mCamera == null)
{
// Create an instance of Camera
mCamera = getCameraInstance();
}
if (mPreview == null)
{
mPreview = new CameraView(getApplicationContext(), mCamera, this);
preview.addView(mPreview);
}
}
#Override
protected void onPause()
{
super.onPause();
Log.d("CameraPage-onPause", "Vado in onPause e rilascio le risorse");
releaseMediaRecorder(); // if you are using MediaRecorder, release it first
releaseCamera(); // release the camera immediately on pause event
preview.removeView(mPreview);
mPreview = null;
}
private void stopRecording()
{
mMediaRecorder.stop();
releaseMediaRecorder();
// Restarto la preview della camera
mCamera.startPreview();
// mCamera.lock();
}
private boolean prepareVideoRecorder()
{
// mCamera = getCameraInstance();
mMediaRecorder = new MediaRecorder();
// Stop preview because I have to start the preview for the video
mCamera.stopPreview();
// 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)
mMediaRecorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH));
// Step 4: Set output file
setOutputFile();
mMediaRecorder.setOutputFile(getOutputFile());
// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
mMediaRecorder.setOrientationHint(CameraPage
.getCameraDisplayOrientation(this,
Camera.CameraInfo.CAMERA_FACING_BACK, mCamera));
// Step 6: Prepare configured MediaRecorder
try
{
mMediaRecorder.prepare();
} catch (IllegalStateException e)
{
Log.d("CameraPage-prepareVideoRecorder",
"IllegalStateException preparing MediaRecorder: "
+ e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e)
{
Log.d("CameraPage-prepareVideoRecorder",
"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 (mCamera != null)
{
mCamera.release(); // release the camera for other applications
mCamera = null;
}
if (mPreview != null)
mPreview.getHolder().removeCallback(mPreview);
}
/** A safe way to get an instance of the Camera object. */
private Camera getCameraInstance()
{
Camera c = null;
try
{
Log.d("CameraPage-getCameraInstance", "Prendo istanza camera");
c = Camera.open(); // attempt to get a Camera instance
} catch (Exception e)
{
// Camera is not available (in use or does not exist)
Log.d("CameraPage-getCameraInstance",
"Eccezione durante retrieve istanza camera " + e);
}
return c; // returns null if camera is unavailable
}
#SuppressLint("SimpleDateFormat")
private void setOutputFile()
{
String folderPath = Environment.getExternalStorageDirectory().getPath();
File vims = new File(folderPath + "/ViMS");
if (!vims.exists())
vims.mkdir();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd---HH-mm-ss");
Date date = new Date();
String timestamp = "/" + dateFormat.format(date) + ".mp4";
Log.d("CameraPage-getOutputFile", Environment
.getExternalStorageDirectory().getPath());
fileName = vims.getPath() + timestamp;
}
private String getOutputFile()
{
return fileName;
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera)
{
int result = CameraPage.getCameraDisplayOrientation(activity, cameraId,
camera);
if (android.os.Build.VERSION.SDK_INT <= 14)
{
camera.stopPreview();
camera.setDisplayOrientation(result);
camera.startPreview();
} else
{
camera.setDisplayOrientation(result);
}
}// end setCameraDisplayOrientation
public static int getCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera)
{
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.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;
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;
}
return result;
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.d("CameraPage-onDestroy", "Called onDestroy");
}
}// end CameraPage
CameraView.java
package model;
import java.io.IOException;
import pages.CameraPage;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/** A basic Camera preview class */
public class CameraView extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder mHolder;
private Camera mCamera;
private Activity activity;
public CameraView(Context context)
{
super(context);
Log.d("CameraView-default constructor",
"Chiamato uno dei due default constructors");
}
public CameraView(Context context, AttributeSet attrs)
{
super(context, attrs);
Log.d("CameraView-default constructor",
"Chiamato uno dei due default constructors");
}
public CameraView(Context context, Camera camera, Activity activity)
{
super(context);
Log.d("CameraView-constructor",
"Inizializzo la classe con la camera e il context");
this.activity = activity;
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)
{
Log.d("CameraView-surfaceCreated",
"La superfice è stata creata, setto la preview della camera sulla superficie");
// 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-surfaceCreated", "Error setting camera preview: "
+ e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.d("CameraView-surfaceDestroyed",
"Distrutta superficie della preview");
// Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.d("CameraView-surfaceChanged",
"Gestisco i cambiamenti nella superficie che ospita la camera");
// 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
Log.d("CameraView-surfaceChanged", "Preview surface doesn't exist");
return;
}
try
{
CameraPage.setCameraDisplayOrientation(activity,
Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
} catch (Exception e)
{
Log.d("CameraView-surfaceChanged",
"Exception reorienting the camera " + e);
}
}// end surfaceChanged
}// end CameraView
camera_surface.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
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" >
</FrameLayout>
<ImageButton
android:id="#+id/camera_surface_buttonRecordStop"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:adjustViewBounds="true"
android:background="#null"
android:contentDescription="#string/action"
android:scaleType="fitCenter"
android:src="#drawable/iconarecord" />
</RelativeLayout>
The Activity has been tested from Android 2.3.6 to 4.3. If you find any problem or have any suggestion please let me know!
If your issue is associated with your rotation variable, you may consider looking at this link. The main difference to pull away from that link is a WindowManager object is created and then used to get the rotation. This seemingly small difference has been the difference maker between a piece of my code working and not working.
You can simply say Camera.CameraInfo info = new Camera.CameraInfo(); and Camera.getCameraInfo(...);.
I am curious as to why you are specifying CameraInfo.CAMERA_FACING_BACK in android.hardware.Camera.getCameraInfo(CameraInfo.CAMERA_FACING_BACK, info); I feel like you could just call info.facing to get the int instead.
I hope between the link and my suggestions/inquiries that something sparks the correct answer!

Categories

Resources