У меня есть приложение, которое использует камеру Android.
Я хочу реализовать что-то вроде класса CameraManager
, которое будет касаться всего, что связано с камерой, открытия, закрытия, параметров камеры и буфера кадров.
Дело в том, что я хочу отделить CameraManager
от графического интерфейса, но в Android камера кажется неотделимой от графического интерфейса, потому что для получения предварительного просмотра вам необходим surfaceView
просмотр.
Одна из CameraManager
surfaceView
в том, что CameraManager
возвратит surfaceView
в GUI-менеджер, после инициализации CameraManager
, и после этого менеджер GUI обрабатывает все. Но он недостаточно отделился, потому что диспетчер камеры по-прежнему трогает GUI.
Любые мысли о том, как я могу максимизировать эту инкапсуляцию?
Почему бы не использовать предложенный метод Google и реализовать представления в XML. Создайте два пользовательских вида поверхности (в моем случае один был GLSurfaceView, а другой - SurfaceView). Один вид реализует камеру, а второй может обрабатывать графический интерфейс с графикой и/или кнопками. Ключ создает пользовательский GLSurfaceView и SurfaceView в XML, который использует имена классов расширенных SurfaceView и GLSurfaceView. Также вы должны сделать прозрачный вид графического интерфейса. Обратите внимание, что графика рисуется в классе MainRenderer, который здесь не включен. Помните, что приведенный ниже код имеет проблемы с потерей контекста OpenGL, которые я исправляю. Код, показанный ниже, должен быть достаточным, чтобы помочь вам начать работу, но он не будет работать на нем без модов... Большая часть приведенного ниже кода получена из Googles OpenGl Tutorial
с моими модами, чтобы все разделилось.
Вот 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 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));
}
Часть пользовательского 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();
}
передать представление поверхности в качестве параметра в конструктор CameraManager. Надеюсь, вы создадите менеджера с открытым исходным кодом :)
edit: это то, что я использовал в старом проекте (совместное использование - это хорошо: 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 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(); } }