简体   繁体   中英

How can get raw file from jni native c++

I'm making a simple app in Android. I'm using NDK to make JNI calls. I have a file in a resource subfolder (raw), which I need to access from native c++ code. I want to read it from native using for example "ifstream" function but I don't get to do that.

That's my Java code:

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);
    }

That's my C++ code:

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);
}

Anyone can help me? I'm desperated. Thanks!

The file will be stored inside the APK, but if you rename the file extension to something like .PNG then it will not be compressed. Put the file in the assets folder, not res/raw .

You can get the APK file path like this:

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;
}

Then find the offset of your resource inside the 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();
    }
}

Call like this:

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

You can call your C++ and pass offset , fileSize and apkFilepath via JNI. Open the file, seek past offset bytes and then read out fileSize bytes of data.

The accepted answer to this question shows an alternative method but I haven't tried doing it that way so I can't vouch for it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM