CMake, JNI boost читает файл json — Android

#android #c #json #boost #cmake

Вопрос:

Как правильно открыть файл с помощью boost::property_tree::json_parser::read_json

Текущее дерево:

введите описание изображения здесь

 boost::property_tree::ptree config;
boost::property_tree::json_parser::read_json("conf/file.json", config);
 

Но я получаю сообщение об ошибке, что он не может найти файл

завершается с неперехваченным исключением типа boost::wrapexceptboost::property_tree::json_parser::json_parser_error: conf/файл.json: не удается открыть файл

Как бы я продолжил копирование файла на устройство и смог бы его открыть?

Комментарии:

1. проверьте текущий каталог и, соответствует ли он ожидаемому пути. Убедитесь, что файл конфигурации был загружен в ожидаемое место.

2. Поместите файлы в assets папку и используйте библиотеку ресурсов JNI для доступа к ним.

3. @MarekR Как мне убедиться и проверить, был ли он загружен в нужное место?

4. @RichardCritten это работает с boost?

5. @RichardCritten как мне конвертировать InputStream в boost ptree , была бы признательна любая помощь?

Ответ №1:

Я использовал этот код, чтобы заставить его работать, в основном вы копируете файл из Android raw dir в какое-то место на устройстве, которое может видеть код C JNI.

MainActivity код:

 private static final String RES_RAW_CONFIG_PATH_ENV_VAR = "RES_RAW_CONFIG_PATH";
private static final String RES_RAW_CONFIG_FILE_NAME = "res_raw_config.json";

@Override
protected void onCreate(Bundle savedInstanceState) {
    initResRawConfig(true); // this will copy the file
    ...
}

private boolean existsInFilesDir(String fileName) {
    val file = File(filesDir, fileName)
    return file.exists()
}

private void initResRawConfig(boolean forceCopy) {
    if (existsInFilesDir(RES_RAW_CONFIG_FILE_NAME) amp;amp; !forceCopy) {
        Log.d(TAG, "Config file: "   RES_RAW_CONFIG_FILE_NAME   " already exists in "   getFilesDir().toString());
    }
    else {
        copyFileFromResToFilesDir(R.raw.res_raw_config, RES_RAW_CONFIG_FILE_NAME);
        Log.d(TAG, "Config file: "   RES_RAW_CONFIG_FILE_NAME   " copied to "   getFilesDir().toString());
    }

    // Set Environment Variable to get path from native
    try {
        Os.setenv(RES_RAW_CONFIG_PATH_ENV_VAR, getFilesDir().getAbsolutePath(), true);
    } catch (ErrnoException e) {
        e.printStackTrace();
    }
}

private void copyFileFromResToFilesDir(int fromResId, String toFile) {
    InputStream is =  getResources().openRawResource(fromResId);
    byte[] buffer = new byte[4096];
    try
    {
        FileOutputStream fos = openFileOutput(toFile, Context.MODE_PRIVATE);

        int bytes_read;
        while ((bytes_read = is.read(buffer)) != -1)
            fos.write(buffer, 0, bytes_read);

        fos.close();
        is.close();
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

public String getResRawConfigDir()
{
    return getFilesDir().toString();
}

 

JNI код:

 // get file path from java method
std::string getResRawConfigDirFromJava(JNIEnv *env, jobject obj) {
    jclass clazz = env->GetObjectClass(obj); // or env->FindClass("com/example/myapp/MainActivity");
    jmethodID method = env->GetMethodID(clazz, "getResRawConfigDir", "()Ljava/lang/String;");
    jobject ret = env->CallObjectMethod(obj, method);

    auto jConfigDirPath = (jstring) ret;

    return std::string(env->GetStringUTFChars(jConfigDirPath, nullptr));
}

extern "C" JNIEXPORT jstring
sampleFunc(JNIEnv *env, jobject thiz) {
    std::string configPath = getResRawConfigDirFromJava(env, thiz);
    std::string filePath = configPath   "/"   "res_raw_config.json";
}

 

Ссылка: https://github.com/nkh-lab/ndk-config-provider/blob/master/app/src/main/java/com/example/myapp/MainActivity.java