I am using Camera feature in my app. Everything works fine but when the device gets locked/sleep, upon returning to the app the camera portion(SurfaceView) is just black. Below is my code. Can someone please identify the problem?
public class Activity_Camera extends Activity implements SurfaceHolder.Callback, Camera.AutoFocusCallback, Observer
{
// Surface vars
private SurfaceView preview;
private SurfaceHolder previewHolder;
// Camera vars
private Camera mCamera;
private boolean mPreviewRunning = false;
private boolean mCaptureFrame = false;
private int frame_number = 1;
private byte[] frame = new byte[1];
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview = (SurfaceView) findViewById(R.id.preview);
previewHolder = preview.getHolder();
previewHolder.addCallback(this);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onPause()
{
super.onPause();
if (mPreviewRunning)
{
mCamera.stopPreview();
mPreviewRunning = false;
}
mCamera.setPreviewCallback(null);
mCamera.release();
}
// implements SurfaceHolder.Callback
public void surfaceCreated(SurfaceHolder holder)
{
mCamera = Camera.open();
}
// implements SurfaceHolder.Callback
public void surfaceDestroyed(SurfaceHolder holder)
{
mPreviewRunning = false;
}
// implements Camera.AutoFocusCallback
public void onAutoFocus(boolean success, Camera camera)
{
}
PreviewCallback previewCallback = new PreviewCallback()
{
public void onPreviewFrame(byte[] data, Camera camera)
{
}
};
// implements SurfaceHolder.Callback
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (mPreviewRunning)
{
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(640, 480);
mCamera.setParameters(p);
try
{
mCamera.setPreviewDisplay(holder);
} catch (IOException e)
{
e.printStackTrace();
}
mCamera.setPreviewCallback(previewCallback);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
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;
}
Log.i("DEGREES ARE WHAT??", Integer.toString(degrees));
// mCamera.setDisplayOrientation(degrees);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
mPreviewRunning = true;
}
// implements Observer
// captures a frame when the compass listener says it is appropriate
public void update(Observable observable, Object data)
{
mCaptureFrame = true;
}
}
Please identify the issue, as I suspect something wrong with onPause(), it also gives me exception when I press back button after the black camera screen:
java.lang.RuntimeException: Method called after release()
on this line:
mCamera.setPreviewCallback(null); // (in onPause())
Here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#E6E5E6">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal">
<TextView
android:id="#+id/tv_camera_url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textColor="#android:color/black"
android:text="URL goes here........"
android:layout_marginTop="3dp"
android:textStyle="bold"/>
<TextView
android:id="#+id/tv_speaknow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:background="#ffffff"
android:layout_marginTop="3dp"
android:text="Speak Now"
android:textColor="#ff0000"
android:textStyle="bold"/>
</LinearLayout>
<RelativeLayout
android:id="#+id/rl_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<SurfaceView
android:id="#+id/preview"
android:layout_width="480px"
android:layout_height="640px"
android:layout_alignParentBottom="true"/>
<Button
android:id="#+id/btn_take_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/camera"
android:layout_alignBottom="#+id/preview"
android:layout_centerHorizontal="true"
android:layout_marginBottom="5dp"/>
</RelativeLayout>
</LinearLayout>
If its the first time you are launching the app, the onPause really shouldn't be the problem.
But I'd move down the creation and such to onResume instead of onCreate.
And can i see your xml of the surfaceview?
Do you just want 1 picture?
if (mPreviewRunning)
{
mCamera.stopPreview();
}
And most people startPreview from onResume. try to move it up there..
Related
I wrote a class for camera preview
public class CameraView extends SurfaceView implements SurfaceHolder.Callback{
private Camera camera;
public CameraView(Context context) {
super(context);
getHolder().addCallback(this);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera){
Camera.CameraInfo info = new Camera.CameraInfo();
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
public void surfaceCreated(SurfaceHolder surfaceHolder) {
camera = Camera.open();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
setCameraDisplayOrientation((Activity)getContext(), Camera.CameraInfo.CAMERA_FACING_BACK, camera);
Camera.Parameters parameters = camera.getParameters();
Camera.Size bestSize = null;
for (Camera.Size size : parameters.getSupportedPictureSizes()){
if (size.width <= i1 && size.height <=i2) {
if (bestSize == null) {
bestSize = size;
} else {
int bestArea = bestSize.width * bestSize.height;
int newArea = size.width * size.height;
if (newArea > bestArea){
bestSize = size;
}
}
}
}
parameters.setPictureSize(bestSize.width, bestSize.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.setParameters(parameters);
try{
camera.setPreviewDisplay(surfaceHolder);
}catch (IOException e){
e.printStackTrace();
}
camera.startPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
camera.stopPreview();
camera.release();
camera = null;
}
}
And then I wrote a layout file and I want to display the preview in the "SurfaceView"
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/camera_view" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_alignParentBottom="true"
android:weightSum="1">
<Button
android:id="#+id/stop_navigation"
android:layout_weight="0.5"
android:layout_height="32dp"
android:layout_width="0dp"
android:text="#string/stop_navigation"
android:textColor="#color/colorWhite"
android:textSize="12sp"
android:background="#color/colorAccent" />
</LinearLayout>
</RelativeLayout>
So how should I do in the main activity? Before I just did the below code and everything is fine.
CameraView cameraView = new CameraView(this);
addContentView(cameraView, new ActionBar.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT));
But now I need to put the preview into the layout I design.
Use FrameLayout and add CameraPreview to it.
// 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);
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
try this:
You need to Change in your SurfaceView in XML File.
Replace your surfaceView with this
<CameraView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/camera_view" />
and your remaining code is Right.let me know after change
Hope this will helps...(:
At first you should add the camera permission in you Manifest.xml :
android:name="android.permission.CAMERA
And, add this in your activity :
#Override
protected void onResume() {
super.onResume();
mCameraView.start();
}
#Override
protected void onPause() {
mCameraView.stop();
super.onPause();
}
Check this link, it's the easiest way to do it :
https://github.com/google/cameraview
I have some frames in my SD card.
There is list of frames in my activity.
Now when user click on frame, Camera preview will be displayed through that frame.
Please see image.
How can I archive this functionality ?
I searched about this but didn't get proper example.
You have to create your own Preview by extending the SurfaceView class.
Take FrameLayout with SurfaceView as child.and customise as per your needs
You can use SurfaceView and create a CustomView that will open the camera and you can adjust its size in the xml accordingly.
Create a class that extends SurfaceView and open camera inside that
CustomPreview.java
public class CustomPreview extends SurfaceView implements SurfaceHolder.Callback{
public static Bitmap mBitmap;
SurfaceHolder holder;
static Camera mCamera;
public CustomPreview(Context context, AttributeSet attrs) {
super(context, attrs);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.getSupportedPreviewSizes();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
mCamera.setPreviewDisplay(holder);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
}
/***
*
* Take a picture and and convert it from bytes[] to Bitmap.
*
*/
public static void takeAPicture(){
Camera.PictureCallback mPictureCallback = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
BitmapFactory.Options options = new BitmapFactory.Options();
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
};
mCamera.takePicture(null, null, mPictureCallback);
}
}
Now you can add this custom view in your XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="#+id/mySurfaceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.mjl.CustomPreview
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</com.mjl.CustomPreview>
</FrameLayout>
<LinearLayout
android:layout_below="#id/mySurfaceView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center">
<ImageView android:id="#+id/myImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/icon"/>
</LinearLayout>
</RelativeLayout>
Now Enjoy the output.
This is my XML file. I take one LinearLayout in which i take SurfaceView and Button, but camera displays view like following Image... look at Image and please give me solution.
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<SurfaceView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/surface"
android:layout_weight="2"/>
<Button
android:layout_height="100dp"
android:layout_width="match_parent"
android:id="#+id/click"
android:text="Click Photo"
android:layout_weight="1"/>
</LinearLayout>
and here is my java code please check this also
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
clickphotobtn=(Button)findViewById(R.id.click);
surfaceview=(SurfaceView)findViewById(R.id.surface);
surfaceholder=surfaceview.getHolder();
surfaceholder.addCallback(this);
surfaceholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
clickphotobtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//startActivity(intent);
camera.takePicture(null, null, null);
}
});
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();
camera.setPreviewDisplay(surfaceholder);
// Toast.makeText(getApplication(), "Create", Toast.LENGTH_LONG).show();
} catch (IOException e) { }
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
Camera.Parameters parameters = camera.getParameters();
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation()== Surface.ROTATION_0)
{
parameters.setPreviewSize(width, height);
camera.setDisplayOrientation(90);
}
if(display.getRotation()== Surface.ROTATION_90 || display.getRotation()== Surface.ROTATION_180)
parameters.setPreviewSize(width, height);
if(display.getRotation()==Surface.ROTATION_270)
{
parameters.setPreviewSize(width, height);
camera.setDisplayOrientation(180);
}
// camera.setParameters(parameters);
try{
camera.setPreviewDisplay(surfaceholder);
camera.startPreview();
}
catch (Exception e){
Toast.makeText(getApplication(), e.toString(), Toast.LENGTH_LONG).show();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (null == camera)
return;
camera.stopPreview();
camera.release();
camera = null;
preview = false;
//Toast.makeText(getApplication(), "Destroy", Toast.LENGTH_LONG).show();
}
This is the right way to change camera orientation, this piece of code worked for me. camera.setDisplayOrientation(90);
Try to follow the way suggested by the documentation, using Camera.CameraInfo in order to obtain the camera orientation and updating it consequently.
Look at the example here: void setDisplayOrientation(int).
Add
public class YourActivity extends AppCompatActivity implements SurfaceHolder.Callback{
....
}
I am trying to place an imageview over a Camera surfaceview, when the application starts the imageview is on top of the camera preview but after a picture is taken and is set to the imageview the RelativeLayout that the camera preview is nested in moves forward when startpreview is called to start the camera again so the camera preview ends up above the imageview. There are buttons in the same layout placed after the imageview in the xml layout and those are not affected. If I don't start the camera again after a picture the imageview has it's image and is visible. Dumping the view hierarchy verifies the same. As far as I can tell this should be something fairly straight-forward, so I'm not sure where I'm going wrong.
UPDATE: I have also attempted to add a completely new ImageView with the bitmap programmatically after the camera is started and that ImageView is moved behind as well.
XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:id="#+id/add_activity"
android:layout_height="fill_parent"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/camera_preview"
/>
<ImageView
android:layout_width="fill_parent"
android:id="#+id/beforeImageView"
android:src="#drawable/app_icon"
android:alpha="0.2"
android:layout_height="fill_parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back"
android:id="#+id/close_camera"
android:layout_gravity="bottom|left"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:gravity="bottom|left"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" />
<Button
android:id="#+id/button_capture"
android:text="Before"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="20dp"
android:background="#color/purple"
android:textColor="#color/white"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/add_progress_bar"
android:layout_gravity="center" />
</FrameLayout>
JAVA:
public class AddActivity extends Activity {
private Camera mCamera;
CameraPreview mPreview;
private RelativeLayout preview;
boolean useFrontCamera = true;
boolean tookBeforeImage = false;
boolean tookAfterImage = false;
Bitmap beforeImage;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
//Hide Notification and Action Bars
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
ActionBar actionBar = getActionBar();
actionBar.hide();
progressBar = (ProgressBar) findViewById(R.id.add_progress_bar);
progressBar.setVisibility(View.INVISIBLE);
boolean cameraCheck = checkCameraHardware(getApplicationContext());
if (cameraCheck) {
StartCamera cameraLaunch = new StartCamera();
cameraLaunch.execute();
}
Button closeCameraButton = (Button) findViewById(R.id.close_camera);
closeCameraButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
releaseCamera();
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_VISIBLE;
decorView.setSystemUiVisibility(uiOptions);
ActionBar actionBar = getActionBar();
actionBar.show();
finish();
}
});
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.takePicture(null,null,mPicture);
}
});
}
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
#Override
protected void onPause() {
super.onPause();
releaseCamera();
}
#Override
public void onBackPressed() {
releaseCamera();
super.onBackPressed();
}
#Override
protected void onResume() {
super.onResume();
//Hide Notification and Action Bars
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
ActionBar actionBar = getActionBar();
actionBar.hide();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.menu_add, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
//return true;
}
return super.onOptionsItemSelected(item);
}
private class StartCamera extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(String... params) {
try {
if (useFrontCamera) {
mCamera = Camera.open();
mCamera.enableShutterSound(true);
} else {
//Flip Camera
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
mPreview = new CameraPreview(getApplicationContext(),mCamera);
preview = (RelativeLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview,0);
progressBar.setVisibility(View.INVISIBLE);
}
}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Display display = getWindowManager().getDefaultDisplay();
int rotation = 0;
switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
rotation = 90;
break;
case Surface.ROTATION_90:
rotation = 0;
break;
case Surface.ROTATION_180:
rotation = 270;
break;
case Surface.ROTATION_270:
rotation = 180;
break;
}
Bitmap bitmap = ImageTools.toBitmap(data);
bitmap = ImageTools.rotate(bitmap, rotation);
if (!tookBeforeImage) {
beforeImage = bitmap;
ResetCamera cameraReset = new ResetCamera();
cameraReset.execute();
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setText("After");
tookBeforeImage = true;
} else if (tookBeforeImage == true && tookAfterImage == false) {
} else {
}
}
};
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
this.setBackgroundColor(Color.TRANSPARENT);
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.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("Camera Error", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d("Camera Error", "Error starting camera preview: " + e.getMessage());
}
}
}
private static class ImageTools {
public static Bitmap toBitmap(byte[] data) {
return BitmapFactory.decodeByteArray(data, 0, data.length);
}
public static Bitmap rotate(Bitmap in, int angle) {
Matrix mat = new Matrix();
mat.postRotate(angle);
return Bitmap.createBitmap(in, 0, 0, in.getWidth(), in.getHeight(), mat, true);
}
}
private class ResetCamera extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(String... params) {
mCamera.startPreview();
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
ImageView beforeImageView = (ImageView) findViewById(R.id.beforeImageView);
beforeImageView.setImageBitmap(beforeImage);
beforeImageView.setImageAlpha(100);
//Trying to add programmatically still ends up behind Camera Preview
ImageView newBefore = (ImageView) new ImageView(getApplicationContext());
newBefore.setImageBitmap(beforeImage);
newBefore.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
preview.addView(newBefore,0);
progressBar.setVisibility(View.INVISIBLE);
}
}
}
It was due to trying to load too large of a bitmap, it was quietly throwing a notice in the log as it was unable to create a texture. Reducing the bitmap's size solved the issue.
I have written a code that used to display camera. Following is my layout file's code,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/previewLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
<LinearLayout
android:id="#+id/startBar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:background="#drawable/leftbarbg"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="#+id/MuteBtn"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="2"
android:src="#drawable/mutebtn" />
<ImageView
android:id="#+id/VideosBtn"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="2"
android:src="#drawable/videosbtn" />
<ImageView
android:id="#+id/RecBtn"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="3"
android:src="#drawable/action_rec_selected" />
<ImageView
android:id="#+id/SettingsBtn"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="2"
android:src="#drawable/settingsbtn" />
<ImageView
android:id="#+id/ChatBtn"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="2"
android:src="#drawable/chatbtn" >
</ImageView>
</LinearLayout>
<RelativeLayout
android:id="#+id/stopBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="3dp"
android:visibility="gone" >
<ImageView
android:id="#+id/StopBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/stopbtn" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="70dp"
android:layout_marginTop="20dp" >
<ImageView
android:id="#+id/MenuBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="#drawable/menubtn" />
<ImageView
android:id="#+id/LiveModeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:src="#drawable/livemodeoff" />
<Chronometer
android:id="#+id/video_chronometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="28sp"
android:textStyle="bold" />
</RelativeLayout>
</RelativeLayout>
And this is my code of CameraSurfaceview,
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Camera camera;
private MediaRecorder mediaRecorder;
private Boolean previewing;
private AutoFocusManager autoFocusManager;
private CameraDetectionObserver cameraDetectionObserver;
public CameraSurfaceView(Context context, AutoFocusManager autoFocusManager, CameraDetectionObserver cameraDetectionObserver) {
super(context);
this.holder = this.getHolder();
this.holder.addCallback(this);
this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
this.autoFocusManager= autoFocusManager;
this.cameraDetectionObserver= cameraDetectionObserver;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (camera != null) {
Camera.Parameters parameters = camera.getParameters();
List< String > FlashModes = parameters.getSupportedFlashModes();
if (FlashModes.contains(Parameters.FLASH_MODE_AUTO)) {
parameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
System.out.println("FLASH_MODE_AUTO");
}
List< String > WhiteBalance = parameters.getSupportedWhiteBalance();
if (WhiteBalance.contains(Parameters.WHITE_BALANCE_AUTO)) {
parameters.setFlashMode(Parameters.WHITE_BALANCE_AUTO);
System.out.println("WHITE_BALANCE_AUTO");
}
List< String > Antibanding = parameters.getSupportedAntibanding();
if (Antibanding.contains(Parameters.ANTIBANDING_AUTO)) {
parameters.setAntibanding(Camera.Parameters.ANTIBANDING_AUTO);
System.out.println("ANTIBANDING_AUTO");
}
List<Size> previews = parameters.getSupportedPreviewSizes();
int i = 0;
parameters.setPreviewSize( previews.get(4).width, previews.get(4).height );
camera.setParameters(parameters);
camera.startPreview();
autoFocusManager.startAutoFocus(camera);
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (camera != null) {
camera.release();
camera = null;
}
try {
camera = Camera.open(findBackFacingCamera());
camera.setPreviewDisplay(holder);
previewing = true;
cameraDetectionObserver.cameraInitializationStatus(true);
} catch (IOException e) {
camera.release();
camera = null;
}catch (Exception e) {
e.printStackTrace();
cameraDetectionObserver.cameraInitializationStatus(false);
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (previewing) {
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
autoFocusManager.stopAutoFocus();
System.out.println("surface destroyed");
}
}
public void stopPreview(){
if (previewing) {
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
autoFocusManager.stopAutoFocus();
System.out.println("surface destroyed");
}
}
public Camera getCamera()
{
return this.camera;
}
public MediaRecorder getMediaRecorder(){
mediaRecorder = new MediaRecorder();
camera.unlock();
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mediaRecorder.setPreviewDisplay(holder.getSurface());
mediaRecorder.setVideoFrameRate(29);
mediaRecorder.setVideoSize(ByteArraysForLogin.VideoDimention.vWidth,ByteArraysForLogin.VideoDimention.vHeight);
return mediaRecorder;
}
private int findBackFacingCamera() {
int cameraId = -1;
// Search for the back facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
break;
}
}
return cameraId;
}
}
Above code works fine but it shows camera preview in stretched format in both landscape & portrait mode as following image.
However the resultan camera image is not stretched it is in normal mode only preview is stretched.
P.S. I am asking this question after trying this
try adding
getWindow().setFormat(PixelFormat.UNKNOWN);
in your onCreate
if that doesn't help maybe setting the rotation will?
camera.setDisplayOrientation(90);
and if that still doesn't help, all the results on Google are saying the aspect ratio of the SurfaceView must match the aspect ratio of the camera
try and use different resolution and increase frame width and height