3

I'm trying to make an app in Android that uses OpenCV in C++. The problem I face is that I want to open a text file from the native part to read it word by word, but it won't open. My code is the following:

JNI method:

JNIEXPORT jboolean JNICALL Java_com_alejandro_nativeopencv_NativeClass_initRecognizer(JNIEnv * env, jclass clazz){

    recognizer = Recognizer("ORB","ORB","BruteForce-Hamming");
    recognizer.createObject("/storage/emulated/0/TFG/Fotos/Carpeta", true);
    recognizer.createObject("/storage/emulated/0/TFG/Fotos/Cereales", true);

    return true;
}

And the Recognizer::createObject method that I am using:

Recognizer.cpp:

#include "headers/Recognizer.h"
#include <fstream>
#include <iostream>
#include <string>
#include <android/log.h>

using namespace std;
using namespace cv;

//...other methods, constructors and stuff...

Object Recognizer::createObject(String path, bool add) {
    __android_log_print(ANDROID_LOG_DEBUG,"path","%s",(path + "/info.txt").c_str());
    ifstream file((path + "/info.txt").c_str());
    if (!file.is_open()){
        //always enters here
        return Object(true);  //null object
    } else{
        //never enters here
        String name;
        vector < vector<KeyPoint> > keypoints;
        vector <Mat> descriptors;
        vector < vector<Point2f> > corners;
        vector <String> viewNames;
        bool easy;

        string word;
        int i = 0;
        while (file >> word)
        {
            if(i == 0){

                /* Object name */
                name = word;

                __android_log_print(ANDROID_LOG_DEBUG,"NOMBRE","%s",name.c_str());

            } else if(i == 1){

                /* Object easy or not */
                easy = (word == "true");
                __android_log_print(ANDROID_LOG_DEBUG, "EASY", "%d", easy);
            } else if(i%2 == 0){

                /* Object image view*/
                keypoints.push_back(vector <KeyPoint>());
                descriptors.push_back(Mat());
                corners.push_back(vector <Point2f>(4));

                Mat image = imread(path + "/" + word, CV_LOAD_IMAGE_GRAYSCALE);
                this->detector->detect(image, keypoints[(i/2)-1]);
                this->extractor->compute(image, keypoints[(i/2)-1], descriptors[(i/2)-1]);
                corners[(i/2)-1][0] = cvPoint(0,0);
                corners[(i/2)-1][1] = cvPoint(image.cols,0);
                corners[(i/2)-1][2] = cvPoint(image.cols, image.rows);
                corners[(i/2)-1][3] = cvPoint(0, image.rows);
                __android_log_print(ANDROID_LOG_DEBUG, "VISTA", "%d", (i/2)-1);
            } else{

                /* Object name view */
                viewNames.push_back(word);

                String aux = word;
                __android_log_print(ANDROID_LOG_DEBUG, "VISTA NOMBRE", "%s", aux.c_str());
            }

            i++;
        }
        Object obj = Object(name, keypoints, descriptors, corners, viewNames, easy);

        if(add){
            this->objects.push_back(obj);
        }

        file.close();

        return obj;
    }
}

The problem is here:

    __android_log_print(ANDROID_LOG_DEBUG,"path","%s",(path + "/info.txt").c_str());
    ifstream file((path + "/info.txt").c_str());
    if (!file.is_open()){
        //always enters here
        return Object(true);  //null object
    } else{
        //never enters here
        ...do stuff...
    }

In the JNI method, I pass as parameter the path where the info.txt file that I want to read is located, but it doesn't open it (no error, it just enters in the first if statement. I first tried putting the folder in the sdcard of my mobile phone, and after that in my internal storage, but it doesn't work in any way. I checked in my phone, and I guess the path is correct:

Link to the image showing the folder path

Also I have in the Android Manifest the read and write external storage permission.

Do you know where or what is the problem here?

Thank you very much!

EDIT 1:

Changed code to this:

__android_log_print(ANDROID_LOG_DEBUG,"path","%s",(path + "/info.txt").c_str());
ifstream file;
file.open((path + "/info.txt").c_str());
if (!file.is_open()){
    //always enters here
    return Object(true);  //null object
} else{
    //never enters here
    ...do stuff...
}

Still having the same problem.

EDIT 2

The log results I'm getting are these (they correspond with the paths it's trying to access):

D/path: /storage/emulated/0/TFG/Fotos/Carpeta/info.txt
D/path: /storage/emulated/0/TFG/Fotos/Cereales/info.txt

The file info.txt is in that path according to my device:

Photo

Jongware
  • 22,200
  • 8
  • 54
  • 100
AMarquez94
  • 277
  • 2
  • 7
  • 16
  • attach the logs details that you are using plus try this method http://stackoverflow.com/questions/20663467/jni-reading-a-text-file-in-c-code-and-returning-to-sdk – Pavneet_Singh Sep 29 '16 at 11:18
  • what is the android version of your android phone ? cuz if it is greater than lollipop than make sure you have implemented permission model – Pavneet_Singh Sep 29 '16 at 11:27
  • @PavneetSingh added the logs details. Will try the method you posted and tell you, thanks :) PS: Android version is 6.0.1 (Marshmallow) – AMarquez94 Sep 29 '16 at 11:27
  • you don't have to change the code , first checkout the update part of answer and implement it if it isn't there – Pavneet_Singh Sep 29 '16 at 11:33
  • @PavneetSingh arg, no, I think it may be the problem, because I only have the permission in the Android Manifest. Will have a look and post the solution if I found it. Thank you very much :) – AMarquez94 Sep 29 '16 at 11:33

1 Answers1

7

The file is not yet opened, you have to call file.open() function to associate the stream with current file before is_open check.

file.open();
 if (!file.is_open()){
        return Object(true); 
    }

Update : The other reason could be that you don't have runtime permission model . try the official docs and this link for precise example

Community
  • 1
  • 1
Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
  • 1
    worked like a charm, thank you very much! (I upvoted your answer, but it says it will not show because I have less than 15 rep points, sorry). – AMarquez94 Sep 29 '16 at 11:48