我有一个使用Android相机的应用。
我希望实现像CameraManager
类这样的东西,它将处理与摄像机,打开,关闭,摄像机参数和帧缓冲区有关的所有事情。
问题是,我想将CameraManager
与GUI分开,但在Android中,相机似乎与GUI不可分割,因为您需要surfaceView
才能获得预览。
我有一个想法,是CameraManager
在surfaceView
初始化之后向GUI管理器返回CameraManager
,并让GUI管理器在此之后处理所有内容。但是,它没有足够的分离,因为相机管理器仍在触摸GUI的东西。
有关如何设法最大化此封装的任何想法?
答案 0 :(得分:1)
为什么不使用建议的Google方法并在XML中实现视图。创建两个自定义表面视图(在我的情况下,一个是GLSurfaceView,另一个是SurfaceView)。一个视图实现了摄像头,第二个视图可以处理带有图形和/或按钮的GUI。关键是在XML中创建自定义GLSurfaceView和SurfaceView,它使用扩展SurfaceView和GLSurfaceView的类名。您还必须使GUI视图透明。请注意,图形是在MainRenderer类中绘制的,此类不包括在内。请注意下面的代码有OpenGL上下文丢失的问题,我正在努力修复。下面显示的代码应该足以帮助你开始,但如果没有mod,它将无法自行运行...下面的大部分代码都源自Googles OpenGl 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(); } }