当前位置: 首页 > article >正文

Android学习20 -- NDK5--操作camera(TODO)

在 Android NDK 环境中,直接用 C++ 操作摄像头,可以使用 Native Camera API(通过 NdkCamera2 提供的接口)。以下是一个完整的示例,展示如何在 NDK 环境中用 C++ 打开摄像头并预览图像。


1. 设置 Android 项目权限

AndroidManifest.xml 中,添加摄像头权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

2. Native C++ 代码实现

native-lib.cpp
#include <jni.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCaptureRequest.h>
#include <camera/NdkCameraMetadataTags.h>
#include <android/log.h>

#define LOG_TAG "NativeCamera"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

ACameraManager *cameraManager = nullptr;
ACameraDevice *cameraDevice = nullptr;
ACaptureRequest *captureRequest = nullptr;
ACameraCaptureSession *captureSession = nullptr;

extern "C" JNIEXPORT void JNICALL
Java_com_example_ndkcamera_NativeCamera_initCamera(JNIEnv *env, jobject, jobject surface) {
    // 获取 CameraManager
    cameraManager = ACameraManager_create();

    // 获取摄像头 ID 列表
    ACameraIdList *cameraIdList = nullptr;
    ACameraManager_getCameraIdList(cameraManager, &cameraIdList);

    if (cameraIdList->numCameras < 1) {
        LOGD("No cameras found");
        return;
    }

    const char *cameraId = cameraIdList->cameraIds[0];
    LOGD("Using camera ID: %s", cameraId);

    // 打开摄像头
    ACameraDevice_StateCallbacks deviceStateCallbacks = {
            .onDisconnected = [](void *context, ACameraDevice *device) {
                LOGD("Camera disconnected");
                ACameraDevice_close(device);
            },
            .onError = [](void *context, ACameraDevice *device, int error) {
                LOGD("Camera error: %d", error);
                ACameraDevice_close(device);
            }};
    ACameraManager_openCamera(cameraManager, cameraId, &deviceStateCallbacks, &cameraDevice);

    // 创建捕获请求
    ACaptureRequest_alloc(ACAMERA_REQUEST_TEMPLATE_PREVIEW, &captureRequest);

    // 获取 NativeWindow
    ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
    ACameraOutputTarget *outputTarget = nullptr;
    ACameraOutputTarget_create(nativeWindow, &outputTarget);
    ACaptureRequest_addTarget(captureRequest, outputTarget);

    // 创建会话
    ACameraCaptureSession_stateCallbacks sessionCallbacks = {
            .onActive = [](void *context, ACameraCaptureSession *session) {
                LOGD("Capture session active");
            },
            .onClosed = [](void *context, ACameraCaptureSession *session) {
                LOGD("Capture session closed");
            },
            .onReady = [](void *context, ACameraCaptureSession *session) {
                LOGD("Capture session ready");
            }};
    ACameraDevice_createCaptureSession(cameraDevice, 1, &outputTarget, &sessionCallbacks, &captureSession);

    // 启动预览
    ACameraCaptureSession_setRepeatingRequest(captureSession, nullptr, captureRequest, nullptr);

    // 释放资源
    ACameraOutputTarget_free(outputTarget);
    ACameraIdList_free(cameraIdList);
}

3. Java 代码调用 Native 方法

NativeCamera.java
package com.example.ndkcamera;

import android.view.Surface;

public class NativeCamera {
    static {
        System.loadLibrary("native-lib");
    }

    public native void initCamera(Surface surface);
}
MainActivity.java
package com.example.ndkcamera;

import android.os.Bundle;
import android.view.TextureView;
import android.view.Surface;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private NativeCamera nativeCamera;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextureView textureView = new TextureView(this);
        setContentView(textureView);

        nativeCamera = new NativeCamera();

        textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                Surface previewSurface = new Surface(surface);
                nativeCamera.initCamera(previewSurface);
            }

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

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

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

4. 配置 CMake 文件

CMakeLists.txt
cmake_minimum_required(VERSION 3.10.2)

project("ndkcamera")

add_library(native-lib SHARED native-lib.cpp)

find_library(log-lib log)
find_library(camera2-lib camera2ndk)

target_link_libraries(native-lib ${log-lib} ${camera2-lib})

5. 项目结构

app/
├── src/
│   ├── main/
│   │   ├── java/com/example/ndkcamera/  # Java 文件
│   │   │   ├── MainActivity.java
│   │   │   ├── NativeCamera.java
│   │   ├── cpp/                         # C++ 文件
│   │   │   ├── native-lib.cpp
│   │   ├── AndroidManifest.xml
├── CMakeLists.txt

运行结果

  • 运行应用后,TextureView 将显示摄像头的实时预览。
  • 所有 NDK 摄像头操作都通过 NdkCamera2 接口完成。

此示例演示了如何通过 NDK 的 Camera2 API 用 C++ 操作摄像头,包括打开摄像头、配置预览会话和显示图像。


http://www.kler.cn/a/468588.html

相关文章:

  • 【网络安全技术与应用】(选修)实验8 入侵检测
  • 线程池与并发工具:Java的分身管理器
  • 工控安全需求分析与安全保护工程
  • TDengine + MQTT :车联网时序数据库如何高效接入
  • PINN模型详解
  • 云原生监控与日志管理:确保云原生应用的可靠性与性能
  • 【能用的方案】springBoot集成netty中如何使用@Value(通过依赖注入(DI)来访问)配置文件中的属性值
  • MaxKB知识库问答系统v1.9版本有哪些具体的改进?
  • 【网络安全 | 漏洞挖掘】通过模拟功能实现提权(Bugcrowd)
  • ESP32学习--SPIFFS文件系统
  • gaussdb中怎么查询一个表有多少GB
  • Spring MVC实战指南:构建高效Web应用的架构与技巧(二)
  • JMeter线程组Duration和循环次数设置冲突后,Duration优先级高
  • 代码随想录 day55 第十一章 图论part05
  • 数据结构之双链表(超详解)
  • 【intro】BLEU
  • 圆周率的广泛应用
  • vscode如何离线安装插件
  • 深度学习YOLOv3压双黄线期末项目
  • 7-10 逆序对
  • ArkTS更简洁
  • 贝叶斯算法详解:用概率思维解决分类难题
  • 如何提高软件研发效率?
  • 0042.大学校园生活信息平台+论文
  • 2.1.8 epoll的实现原理
  • 流程图(三)利用python绘制桑基图