HarmonyOS鸿蒙Next应用开发-扫码功能:接收或捕获帧数据时,为什么回调函数对象ImageReceiver.IImageArrivalListener的onImageArrival()方法无法进入?

HarmonyOS鸿蒙Next应用开发-扫码功能:接收或捕获帧数据时,为什么回调函数对象ImageReceiver.IImageArrivalListener的onImageArrival()方法无法进入?

根据官方文档,我实现了相机的预览界面和扫码框界面之后,紧接着准备进行帧数据的获取。结果用Hilog日志进行查看时,发现回调函数对象ImageReceiver.IImageArrivalListeneronImageArrival()方法无法进入,如何解决?代码块如下:

import com.saomiao.camera.core.ScannerCore;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.components.surfaceprovider.Surface;
import ohos.agp.components.surfaceprovider.SurfaceOps;
import ohos.agp.window.dialog.ToastDialog;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraAbility;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.device.CameraConfig.Builder;
import ohos.media.camera.device.CameraFrameConfig;
import ohos.media.camera.device.CameraFrameConfig.Builder;
import ohos.media.camera.device.CameraStateCallback;
import ohos.media.image.Image;
import ohos.media.image.ImageReceiver;
import ohos.media.image.ImageReceiver.IImageArrivalListener;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageFormat;
import ohos.media.image.common.Size;
import java.util.List;

public class CameraView extends DirectionalLayout {
    private Camera cameraSurface;
    private SurfaceProvider surfaceProvider;
    private Surface previewSurface;
    private Context context;
    private String cameraId;
    private ImageReceiver imageReceiver;
    private ScanBoxView scanBoxView;
    private ScannerCore scannerCore;
    private static final int SCREEN_WIDTH = 1080;
    private static final int SCREEN_HEIGHT = 1920;
    private static final int IMAGE_RCV_CAPACITY = 9;
    private EventHandler eventHandler = new EventHandler(EventRunner.current());
    private ComponentContainer componentContainer;
    private CameraAbility cameraSupporter;
    static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00311, "MY_TAG");

    public CameraView(Context context) {
        super(context);
        this.context = context;
        initSurface(context);
    }

    private void initSurface(Context context) {
        WindowManager.getInstance().getTopWindow().get().setTransparent(true);
        DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
                ComponentContainer.LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_PARENT
        );
        surfaceProvider = new SurfaceProvider(context);
        surfaceProvider.setLayoutConfig(params);
        surfaceProvider.pinToZTop(false);
        surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
        addComponent(surfaceProvider);
    }

    private class SurfaceCallBack implements SurfaceOps.Callback {
        @Override
        public void surfaceCreated(SurfaceOps surfaceOps) {
            initCamera();
            HiLog.warn(label, "开始进入surfaceCreated方法");
            setImageArrivalListener();
            HiLog.warn(label, "结束surfaceCreated方法");
        }

        @Override
        public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {}

        @Override
        public void surfaceDestroyed(SurfaceOps surfaceOps) {}
    }

    private void initCamera() {
        CameraKit cameraKit = CameraKit.getInstance(context);
        String[] cameraList = cameraKit.getCameraIds();
        if (cameraList.length > 1) {
            cameraId = cameraList[0];
        }
        CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
        cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
        cameraSupporter = cameraKit.getCameraAbility(cameraId);
    }

    private class CameraStateCallbackImpl extends CameraStateCallback {
        @Override
        public void onCreated(Camera camera) {
            HiLog.warn(label, "开启相机");
            previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
            if (previewSurface == null) {
                return;
            }
            CameraConfig.Builder builder = camera.getCameraConfigBuilder();
            builder.addSurface(previewSurface);
            camera.configure(builder.build());
            getImageSurface(camera, builder);
            cameraSurface = camera;
        }

        @Override
        public void onConfigured(Camera camera) {
            FrameConfig.Builder builder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
            builder.addSurface(previewSurface);
            camera.triggerLoopingCapture(builder.build());
        }

        @Override
        public void onReleased(Camera camera) {
            super.onReleased(camera);
        }
    }

    private final ImageReceiver.IImageArrivalListener imageArrivalListener
            = new ImageReceiver.IImageArrivalListener() {
        @Override
        public void onImageArrival(ImageReceiver imageReceiver) {
            HiLog.warn(label, "进入onImageArrival方法");
            Image image = imageReceiver.readNextImage();
            Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);
            byte[] data = new byte[component.remaining()];
            HiLog.warn(label, "扫码的data值为:" + data.length);
            component.read(data);
            if (data != null && data.length > 0) {
                getImagePixelmap(data);
            }
        }
    };

    private void setImageArrivalListener() {
        HiLog.warn(label, "进入setImageArrivalListener方法");
        imageReceiver = ImageReceiver.create(SCREEN_HEIGHT, SCREEN_WIDTH, ImageFormat.JPEG, IMAGE_RCV_CAPACITY);
        imageReceiver.setImageArrivalListener(imageArrivalListener);
        HiLog.warn(label, "结束setImageArrivalListener方法");
    }

    private void getImageSurface(Camera camera, Builder cameraBuilder) {
        HiLog.warn(label, "进入getImageSurface方法");
        cameraBuilder = camera.getCameraConfigBuilder();
        Surface imageSurface = imageReceiver.getRecevingSurface();
        cameraBuilder.addSurface(imageSurface);
        HiLog.warn(label, "结束getImageSurface方法");
    }

    private void getImagePixelmap(byte[] data) {
        HiLog.warn(label, "进入getImagePixelmap方法");
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        sourceOptions.formatHint = "image/jpg";
        ImageSource imageSource = ImageSource.create(data, sourceOptions);
        PixelMap pixelMap = imageSource.createPixelmap(null);
        String scanValue = scannerCore.processPixelMapData(pixelMap, scanBoxView.getFramingRect());
        new ToastDialog(getContext()).setText("扫码结果为:" + scanValue);
        HiLog.warn(label, "扫码结果为:" + scanValue);
    }

    private void releaseCamera() {
        if (cameraSurface != null) {
            cameraSurface.release();
        }
    }
}

