HarmonyOS鸿蒙Next应用开发-扫码功能:接收或捕获帧数据时,为什么回调函数对象ImageReceiver.IImageArrivalListener的onImageArrival()方法无法进入?
HarmonyOS鸿蒙Next应用开发-扫码功能:接收或捕获帧数据时,为什么回调函数对象ImageReceiver.IImageArrivalListener的onImageArrival()方法无法进入?
根据官方文档,我实现了相机的预览界面和扫码框界面之后,紧接着准备进行帧数据的获取。结果用Hilog日志进行查看时,发现回调函数对象ImageReceiver.IImageArrivalListener
的onImageArrival()
方法无法进入,如何解决?代码块如下:
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()
方法如何才能进入实现函数的回调?
楼主可以参考下楼上大佬的回答哦
更多关于HarmonyOS鸿蒙Next应用开发-扫码功能:接收或捕获帧数据时,为什么回调函数对象ImageReceiver.IImageArrivalListener的onImageArrival()方法无法进入?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
姓名:张三
职业:软件工程师
简介:具有五年以上软件开发经验,熟悉多种编程语言和技术。
如图所示,需要cameraConfigBuilder.addSurface
添加imageReceiver
的Surface,然后framePreviewConfigBuilder
也添加mageReceiver
的Surface,这样相机的所有捕获帧都在onImageArrival
回调中收到结果,不过这样捕获频率太高,会有性能问题,我个人采用的是定时循环单拍的方案,楼主也可以参考单拍的代码,如下:
好的,我再测试一下。
此内容有用,可以实现ImageReceiver.IImageArrivalListener
的 onImageArrival()
方法的回调。
在HarmonyOS鸿蒙Next应用开发中,ImageReceiver.IImageArrivalListener
的onImageArrival()
方法无法进入,可能是由于以下原因:
-
ImageReceiver未正确初始化:确保
ImageReceiver
对象已正确创建并配置了适当的参数,如图像格式、尺寸等。 -
监听器未正确注册:确保
ImageReceiver.IImageArrivalListener
已通过setImageArrivalListener()
方法正确注册到ImageReceiver
对象上。 -
图像数据未到达:检查图像数据是否已成功传输到
ImageReceiver
。如果图像数据未到达,onImageArrival()
方法自然不会触发。 -
权限问题:确保应用已获取必要的权限,如相机权限,以便能够接收图像数据。
-
生命周期问题:检查
ImageReceiver
和监听器的生命周期是否与应用的当前状态匹配。例如,如果ImageReceiver
在后台被销毁,监听器将无法接收到图像数据。 -
线程问题:确保
onImageArrival()
方法在主线程或适当的线程中执行。如果该方法在错误的线程中执行,可能会导致无法正常触发。 -
系统资源限制:在某些情况下,系统资源限制可能导致
ImageReceiver
无法正常工作,从而影响onImageArrival()
方法的触发。 -
API版本兼容性:检查使用的API版本是否与当前HarmonyOS版本兼容。不兼容的API版本可能导致方法无法正常执行。
通过排查以上可能的原因,可以更好地理解为什么onImageArrival()
方法无法进入,并采取相应的措施解决问题。
在HarmonyOS鸿蒙Next应用开发中,onImageArrival()
方法无法进入可能有以下原因:
- 未正确注册监听器:确保在
ImageReceiver
对象上正确注册了IImageArrivalListener
监听器。 - 权限问题:检查是否已获取相机和存储相关权限,如
ohos.permission.CAMERA
和ohos.permission.WRITE_USER_STORAGE
。 - 相机未启动或配置错误:确认相机已正确启动,并且
ImageReceiver
的配置(如分辨率、格式)与相机输出匹配。 - 回调线程问题:确保回调方法在主线程或合适的线程中执行,避免阻塞或线程冲突。
检查以上几点,通常可以解决onImageArrival()
无法进入的问题。