如何从jni native c ++

时间:2016-08-17 08:31:10

标签: android c++ file android-ndk java-native-interface

我在Android中制作了一款简单的应用。我正在使用NDK进行JNI呼叫。我有一个资源子文件夹(原始)中的文件,我需要从本机c ++代码访问。我想从本地使用例如" ifstream"功能,但我不能做到这一点。

那是我的Java代码:

Algorithm algorithm = new Algorithm();

    InputStream isModel = getResources().openRawResource(R.raw.model);

    String model = algorithm.ReadResourceFile(isModel);

    if(imgInput != null && txtResults != null)
    {
        Bitmap bmp = ((BitmapDrawable)imgInput.getDrawable()).getBitmap();

        //Convert Bitmap to Mat
        Mat image = new Mat(bmp.getHeight(), bmp.getWidth(), CvType.CV_8U);

        //Print results on txtResults
        String results = algorithm.DetectEmotionByImage(image.nativeObj, model);
        txtResults.setText(results);
    }

那是我的C ++代码:

JNIEXPORT jstring JNICALL
Java_org_ctic_emoplay_1android_algorithm_Algorithm_DetectEmotionByImage(JNIEnv *env,
                                                                        jobject instance,
                                                                        jlong image,
                                                                        jstring fileModel_,
                                                                        jstring fileRange_,
                                                                        jstring fileModelFlandmarks_,
                                                                        jstring fileHaarCascade_)
{
    const char *fileModel = env->GetStringUTFChars(fileModel_, NULL);

    SVM_testing testing;

    Mat* imageInput= (Mat*)image;
    Mat& inImageInput = *(Mat*) imageInput;

    string results = testing.TestModel(inImageInput, fileModel);

    const char* final_results = results.c_str();

    env->ReleaseStringUTFChars(fileModel_, fileModel);

    return env->NewStringUTF(final_results);
}

任何人都可以帮助我吗?我绝望了。谢谢!

1 个答案:

答案 0 :(得分:0)

该文件将存储在APK中,但如果您将文件扩展名重命名为.PNG,则不会对其进行压缩。将文件放在assets文件夹中,而不是res/raw

您可以像这样获取APK文件路径:

public static String getAPKFilepath(Context context) {
    // Get the path
    String apkFilePath = null;
    ApplicationInfo appInfo = null;
    PackageManager packMgmr = context.getPackageManager();
    String packageName = context.getApplicationContext().getPackageName();
    try {
        appInfo = packMgmr.getApplicationInfo(packageName, 0);
        apkFilePath = appInfo.sourceDir;
    } catch (NameNotFoundException e) {
    }
    return apkFilePath;
}

然后在APK中找到资源的偏移量:

public static void findAPKFile(String filepath, Context context) {
    String apkFilepath = getAPKFilepath(context);

    // Get the offset and length for the file: theUrl, that is in your
    // assets folder
    AssetManager assetManager = context.getAssets();
    try {

        AssetFileDescriptor assFD = assetManager.openFd(filepath);
        if (assFD != null) {
            long offset = assFD.getStartOffset();
            long fileSize = assFD.getLength();
            assFD.close(); 

            // **** offset and fileSize are the offset and size
            // **** in bytes of the asset inside the APK
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

这样打电话:

findAPKFile("model.png", MyActivity.this);

您可以调用C ++并通过JNI传递offsetfileSizeapkFilepath。打开文件,查找超过offset个字节,然后读出fileSize个字节的数据。

this question接受的答案显示了另一种方法,但我没有尝试过这样做,所以我无法保证。