个人首先说明: 以上代码使用的是真机测试,而不是模拟器测试。

ImageReceiver.IImageArrivalListener的onImageArrival()方法无法进入,个人编写的主要代码块为:

private final ImageReceiver.IImageArrivalListener imageArrivalListener
    = new ImageReceiver.IImageArrivalListener(){
        @Override
        public void onImageArrival(ImageReceiver imageReceiver) {
            HiLog.warn(label,"进入onImageArrival方法");
            Image image = imageReceiver.readNextImage();
            Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);
            byte[] data = new byte[component.remaining()];
            HiLog.warn(label,"扫码的data值为:"+data.length);
            component.read(data);
            if(data != null && data.length > 0){
                getImagePixelmap(data);
            }
        }
    };

最后,想问一下onImageArrival()方法如何才能进入实现函数的回调?

7 回复

楼主可以参考下楼上大佬的回答哦

更多关于HarmonyOS鸿蒙Next应用开发-扫码功能:接收或捕获帧数据时,为什么回调函数对象ImageReceiver.IImageArrivalListener的onImageArrival()方法无法进入?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


姓名:张三
职业:软件工程师
简介:具有五年以上软件开发经验,熟悉多种编程语言和技术。

如图所示,需要cameraConfigBuilder.addSurface添加imageReceiver的Surface,然后framePreviewConfigBuilder也添加mageReceiver的Surface,这样相机的所有捕获帧都在onImageArrival回调中收到结果,不过这样捕获频率太高,会有性能问题,我个人采用的是定时循环单拍的方案,楼主也可以参考单拍的代码,如下:

好的,我再测试一下。

此内容有用,可以实现ImageReceiver.IImageArrivalListeneronImageArrival() 方法的回调。

在HarmonyOS鸿蒙Next应用开发中,ImageReceiver.IImageArrivalListeneronImageArrival()方法无法进入,可能是由于以下原因:

  1. ImageReceiver未正确初始化:确保ImageReceiver对象已正确创建并配置了适当的参数,如图像格式、尺寸等。

  2. 监听器未正确注册:确保ImageReceiver.IImageArrivalListener已通过setImageArrivalListener()方法正确注册到ImageReceiver对象上。

  3. 图像数据未到达:检查图像数据是否已成功传输到ImageReceiver。如果图像数据未到达,onImageArrival()方法自然不会触发。

  4. 权限问题:确保应用已获取必要的权限,如相机权限,以便能够接收图像数据。

  5. 生命周期问题:检查ImageReceiver和监听器的生命周期是否与应用的当前状态匹配。例如,如果ImageReceiver在后台被销毁,监听器将无法接收到图像数据。

  6. 线程问题:确保onImageArrival()方法在主线程或适当的线程中执行。如果该方法在错误的线程中执行,可能会导致无法正常触发。

  7. 系统资源限制:在某些情况下,系统资源限制可能导致ImageReceiver无法正常工作,从而影响onImageArrival()方法的触发。

  8. API版本兼容性:检查使用的API版本是否与当前HarmonyOS版本兼容。不兼容的API版本可能导致方法无法正常执行。

通过排查以上可能的原因,可以更好地理解为什么onImageArrival()方法无法进入,并采取相应的措施解决问题。

在HarmonyOS鸿蒙Next应用开发中,onImageArrival()方法无法进入可能有以下原因:

  1. 未正确注册监听器:确保在ImageReceiver对象上正确注册了IImageArrivalListener监听器。
  2. 权限问题:检查是否已获取相机和存储相关权限,如ohos.permission.CAMERAohos.permission.WRITE_USER_STORAGE
  3. 相机未启动或配置错误:确认相机已正确启动,并且ImageReceiver的配置(如分辨率、格式)与相机输出匹配。
  4. 回调线程问题:确保回调方法在主线程或合适的线程中执行,避免阻塞或线程冲突。

检查以上几点,通常可以解决onImageArrival()无法进入的问题。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!