将单独的 Class 实现为 Activity

Implementing a separate Class into Activity

问题 在清理我的代码时,我想将我的 Android 相机方法移动到一个单独的 class,以符合我认为的最佳实践。经过一整天的搜索,我仍在努力弄清楚如何准确地做到这一点。主要问题是实施方法的差异以及从 camera API 到 camera2 API 的移动导致在网上找到我无法复制的解决方案。请注意,我是 Java 的初学者,因此,这可能是一个非常菜鸟的错误,由于网络上的信息种类繁多,我无法解决。

当前代码 我的主要问题是 startCamera() 中的 SurfaceTexture texture = surfaceView.getSurfaceTexture();Cannot resolve method 'getSurfaceTexture()'previewBuilder.addTarget(texture); 抱怨 addTarget (android.view.surface) in Builder cannot be applied to (android.graphics.SurfaceTexture).

public class CameraView extends TextureView implements TextureView.SurfaceTextureListener{

    private Size previewsize;
    private CameraDevice cameraDevice;
    private CaptureRequest.Builder previewBuilder;
    private CameraCaptureSession previewSession;
    private final Context context;
    public SurfaceView surfaceView;
    public TextureView textureView;

    public CameraView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
        // Once the surface is created, simply open a handle to the camera hardware.
        openCamera();
    }

    public void onSurfaceTextureUpdated(SurfaceTexture texture) {
    }

    public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int     width, int height) {

        try {
            //cameraDevice.setPreviewDisplay(holder);

            //cameraDevice.startPreview();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
        // stopPreview();
        cameraDevice.close();
        return true;
    }

    public void openCamera()
    {
        CameraManager manager = (CameraManager) context.getSystemService (Context.CAMERA_SERVICE);
        try
        {
            String cameraId = manager.getCameraIdList()[0];
            CameraCharacteristics     characteristics=manager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            previewsize = map.getOutputSizes(SurfaceTexture.class)[0];
            try {
                manager.openCamera(cameraId, stateCallback, null);
            } catch (SecurityException e){
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(CameraDevice camera) {
            cameraDevice = camera;
            startCamera();
        }
        @Override
        public void onClosed(CameraDevice camera) {
            // nothing
        }
        @Override
        public void onDisconnected(CameraDevice camera) {
        }
        @Override
        public void onError(CameraDevice camera, int error) {
        }
    };

    void startCamera()
    {
        if (cameraDevice == null || previewsize==null)
        {
            return;
        }

        SurfaceTexture texture = surfaceView.getSurfaceTexture();
texture.setDefaultBufferSize(previewsize.getWidth(),previewsize.getHeight());

        Surface surface = new Surface(texture);
        try
        {
            // add all the standard stuff to the previewBuilder
            previewBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        } catch (Exception e) {}
        previewBuilder.addTarget(texture);
        try
        {
            cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession session) {
                previewSession = session;
                getChangedPreview();
            }
            @Override
            public void onConfigureFailed(CameraCaptureSession session{
            }
        },null);
        } catch (Exception e) {}
    }

    void getChangedPreview()
    {
        previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);

        HandlerThread thread = new HandlerThread("changed Preview");
        thread.start();
        Handler handler = new Handler(thread.getLooper());
        try
        {
            previewSession.setRepeatingRequest(previewBuilder.build(), null, handler);
        }catch (Exception e){}
    }
}

目标 为了保持我的代码干净易懂,我想将 MainActivity class 限制为在视图之间切换,而不是在其中包含大量方法。我想通过将以下对象从 INVISIBLE 切换到 VISIBLE 来激活我的应用程序中的相机视图。其他建议表示赞赏。

cameraView = (CameraView) findViewById(R.id.camera);

MainActivity.java 看起来像:

public class MainActivity extends AppCompatActivity {

    private TextView mTextMessage;
    private CameraView cameraView;
    private MainSurfaceView mGLView;
    private TextureView textureView;

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    mTextMessage.setText(R.string.title_home);
                    return true;
                case R.id.navigation_dashboard:
                    mTextMessage.setText(R.string.title_dashboard);
                    return true;
                case R.id.navigation_notifications:
                    mTextMessage.setText(R.string.title_notifications);
                    return true;
            }
            return false;
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextMessage = (TextView) findViewById(R.id.message);
        cameraView = (CameraView) findViewById(R.id.camera);
        mGLView = (MainSurfaceView) findViewById(R.id.glSurfaceView);
        BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

    }
}

感谢您的帮助!

SurfaceTexture texture = surfaceView.getSurfaceTexture(); 在 startCamera() 中表示 Cannot resolve method 'getSurfaceTexture()'

你调用了surfaceView的getSurfaceTexture方法。 surfaceView 是一个 SurfaceView。让我们看一下文档: https://developer.android.com/reference/android/view/SurfaceView.html 显然 SurfaceView 没有名为 "getSurfaceTexture()" 的方法。但是,在 Google 上搜索 "getSurfaceTexture() Android" 显示该方法属于 TextureView class。您的 class CameraView 有一个名为 "textureView" 的字段,因此(我不知道您到底想实现什么)如果需要,可以调用该字段上的方法。另外,你的 class CameraView 本身就是一个 TextureView(你想要那个吗),所以如果你想在 class 本身上调用它,你也可以只调用 getSurfaceTexture()

previewBuilder.addTarget(texture); 抱怨 addTarget (android.view.surface) in Builder cannot be applied to (android.graphics.SurfaceTexture). 让我们再看看文档:https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.Builder.html 显然 CaptureRequest.builder(previewBuilder 的类型)有一个名为 addTarget 的方法,但该方法只接受 Surface!你正在传递一个纹理。您可能想将 texture 更改为 surface