使用Intent调用Android系统自身的相机功能

使用Intent调用Android系统自身的相机功能 中,演示了如何使用 intent 调用内置的相机进行拍照。本文我们将演示如何使用 Camera2 API 完成拍照任务。对于想要定制相机的开发人员来说,理解 Camera2 API 是必须要掌握的。

声明权限

使用相机并保存拍摄的相片,需要在应用的 AndroidManifest.xml 加入权限声明相机和存储的权限:

1
2
3
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera2.full" />

构造界面

构造一个包含一个 TextureView 和两个 Button 的界面, TextrueView 用来显示相机镜头所拍摄到的画面。

activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextureView
android:id="@+id/tuwPhoto"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/linearLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">

<Button
android:id="@+id/btnOpenCamera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Open Camera" />

<Button
android:id="@+id/btnTakePhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Take Photo" />
</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

构建一个TextrueView 的监听器

使用 SurfaceTextureListener 监听器来监听(响应)TexttrueView 状态变化的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};

构建一个相机状态的回调接口类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}

@Override
public void onDisconnected(CameraDevice camera) {
cameraDevice.close();
}

@Override
public void onError(CameraDevice camera, int error) {
cameraDevice.close();
cameraDevice = null;
}
};

创建一个相机会话回调接口

1
2
3
4
5
6
7
8
final CameraCaptureSession.CaptureCallback captureCallbackListener = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_LONG).show();
createCameraPreview();
}
};

在按钮事件中打开相机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "Open camera...");
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
this.checkPermission();
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "openCamera completed.");
}

本文标题:使用Intent调用Android系统自身的相机功能

文章作者:梅老师

发布时间:2019年10月08日 - 15:10

最后更新:2020年05月28日 - 16:05

原始链接:https://www.mls-tech.info/app/android/android-use-camera-with-camera2-api/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。