如何在Android中分离相机和GUI?

时间:2012-04-22 14:21:19

标签: android user-interface camera encapsulation

我有一个使用Android相机的应用。

我希望实现像CameraManager类这样的东西,它将处理与摄像机,打开,关闭,摄像机参数和帧缓冲区有关的所有事情。

问题是,我想将CameraManager与GUI分开,但在Android中,相机似乎与GUI不可分割,因为您需要surfaceView才能获得预览。

我有一个想法,是CameraManagersurfaceView初始化之后向GUI管理器返回CameraManager,并让GUI管理器在此之后处理所有内容。但是,它没有足够的分离,因为相机管理器仍在触摸GUI的东西。

有关如何设法最大化此封装的任何想法?

2 个答案:

答案 0 :(得分:1)

为什么不使用建议的Google方法并在XML中实现视图。创建两个自定义表面视图(在我的情况下,一个是GLSurfaceView,另一个是SurfaceView)。一个视图实现了摄像头,第二个视图可以处理带有图形和/或按钮的GUI。关键是在XML中创建自定义GLSurfaceView和SurfaceView,它使用扩展SurfaceView和GLSurfaceView的类名。您还必须使GUI视图透明。请注意,图形是在MainRenderer类中绘制的,此类不包括在内。请注意下面的代码有OpenGL上下文丢失的问题,我正在努力修复。下面显示的代码应该足以帮助你开始,但如果没有mod,它将无法自行运行...下面的大部分代码都源自Googles OpenGl Tutorial

OpenGl ES 1.0 Tutorial

使用我自己的mod来将所有内容分开。

这是XML:

  <?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" >                         
<com.zypath.opengltest.MainSurfaceView
    android:id="@+id/glSurfaceView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />                                       
<com.zypath.opengltest.CameraView
    android:id="@+id/camera"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:keepScreenOn="true" />
<LinearLayout
    android:id="@+id/status"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
         android:id="@+id/mangle"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="@string/mangle"
         android:textColor="@color/mcolor" />                       
</LinearLayout>   

主要代码的一部分:

  public class Main extends Activity {
  ...


   @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // When working with the camera, it's useful to stick to one orientation.
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    //Set full screen
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.main);

    //Substantiate surfaces
    cameraView = (CameraView) findViewById(R.id.camera);
    mGLView = (MainSurfaceView) findViewById(R.id.glSurfaceView);        

    //Initialize TextViews
    txtView = (TextView) findViewById(R.id.mangle);
    txtView.setText("Angle: " + String.valueOf(mAngle)); 


}

Custom MainSurfaceView的一部分

  public class MainSurfaceView extends GLSurfaceView {
...

//Constructor
public MainSurfaceView(Context context, AttributeSet attrs) {       
    super(context, attrs);
    this.context = context;

    mRenderer = new MainRenderer();
    setEGLConfigChooser(8, 8, 8, 8, 16, 0); 

    setRenderer(mRenderer);
    getHolder().setFormat(PixelFormat.TRANSLUCENT);    

    setZOrderOnTop(true);

    //Render only when there is a change
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);         
}

//TouchEvent handler
  @Override
public boolean onTouchEvent(MotionEvent event) {

    x = event.getX();
    y = event.getY();

    .....

    return true;
}

摄像头代码的一部分:

  public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
  ...
private Camera camera;
SurfaceHolder holder;

public CameraView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // We're implementing the Callback interface and want to get notified
    // about certain surface events.
    getHolder().addCallback( this );
    // We're changing the surface to a PUSH surface, meaning we're receiving
    // all buffer data from another component - the camera, in this case.
    getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
}

public void surfaceCreated( SurfaceHolder holder ) {
    // Once the surface is created, simply open a handle to the camera hardware.
    camera = Camera.open();
}

public void surfaceChanged( SurfaceHolder holder, int format, int width, int height ) {

        camera.setPreviewDisplay( holder );

    camera.startPreview();
}

答案 1 :(得分:0)

将表面视图作为参数传递给CameraManager构造函数。 我希望你让经理开源:)

编辑: 这是我在一个旧项目中使用的(共享是一件好事:P)

CameraView

package at.fhb.triangulate.gui;
import android.content.Context;
import android.content.res.Resources.Theme;
import android.view.View;
import at.fhb.triangulate.main.TriangulateMain;


/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;

import java.io.IOException;
import java.util.List;


public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
    SurfaceHolder mHolder;
    Camera mCamera;

    public CameraView(Context context) {
        super(context);

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
        mCamera = Camera.open();
        try {
           mCamera.setPreviewDisplay(holder);
        } catch (IOException exception) {
            mCamera.release();
            mCamera = null;
            // TODO: add more exception handling logic here
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
        mCamera.stopPreview();
        mCamera = null;
    }


    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(w, h);
       // parameters.set("orientation", "portrait");

        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }

}