You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android C++移植二进制文件问题:Windows资源加载代码适配NDK遇阻

移植Windows资源加载到Android NDK的二进制数据处理方案

我来帮你搞定这个从Windows到Android NDK的二进制数据适配问题!先理清楚原Windows代码的逻辑:

原Windows代码通过FindResource/LoadResource/LockResource这套API,把嵌入到程序里的KEY_DATA类型资源读出来,拿到二进制缓冲区后初始化Keystore。

现在你已经把二进制内容转成了BYTE数组key_bytes,接下来的适配其实很直接,分两种情况给你讲:

直接用已定义的BYTE数组适配

既然已经把二进制数据硬编码成数组了,直接替换原来的资源加载逻辑就行,注意这几个细节:

  • 替换核心代码
    原来的pBuffer就是数组的首地址,cbBuffer就是数组的字节长度,直接写:

    // 替换掉Windows资源加载的那几行
    LPBYTE pBuffer = key_bytes;
    size_t cbBuffer = sizeof(key_bytes);
    Keystore.Initialize(pBuffer, cbBuffer);
    
  • 避开数组退化为指针的坑
    如果key_bytes是函数里的局部数组,或者你把它传递到其他函数里,sizeof(key_bytes)会变成指针的大小(比如4或8字节),而不是数组实际长度。这种情况建议提前把长度存成常量:

    // 定义数组时就把长度定好
    constexpr size_t KEY_DATA_LENGTH = sizeof(key_bytes);
    // 初始化时直接用
    Keystore.Initialize(key_bytes, KEY_DATA_LENGTH);
    

更适合大文件的优雅方案(可选)

如果你的二进制数据比较大,硬编码成数组会让代码变得超级臃肿,而且后续更新数据还要改代码,推荐把二进制文件放到APK的assets目录,然后在NDK里读取:

  1. 把你的二进制文件(比如叫key_data.bin)放到app/src/main/assets目录下
  2. 在NDK代码里通过AAssetManager读取:
    #include <android/asset_manager.h>
    #include <android/asset_manager_jni.h>
    
    // 注意:AAssetManager指针需要从JNI层传递过来(比如在JNI_OnLoad里获取)
    AAsset* keyAsset = AAssetManager_open(assetManager, "key_data.bin", AASSET_MODE_BUFFER);
    if (keyAsset != nullptr) {
        // 直接拿到缓冲区和长度
        const void* buffer = AAsset_getBuffer(keyAsset);
        off_t bufferSize = AAsset_getLength(keyAsset);
        Keystore.Initialize((LPBYTE)buffer, bufferSize);
        // 用完记得关闭资源
        AAsset_close(keyAsset);
    } else {
        // 这里处理文件打开失败的情况,比如打日志或者抛异常
    }
    

这种方式不仅代码更干净,后续更新二进制文件只需要替换assets里的文件就行,不用改C++代码。

最后要注意的小细节

  • 字节序:Windows和Android(ARM/x86架构)都是小端字节序,所以如果原资源是小端的,完全不用处理字节序;如果是大端数据,记得做转换。
  • 数组生命周期:如果key_bytes是全局或静态数组,生命周期和程序一致,没问题;如果是局部数组,要确保Keystore在使用缓冲区的时候,这个数组不会被销毁(比如不要在函数里定义局部数组,然后返回指针给Keystore)。

内容的提问来源于stack exchange,提问作者Pieter Wp

火山引擎 最新活动