C++通过JNI传递AssetManager读取安卓assets目录中文件

在 Android 设备上,assets 目录位于应用程序的 APK 包内部,它并不直接暴露在设备的文件系统中。因此,无法通过传统的文件路径直接访问 assets 目录下的文件。访问 assets 目录下的文件通常通过 AssetManager 来实现。

就可以实现将C++需要的文件打包到APK内,提前放到在安卓工程中 assets 目录下。

要在 C++ 中读取 assets 目录下的一个文本文件,并使用 Android 的原生日志功能打印其内容,可以按照以下步骤进行。

1. 在 Kotlin 中获取 AssetManager 并传递给 C++

在你的 Kotlin 代码中获取 AssetManager 实例并传递给 C++。

kotlin 复制代码
import android.content.res.AssetManager

class MyActivity : AppCompatActivity() {

    // 加载本地库
    companion object {
        init {
            System.loadLibrary("my_native_lib")
        }
    }

    private external fun nativeInit(assetManager: AssetManager)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 获取 AssetManager 实例
        val assetManager = assets

        // 传递 AssetManager 到 C++
        nativeInit(assetManager)
    }
}

2. 在 C++ 中通过 JNI 接收 AssetManager 并读取文件内容,并使用 Android 的原生日志功能打印其内容

在 C++ 代码中,通过 JNI 接收 AssetManager,并使用 AAssetManager API 读取文件内容,并使用 __android_log_print 打印内容。以下是一个示例:

声明 JNI 接口

在你的头文件中声明 JNI 接口:

cpp 复制代码
// my_native_lib.h
#ifndef MY_NATIVE_LIB_H
#define MY_NATIVE_LIB_H

#include <jni.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT void JNICALL Java_com_example_myapp_MyActivity_nativeInit(JNIEnv* env, jobject obj, jobject assetManager);

#ifdef __cplusplus
}
#endif

#endif // MY_NATIVE_LIB_H
实现 JNI 接口

在你的 C++ 源文件中实现 JNI 接口:

cpp 复制代码
// my_native_lib.cpp
#include "my_native_lib.h"
#include <android/log.h>
#include <vector>

#define LOG_TAG "MyNativeLib"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_example_myapp_MyActivity_nativeInit(JNIEnv* env, jobject obj, jobject assetManager) {
    // 获取 AAssetManager
    AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);

    // 打开文本文件 (假设文件名为 "my_file.txt")
    const char* fileName = "my_file.txt";
    AAsset* asset = AAssetManager_open(mgr, fileName, AASSET_MODE_BUFFER);
    if (asset != nullptr) {
        // 获取文件大小
        off_t bufferSize = AAsset_getLength(asset);

        // 分配缓冲区并读取文件内容
        std::vector<char> buffer(bufferSize);
        AAsset_read(asset, buffer.data(), bufferSize);

        // 确保字符串以 null 结尾
        buffer.push_back('\0');

        // 使用 Android 日志打印文件内容
        LOGI("File content: %s", buffer.data());

        // 关闭文件
        AAsset_close(asset);
    } else {
        LOGE("Failed to open file: %s", fileName);
    }
}

3. 在你的 Android 项目中添加文本文件

将你的文本文件 my_file.txt 放入 assets 目录中:

app/
├── src/
│   └── main/
│       ├── java/
│       ├── res/
│       └── assets/
│           └── my_file.txt
├── build.gradle
└── ...

关键点总结

  1. Kotlin 代码 :通过 assets 获取 AssetManager 实例,并通过 JNI 方法 nativeInit 传递给 C++。
  2. C++ 代码 :在 C++ 中使用 AAssetManager_fromJava 获取 AAssetManager,并使用 AAssetManager_open 打开 assets 目录下的文件。使用 __android_log_print 打印文件内容。
  3. 文本文件 :确保你的文本文件位于 assets 目录中,并在 C++ 代码中正确读取和打印文件内容。

通过这些步骤,你可以在 C++ 代码中读取 assets 目录下的文本文件,并使用 Android 的原生日志功能打印其内容。

相关推荐
未来可期LJ36 分钟前
【C++ 设计模式】单例模式的两种懒汉式和饿汉式
c++·单例模式·设计模式
Trouvaille ~1 小时前
【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略
c++·c++20·编译原理·编译器·类和对象·rvo·nrvo
little redcap2 小时前
第十九次CCF计算机软件能力认证-乔乔和牛牛逛超市
数据结构·c++·算法
AI原吾2 小时前
掌握Python-uinput:打造你的输入设备控制大师
开发语言·python·apython-uinput
机器视觉知识推荐、就业指导2 小时前
Qt/C++事件过滤器与控件响应重写的使用、场景的不同
开发语言·数据库·c++·qt
毕设木哥2 小时前
25届计算机专业毕设选题推荐-基于python的二手电子设备交易平台【源码+文档+讲解】
开发语言·python·计算机·django·毕业设计·课程设计·毕设
珞瑜·2 小时前
Matlab R2024B软件安装教程
开发语言·matlab
weixin_455446172 小时前
Python学习的主要知识框架
开发语言·python·学习
孤寂大仙v2 小时前
【C++】STL----list常见用法
开发语言·c++·list
她似晚风般温柔7893 小时前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app