This is the code i used to have camera preview in my app, but it shows a java runtime error but not specifies at which the line the error is at. I found this code on https://github.com/commonsguy/cw-advandroid/tree/master/Camera/Preview/,which was given as a solution for one of the questions regarding camera preview, but it shows a blank screen and the app terminates. Any help will be appreciated.
package com.example.smartmeasure;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class CameraPreview extends Activity {
private SurfaceView preview=null;
private SurfaceHolder previewHolder=null;
private Camera camera=null;
private boolean inPreview=false;
private boolean cameraConfigured=false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_preview);
preview=(SurfaceView)findViewById(R.id.camera_preview);
previewHolder=preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume() {
super.onResume();
camera=Camera.open();
startPreview();
}
#Override
public void onPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters) {
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width<=width && size.height<=height) {
if (result==null) {
result=size;
}
else {
int resultArea=result.width*result.height;
int newArea=size.width*size.height;
if (newArea>resultArea) {
result=size;
}
}
}
}
return(result);
}
private void initPreview(int width, int height) {
if (camera!=null && previewHolder.getSurface()!=null) {
try {
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast
.makeText(CameraPreview.this, t.getMessage(), Toast.LENGTH_LONG)
.show();
}
if (!cameraConfigured) {
Camera.Parameters parameters=camera.getParameters();
Camera.Size size=getBestPreviewSize(width, height,
parameters);
if (size!=null) {
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
cameraConfigured=true;
}
}
}
}
private void startPreview() {
if (cameraConfigured && camera!=null) {
camera.startPreview();
inPreview=true;
}
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder,
int format, int width,
int height) {
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// no-op
}
};
}
This is the Error:
05-27 10:34:37.812: E/AndroidRuntime(2559): FATAL EXCEPTION: main 05-27 10:34:37.812: E/AndroidRuntime(2559): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.smartmeasure/com.example.smartmeasure.CameraPreview}: java.lang.ClassCastException: android.widget.FrameLayout 05-27 10:34:37.812: E/AndroidRuntime(2559): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
This is the xml code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="241dp" />
</LinearLayout>
camera_preview is FrameLayout and you are casting it into SurfaceView thats the error ..cast it into FrameLayout
You are casting FrameLayout to SurfaceView in your Activity onCreate, put SurfaceView instead of FrameLayout in XML and then name its id to camera_preview and initialize in Activity.
Your XML code will look like this after editing:
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<SurfaceView
android:id="#+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="241dp"/>
</LinearLayout>
Just to add on to the suggestions above, we are supposed to camera user permissions in AndroidManifest.xml file to access the camera. The permission lines are:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
Related
I want to capture images using the front facing camera "flash" trick similar to Fornt Flash.
I know that it might involves another layer on top of the camera preview
as suggested here and here.
Can anyone post a working solution that includes the camera?
Thanks.
Found out by myself (and some little help from a friend).
Basically you need to create a flash emulator View that has a white background with alpha of 0.7 and visibility gone.
when clicked you need to:
show the view - View.VISIBLE
flashEmulator.setVisibility(View.VISIBLE);
adjust the screenBrightness to the max value
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
lastScreenBrightness = params.screenBrightness;
params.screenBrightness = 1F;
window.setAttributes(params);
convert the background of the flash emulator to HSV
int color = Color.WHITE;
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 1f;
color = Color.HSVToColor(hsv);
flashEmulator.setBackgroundColor(color);
Complete Code for android front flash app
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.frontflash.android">
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
XML
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#android:color/black"
tools:context=".MainActivity">
<com.frontflash.android.CameraPreview
android:id="#+id/cameraPreview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<FrameLayout
android:visibility="gone"
android:alpha="0.7"
android:id="#+id/flashEmulator"
android:background="#android:color/white"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="On"
android:id="#+id/button"
android:layout_centerVertical="false"
android:layout_centerHorizontal="true" />
MainActivity.java
package com.frontflash.android;
import android.app.Activity;
import android.graphics.Color;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
public class MainActivity extends Activity {
private Button button;
private Camera camera;
private boolean isFlashOn;
private FrameLayout flashEmulator;
private float lastScreenBrightness;
private CameraPreview cameraPreview;
#Override
protected void onCreate(Bundle savedInstanceState) {
int fullScreen = WindowManager.LayoutParams.FLAG_FULLSCREEN;
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(fullScreen, fullScreen);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
flashEmulator = (FrameLayout) findViewById(R.id.flashEmulator);
cameraPreview = (CameraPreview)findViewById(R.id.cameraPreview);
startCamera();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isFlashOn) {
turnOffFlash();
button.setText("On");
} else {
turnOnFlash();
button.setText("Off");
}
}
});
}
private void startCamera() {
if (camera == null) {
try {
camera = Camera.open(1);
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(1280, 720);
camera.setDisplayOrientation(90);
camera.setParameters(params);
cameraPreview.connectCamera(camera);
cameraPreview.startPreview();
} catch (Exception e) {
}
}
}
private void turnOnFlash() {
if (!isFlashOn) {
int color = Color.WHITE;
float[] hsv = new float[3];
final Window window = getWindow();
final WindowManager.LayoutParams params = window.getAttributes();
lastScreenBrightness = params.screenBrightness;
params.screenBrightness = 1F;
window.setAttributes(params);
flashEmulator.setVisibility(View.VISIBLE);
Color.colorToHSV(color, hsv);
hsv[2] *= 1f;
color = Color.HSVToColor(hsv);
flashEmulator.setBackgroundColor(color);
isFlashOn = true;
}
}
private void turnOffFlash() {
if (isFlashOn) {
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.screenBrightness = lastScreenBrightness;
window.setAttributes(params);
flashEmulator.setVisibility(View.GONE);
isFlashOn = false;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onPause() {
super.onPause();
turnOffFlash();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onStart() {
super.onStart();
startCamera();
}
#Override
protected void onStop() {
super.onStop();
if (camera != null) {
camera.release();
camera = null;
}
}
}
CameraPreview.java
package com.frontflash.android;
import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Created by sagi on 2/8/2017.
*/
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera camera;
private SurfaceHolder surfaceHolder;
private final String LOG_TAG = "CameraPreview";
public CameraPreview(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public CameraPreview(Context context) {
super(context);
}
public void connectCamera(Camera camera) {
this.camera = camera;
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
startPreview();
}
public void releaseCamera() {
if (camera != null) {
stopPreview();
camera = null;
}
}
void startPreview() {
if (camera != null && surfaceHolder.getSurface() != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e) {
Log.e(LOG_TAG, String.format("Error setting preview display: %s", e.getMessage()));
}
}
}
void stopPreview() {
if (camera != null) {
try {
camera.stopPreview();
} catch (Exception e) {
Log.e(LOG_TAG, String.format("Error stopping preview: %s", e.getMessage()));
}
}
}
public void surfaceCreated(SurfaceHolder surfaceHolder) {
startPreview();
}
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
stopPreview();
startPreview();
}
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
stopPreview();
}
}
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 can display a preview of the camera video properly with a TextureView:
package com.example.camerasurfacetexture;
import java.io.IOException;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.FrameLayout;
public class MainActivity extends Activity implements SurfaceTextureListener
{
private Camera mCamera = null;
private TextureView mTextureView = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height)
{
Log.i("onSurfaceTextureAvailable", "onSurfaceTextureAvailable");
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try
{
mCamera.setPreviewTexture(surface);
}
catch (IOException t)
{
}
mCamera.startPreview();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height)
{
// Ignored, the Camera does all the work for us
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
Log.i("onSurfaceTextureDestroyed", "onSurfaceTextureDestroyed");
mCamera.stopPreview();
mCamera.release();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
// Update your view here!
}
}
and with a SurfaceView:
package com.example.cameratest;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class MainActivity extends Activity
{
private SurfaceView preview = null;
private SurfaceHolder previewHolder = null;
private Camera camera = null;
private boolean inPreview = false;
private boolean cameraConfigured = false;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preview = (SurfaceView) findViewById(R.id.cpPreview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume()
{
super.onResume();
camera = Camera.open();
startPreview();
}
#Override
public void onPause()
{
if (inPreview)
{
camera.stopPreview();
}
camera.release();
camera = null;
inPreview = false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters)
{
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes())
{
if (size.width <= width && size.height <= height)
{
if (result == null)
{
result = size;
}
else
{
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea)
{
result = size;
}
}
}
}
return (result);
}
private void initPreview(int width, int height)
{
if (camera != null && previewHolder.getSurface() != null)
{
try
{
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t)
{
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(MainActivity.this, t.getMessage(),
Toast.LENGTH_LONG).show();
}
if (!cameraConfigured)
{
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null)
{
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
cameraConfigured = true;
}
}
}
}
private void startPreview()
{
if (cameraConfigured && camera != null)
{
camera.startPreview();
inPreview = true;
}
}
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback()
{
public void surfaceCreated(SurfaceHolder holder)
{
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
// no-op
}
};
}
but if I try to do both at the same time:
package com.example.multiplecamerapreviewtest;
import java.io.IOException;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.FrameLayout;
import android.widget.Toast;
public class MainActivity extends Activity implements SurfaceTextureListener
{
private SurfaceView svPreview = null;
private SurfaceHolder previewHolder = null;
private Camera mCamera = null;
private boolean inPreview = false;
private boolean cameraConfigured = false;
private TextureView tvPreview = null;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
svPreview = (SurfaceView) findViewById(R.id.svPreview);
previewHolder = svPreview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// mTextureView = new TextureView(this);
tvPreview = (TextureView) findViewById(R.id.tvPreview);
tvPreview.setSurfaceTextureListener(this);
// setContentView(mTextureView);
}
#Override
public void onResume()
{
super.onResume();
mCamera = Camera.open();
startPreview();
}
#Override
public void onPause()
{
if (inPreview)
{
mCamera.stopPreview();
}
mCamera.release();
mCamera = null;
inPreview = false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters)
{
Camera.Size result = null;
for (Camera.Size size : parameters.getSupportedPreviewSizes())
{
if (size.width <= width && size.height <= height)
{
if (result == null)
{
result = size;
}
else
{
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea)
{
result = size;
}
}
}
}
return (result);
}
private void initPreview(int width, int height)
{
if (mCamera != null && previewHolder.getSurface() != null)
{
try
{
mCamera.setPreviewDisplay(previewHolder);
}
catch (Throwable t)
{
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast.makeText(MainActivity.this, t.getMessage(),
Toast.LENGTH_LONG).show();
}
if (!cameraConfigured)
{
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
if (size != null)
{
parameters.setPreviewSize(size.width, size.height);
mCamera.setParameters(parameters);
cameraConfigured = true;
}
}
}
}
private void startPreview()
{
if (cameraConfigured && mCamera != null)
{
mCamera.startPreview();
inPreview = true;
}
}
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback()
{
public void surfaceCreated(SurfaceHolder holder)
{
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
// no-op
}
};
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height)
{
Log.i("onSurfaceTextureAvailable", "onSurfaceTextureAvailable");
mCamera = Camera.open();
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
tvPreview.setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try
{
mCamera.setPreviewTexture(surface);
}
catch (IOException t)
{
}
mCamera.startPreview();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height)
{
// Ignored, the Camera does all the work for us
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
Log.i("onSurfaceTextureDestroyed", "onSurfaceTextureDestroyed");
mCamera.stopPreview();
mCamera.release();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
// Update your view here!
}
}
I get a "Fail to connect to camera service" exception when calling mCamera.setPreviewTexture().
According to the documentation (http://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay%28android.view.SurfaceHolder%29), this is the expected behavior:
setPreviewDisplay()
Setting a preview surface will un-set any preview surface texture that was set via setPreviewTexture(SurfaceTexture).
(and vice-versa). Is there anything I can do to get these both displaying at the same time?
Send the Camera output to a SurfaceTexture, then render the texture wherever you like using GLES.
See e.g. the "texture from camera" activity in Grafika.
This requires some EGL management and a basic familiarity with GLES, though you can get pretty far just using the code in Grafika. This approach will get you much better performance than manipulating pixels with the NDK, because the GPU does all the work.
Camera is a shared hardware resource. I don't think you can access it (Camera.open()) more than once even within the same application i.e even within the same process with same user id. How about accessing the buffers for camera preview natively and then reading bytes from those buffers to render them on as many TextureViews or SurfaceViews or VideoViews as you wish?
Edited:
NDK Resource:
How do I get the raw Android camera buffer in C using JNI?
I have been getting a set of very specific errors when developing a very basic camera application. The code is almost identical to that on the android website.
The Galaxy SII is the only phone giving me the error which appears as follows in my LogCat console:
06-28 16:28:40.098: E/Surface(1650): Surface::init token -2 identity 18
The number that follows "identity" changes (42, 38, etc) but the error persists.
I think this may be related to the following class, but am still unsure as to its meaning:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
What about the Galaxy SII might cause this error? I am also testing on an HTC Vivid and Pantech Burst. I fear this may be leading to larger problems. I am just trying to understand what this error may be about.
Here is the source:
package com.basicam.android;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
public class CamActivity extends Activity {
private SurfaceView preview=null;
private SurfaceHolder previewHolder=null;
private Camera camera=null;
private boolean inPreview=false;
private boolean cameraConfigured=false;
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d("crap","oncreated");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview=(SurfaceView)findViewById(R.id.preview);
previewHolder=preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume() {
super.onResume();
camera=Camera.open();
startPreview();
}
#Override
public void onPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
super.onPause();
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera cam) {
Camera.Size result=null;
Log.d("crap", "can haz preview sizes?");
int i = 0;
for (Camera.Size size : cam.getParameters().getSupportedPictureSizes()) {
Log.d("sizew", ""+size.width);
if (size.width<=width && size.height<=height) {
Log.d("sizew", ""+size.width);
Log.d("sizeh", ""+size.height);
if (result==null) {
result=size;
}
else {
int resultArea=result.width*result.height;
int newArea=size.width*size.height;
if (newArea>resultArea) {
result=size;
}
}
}
}
return(result);
}
private void initPreview(int width, int height) {
if (camera!=null && previewHolder.getSurface()!=null) {
try {
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e("PreviewDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
}
if (!cameraConfigured) {
Camera.Parameters parameters=camera.getParameters();
Camera.Size size=getBestPreviewSize(width, height,
camera);
if (size!=null) {
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
cameraConfigured=true;
}
}
}
}
private void startPreview() {
if (cameraConfigured && camera!=null) {
camera.startPreview();
inPreview=true;
}
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
// no-op -- wait until surfaceChanged()
}
public void surfaceChanged(SurfaceHolder holder,
int format, int width,
int height) {
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// no-op
}
};
}
I am capturing an image using the following code
public class PictureDemo extends Activity {
private SurfaceView preview=null;
private SurfaceHolder previewHolder=null;
private Camera camera=null;
private boolean inPreview=false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
save=(Button)findViewById(R.id.save);
save.setOnClickListener(this);
image=(ImageView)findViewById(R.id.image);
image.setImageResource(R.drawable.sofa);
preview=(SurfaceView)findViewById(R.id.preview);
previewHolder=preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void onResume() {
super.onResume();
camera=CameraFinder.INSTANCE.open();
}
#Override
public void onPause() {
if (inPreview) {
camera.stopPreview();
}
camera.release();
camera=null;
inPreview=false;
super.onPause();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.options, menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.camera) {
if (inPreview) {
camera.takePicture(null, null, photoCallback);
inPreview=false;
}
return(true);
}
return(super.onOptionsItemSelected(item));
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode==KeyEvent.KEYCODE_CAMERA ||
keyCode==KeyEvent.KEYCODE_SEARCH) {
return(true);
}
return(super.onKeyDown(keyCode, event));
}
private Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters) {
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
if (size.width<=width && size.height<=height) {
if (result==null) {
result=size;
}
else {
int resultArea=result.width*result.height;
int newArea=size.width*size.height;
if (newArea>resultArea) {
result=size;
}
}
}
}
return(result);
}
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t) {
Log.e("PictureDemo-surfaceCallback",
"Exception in setPreviewDisplay()", t);
Toast
.makeText(PictureDemo.this, t.getMessage(), Toast.LENGTH_LONG)
.show();
}
}
public void surfaceChanged(SurfaceHolder holder,
int format, int width,
int height) {
Camera.Parameters parameters=camera.getParameters();
Camera.Size size=getBestPreviewSize(width, height,
parameters);
if (size!=null) {
parameters.setPreviewSize(size.width, size.height);
parameters.setPictureFormat(PixelFormat.JPEG);
camera.setParameters(parameters);
camera.startPreview();
inPreview=true;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// no-op
}
};
Camera.PictureCallback photoCallback=new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
new SavePhotoTask().execute(data);
camera.startPreview();
inPreview=true;
}
};
class SavePhotoTask extends AsyncTask<byte[], String, String> {
#Override
protected String doInBackground(byte[]... jpeg) {
File photo=new File(Environment.getExternalStorageDirectory(),
"photo.jpg");
if (photo.exists()) {
photo.delete();
}
try {
FileOutputStream fos=new FileOutputStream(photo.getPath());
fos.write(jpeg[0]);
fos.close();
}
catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
return(null);
}
}
}
and the xml file is
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.view.SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<ImageView
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="matrix"
android:layout_centerInParent="true"
/>
<Button
android:id="#+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="save"
android:layout_alignParentRight="true"
/>
</FrameLayout>
I can capture an image with this code but i need to add the image which was given to the ImageView to the captured image.
How to do that.
Thanks in advance.
Declare a Bitmap in your class
public class PictureDemo extends Activity {
Bitmap bitmap;
...
I think you can get the image you just took with this:
public void onPictureTaken(byte[] data, Camera camera) {
new SavePhotoTask().execute(data);
camera.startPreview();
inPreview=true;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
}
And then set the bitmap to your ImageView like this:
image.setImageBitmap(bitmap);
Trying doing something like this:
Bitmap bitmap = new Bitmap(define the size and other params you like).
Canvas canvas = new Canvas();
canvas.drawBitmap(your captured image);
canvas.drawBitmap(the overlay image);
// Now the bitmap will include both captured imaged and overlayed image
You can look in here and here
You can do mFrameLayout.getDrawingCache() to get a bitmap of the whole layout. The drawing cache should be enabled. I dont know its default state.