使用 Object-C 本机接口时的代号一 "out of memory"(HEIC 到 JPEG 的转换)

Codename One "out of memory" when using Object-C native interface (HEIC to JPEG conversion)

因为我要为 Android 和 iOS 实现自定义图库,所以我必须通过本机接口直接访问存储在 FileSystemStorage 中的图库文件。

基本思路是通过原生接口获取文件列表,然后在Codename One中做一个跨平台的GUI。这适用于 Android,我必须尽可能快地生成拇指 (在代号一侧,而不是在本机界面一侧),总体结果相当可以接受。

关于 iOS,我还有一个问题,那就是 HEIC 图像文件格式,需要将其转换为 JPEG 才能在代号一中使用。基本上,我通过 the code in this question (我在等待答案...) 获取文件列表,然后我必须将每个 HEIC 文件转换为临时 JPEG 文件, 但我的 HEICtoJPEG 本机界面使应用程序在几张图像后崩溃,并显示“内存不足”Xcode 消息...

我怀疑有问题的代码如下,也许 UIImage* image and/or NSData* mediaData 从未发布过:

#import "myapp_utilities_HEICtoJPEGNativeImpl.h"

@implementation myapp_utilities_HEICtoJPEGNativeImpl

-(NSData*)heicToJpeg:(NSData*)param{
    UIImage* image = [UIImage imageWithData:param];
    NSData* mediaData = UIImageJPEGRepresentation(image, 0.9);
    return mediaData;
}

-(BOOL)isSupported{
    return YES;
}

@end

这是 Java 本机界面:

import com.codename1.system.NativeInterface;

/**
 * @deprecated
 */
public interface HEICtoJPEGNative extends NativeInterface {
        
    public byte[] heicToJpeg(byte[] heicInput);
}

这是 Java public API:

import com.codename1.io.FileSystemStorage;
import com.codename1.io.Util;
import com.codename1.system.NativeLookup;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class HEICtoJPEG {
    private static HEICtoJPEGNative nativeInterface = NativeLookup.create(HEICtoJPEGNative.class);
    
    /**
     * Public API to convert an HEIC file to a new JPEG file (placed in /heic)
     * @param heicFile in the FileSystemStorage
     * @return a new file (with unique name)
     */
    public static String convertToJPEG(String heicFile) throws IOException {
        if (nativeInterface != null && nativeInterface.isSupported()) {
            
            // It ensures that the directory exists.
            FileSystemStorage fss = FileSystemStorage.getInstance();
            String heicDir = fss.getAppHomePath() + "/heic";
            if (!fss.isDirectory(heicDir)) {
                fss.mkdir(heicDir);
            }
            
            ByteArrayOutputStream outHeic = new ByteArrayOutputStream();
            InputStream inHeic = fss.openInputStream(heicFile);
            Util.copy(inHeic, outHeic);
            byte[] heicData = outHeic.toByteArray();
            
            byte[] jpegData = nativeInterface.heicToJpeg(heicData);
            
            String jpegFile = heicDir + "/" + DeviceUtilities.getUniqueId() + ".jpg";
            OutputStream outJpeg = fss.openOutputStream(jpegFile);
            ByteArrayInputStream inJpeg = new ByteArrayInputStream(jpegData);
            Util.copy(inJpeg, outJpeg);
            
            return jpegFile;
            
        } else {
            return null;
        }
    }
}

既然 Android 对应的工作正常,我希望我的自定义画廊代码的其余部分没问题,并且这个内存不足问题是我在此处发布的代码中的问题。

我希望你能给我一个可行的解决方案。谢谢

iOS 端口调用接收或返回原始数组(byte[]int[] 等)的本机接口方法的方式存在内存泄漏。

我刚刚提交了一个修复程序(本机接口调用现在包含在自动释放池中),下周五(2020 年 10 月 9 日)将在构建服务器上可用。

编辑:(2020 年 10 月 2 日,星期五)

此修复已部署到构建服务器,因此您应该能够立即再次构建它并查看它是否解决了您的问题。