Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using android.view.SurfaceView with a camera on part of the screen

Tags:

android

camera

I trying to put together an Android app that will take a picture and process it in some way. I'd like the layout to be similar to Google Goggles. Meaning, camera preview on the top, and some controls on the bottom using portrait orientation.

I've built a first version using code sample from here. This works, but I want to add a button on the bottom.

I've modified my main.xml to look as follows (based on comments from this post):

<?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" >

      <android.view.SurfaceView android:id="@+id/preview"
                              android:layout_width="fill_parent"
                              android:layout_height="fill_parent"
                              android:layout_alignParentTop="true" />

    <Button android:id="@+id/snap" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:text="Snap"
            android:layout_alignParentBottom="true" />

</RelativeLayout>

But when I run this code I get the following exception:

E/AndroidRuntime(  199): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime(  199): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.beerometer/com.beerometer.ImageCapture}: android.view.InflateException: Binary XML file line #6: Error inflating class Android.view.SurfaceView
E/AndroidRuntime(  199):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
E/AndroidRuntime(  199):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
E/AndroidRuntime(  199):    at android.app.ActivityThread.access$2200(ActivityThread.java:119)
E/AndroidRuntime(  199):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
E/AndroidRuntime(  199):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(  199):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  199):    at android.app.ActivityThread.main(ActivityThread.java:4363)
E/AndroidRuntime(  199):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(  199):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(  199):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
E/AndroidRuntime(  199):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
E/AndroidRuntime(  199):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(  199): Caused by: android.view.InflateException: Binary XML file line #6: Error inflating class Android.view.SurfaceView
E/AndroidRuntime(  199):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:576)
E/AndroidRuntime(  199):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
E/AndroidRuntime(  199):    at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
E/AndroidRuntime(  199):    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
E/AndroidRuntime(  199):    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
E/AndroidRuntime(  199):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)
E/AndroidRuntime(  199):    at android.app.Activity.setContentView(Activity.java:1622)
E/AndroidRuntime(  199):    at com.beerometer.ImageCapture.onCreate(ImageCapture.java:37)
E/AndroidRuntime(  199):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
E/AndroidRuntime(  199):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
E/AndroidRuntime(  199):    ... 11 more
E/AndroidRuntime(  199): Caused by: java.lang.ClassNotFoundException: Android.view.SurfaceView in loader dalvik.system.PathClassLoader@44bfc7b0
E/AndroidRuntime(  199):    at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
E/AndroidRuntime(  199):    at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
E/AndroidRuntime(  199):    at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
E/AndroidRuntime(  199):    at android.view.LayoutInflater.createView(LayoutInflater.java:466)
E/AndroidRuntime(  199):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:565)
E/AndroidRuntime(  199):    ... 20 more

When I replace the SurfaceView above with something else, e.g. a TextView, that it displays, but in landscape.

How can I get a camera preview on part of the screen using portrait view?

Thanks

like image 979
oneself Avatar asked Mar 20 '10 23:03

oneself


People also ask

What is camera Preview in Android?

PreviewView is a subclass of FrameLayout . To display the camera feed, it uses either a SurfaceView or TextureView , provides a preview surface to the camera when it's ready, tries to keep it valid as long as the camera is using it, and when released prematurely, provides a new surface if the camera is still in use.

What is camera surface android?

Explanation: SurfaceView is a type of View which contains a SurfaceHolder. SurfaceHolder holds the surface on which we can display our media (generally frames). mCamera is a Camera object which will contains the camera instance.

What is Surface view in Android?

A SurfaceView is a custom view in Android that can be used to drawn inside it. The main difference between a View and a SurfaceView is that a View is drawn in the UI Thread , which is used for all the user interaction.

What is GL surface view?

The GLSurfaceView class provides helper classes for managing EGL contexts, interthread communication, and interaction with the activity lifecycle. You don't need to use a GLSurfaceView to use GLES. For example, GLSurfaceView creates a thread for rendering and configures an EGL context there.


3 Answers

First, your layout probably won't give you what you want. Consider using a RelativeLayout, with the Button anchored to the bottom, and the SurfaceView anchored to the top of the screen and the top of the Button.

Also, you have a duplicate xmlns:android="http://schemas.android.com/apk/res/android" on your SurfaceView that you don't need. The one on your root element will suffice.

In terms of your exception, there may be more detail in your stack trace that you are missing, explaining why startPreview() failed. Look for a "Caused by" or other line mid-way through the stack trace. If you can't identify it, edit your question and paste in the entire stack trace (and ping me via a comment on this answer, since I won't know about the edit otherwise).

You might also experiment with this book example as another Camera preview app, to see if there's something about how I approach the problem that works better for your circumstance.

like image 200
CommonsWare Avatar answered Oct 26 '22 19:10

CommonsWare


If I am not missing something, you cannot just use SurfaceView as is. You need a derived class of your own. I usually create this view programmatically, and give it the full screen. But you can cover parts of it with other views, including buttons:

 setContentView(new CameraView());
 View mainscreen = getLayoutInflater().inflate(R.layout.mainscreen, null, false);
 ViewGroup.LayoutParams generalLayoutParam = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.FILL_PARENT);
 addContentView(mainscreen, generalLayoutParam);
like image 41
Alex Cohn Avatar answered Oct 26 '22 18:10

Alex Cohn


Yes you can use a surfaceView. From the surfaceView you can get the SurfaceHolder which then can be used to set the camera's previewDisplay.

        SurfaceView preview = (SurfaceView) findViewById(R.id.cameraPreview);
    SurfaceHolder previewHolder = preview.getHolder();
    previewHolder.addCallback(surfaceCallback);
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

You'll need to implement the SurfaceHolder.Callback method in order to update the preview size properly. In surfaceCreated set the previewDisplay of the camera. On surfaceChanged update the previewSize for the camera.

camera.setPreviewDisplay(previewHolder);

In fact the example mentioned before is a very good reference!

like image 29
hcpl Avatar answered Oct 26 '22 18:10

hcpl