将单独的 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
问题 在清理我的代码时,我想将我的 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