Log in or register to post comments

Native activity

August 14, 2014 - 3:36am #1

I'm trying to integrate Vuforia in our application that is a pure native activity. I have problem setting up Vuforia.

I do this in my main thread:

            QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
            QCAR::Tracker* tracker = trackerManager.initTracker(QCAR::ImageTracker::getClassType());
tracker is always becomming nullptr.

The only code we have in Java is aa activity thats starts before the our native activity and that loads the Vuforia.so

My question is, is it at all possible to use Vuforia without any Java code??

 

 

Native activity

September 8, 2014 - 2:05am #11

Here are the initialization steps (with comments, and not including any rendering / OpenGL code, as it is not relevant here), that you can check against yours:

1 - Initialize QCAR:
This is normally done in Java (in the Activity init code), but as I understand from your first couple of posts, you managed to execute this from C++ via JNI (which is fine, as long as you pass a pointer to your Native Activity to the setInitParameters):
 
QCAR.setInitParameters( pointer_to_your_activity, QCAR.GL_20)    (note: in native code, QCAR.GL_20 is just an integer  = 2, so you can put 2 in there)
 
perform do / while loop like:
int progress;
do
{
  progress = QCAR.init() 
} while( progress < 100 );
 
(i.e. call QCAR.init multiple times until exiting loop when progress == 100)
 
Also, check whether "progress" returns a negative (< 0) value;   that would indicate an initialization error 
 
When QCAR init is done (progress reached 100 and no errors), ==> proceed with next step:
 
 
2 - Initialize Image Tracker:
 
QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
QCAR::Tracker* tracker = trackerManager.initTracker(QCAR::ImageTracker::getClassType());
if (tracker == NULL)
{
    LOG("Failed to initialize ImageTracker.");
}
 
3 - Create and Load the Datasets:
QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>(
                    trackerManager.getTracker(QCAR::ImageTracker::getClassType()));
if (imageTracker == NULL)
{
    LOG("Failed to load tracking data set because the ImageTracker has not"
        " been initialized.");
    return 0;
}

dataSetStonesAndChips = imageTracker->createDataSet();
if (dataSetStonesAndChips == 0)
{
    LOG("Failed to create a new tracking data.");
    return 0;
}

if (!dataSetStonesAndChips->load("StonesAndChips.xml", QCAR::STORAGE_APPRESOURCE))
{
    LOG("Failed to load data set.");
    return 0;
}

In the code above, of course, you will use the Path to your actual XML dataset (e.g. on SD card or wherever it is)

 

Beyond that, if this still does not work, you may want to try the approach described here step-by-step (although this is using some Java code to initialize the main activity):

https://developer.vuforia.com/resources/dev-guide/android-native-activities

 

 

Native activity

September 7, 2014 - 10:42am #10

I know only the second one is correct, I just wanted to show with 1 and 2 that there is a difference in the error message if the file is existent or not.

And yes I have the  permission READ_EXTERNAL_STORAGE (and WRITE_EXTERNAL_STORAGE) in my manifest.

As said I'm sure the file is there, it is indeed existent when testing with your own API.

This code I tried:

QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>(trackerManager.initTracker(QCAR::ImageTracker::getClassType()));
bool xmlFileExists = QCAR::DataSet::exists("/sdcard/Tarmac.xml", QCAR::STORAGE_ABSOLUTE);
bool datFileExists = QCAR::DataSet::exists("/sdcard/Tarmac.dat", QCAR::STORAGE_ABSOLUTE);
QCAR::DataSet* myDataSet = imageTracker->createDataSet();
bool  loaded = myDataSet->load("/sdcard/Tarmac.xml", QCAR::STORAGE_ABSOLUTE);

So it has an imageTracker initialized, it is not NULL. xmlFileExists==true  and datFileExists==true but loaded==false.

 

Is there anything else in the environment your system requires? Maybe something in java that is not setup because java is not initialized the same way as a java-activity?

Do you think you can provide me with a complete minimalistic native-activity example with your C++ API ?

 

 

 

Native activity

September 7, 2014 - 10:02am #9

When loading a Dataset, you must specify the .XML filename; out of your 4 examples, only this line is correct:

bool b2 = dataSet2->load("/sdcard/Tarmac.xml", QCAR::STORAGE_ABSOLUTE);

because in the above you are (correctly) pointing to Tarmac.xml (i.e. filename with extension .XML);  

all other filenames (e.g. with extension .DAT and /or without extension are not valid and will result in dataset not loaded error).

Can you try again this one only:

bool b2 = dataSet2->load("/sdcard/Tarmac.xml", QCAR::STORAGE_ABSOLUTE);

after making sure that the file is there and that you have the Android permission READ_EXTERNAL_STORAGE enabled in the Andoid Manifest ?

Also, the Image Tracker must be initialized before you attempt to create or load a Dataset (you may also want to double-check this to be sure.)

 

Native activity

September 6, 2014 - 2:13pm #8

Yes, that is pretty much eqvivalent to what I'm doing. One difference is that I do it in C++.

I tried to put the files Tarmac.xml and Tarmac.dat on the sdcard and did the following:

                QCAR::DataSet* dataSet1 = imageTracker->createDataSet();
                bool b1 = dataSet1->load("/sdcard/TarmacDontExist.xml", QCAR::STORAGE_ABSOLUTE);

                QCAR::DataSet* dataSet2 = imageTracker->createDataSet();
                bool b2 = dataSet2->load("/sdcard/Tarmac.xml", QCAR::STORAGE_ABSOLUTE);

                QCAR::DataSet* dataSet3 = imageTracker->createDataSet();
                bool b3 = dataSet3->load("/sdcard/Tarmac.dat", QCAR::STORAGE_ABSOLUTE);

                QCAR::DataSet* dataSet4 = imageTracker->createDataSet();
                bool b4 = dataSet4->load("/sdcard/Tarmac", QCAR::STORAGE_ABSOLUTE);
 

All booleans are false and i get this in the log:

I/AR      (14943): ImageTracker: Successfully created dataset
E/AR      (14943): Failed to load dataset '/sdcard/TarmacDontExist.xml'.
I/AR      (14943): ImageTracker: Successfully created dataset
E/AR      (14943): Dataset /sdcard/Tarmac.dat not loaded successfully. Please redownload your dataset from the Target Management System.
I/AR      (14943): ImageTracker: Successfully created dataset
E/AR      (14943): Dataset /sdcard/Tarmac.dat not loaded successfully. Please redownload your dataset from the Target Management System.
I/AR      (14943): ImageTracker: Successfully created dataset
E/AR      (14943): Failed to load dataset '/sdcard/Tarmac'.

So there is a difference trying to load a file that doesn't exist and one that do exist. Can you check your code on your side to see what can trigger that "Dataset xxx.dat not loaded".. message?

 

Native activity

September 4, 2014 - 8:45am #7

Here I am.  

I have made the following test, using the Native Image Targets sample project as a starting point (see sample project "ImageTargetsNative-3-0-5").

1. Before starting the AR activity, I copy the Tarmac.xml and Tarmac.dat files from the Asset directory into the internal storage data path, using this simple code in the AboutScreen.java class:

private void startARActivity()
    {
        copyFileToInternalStorage("Tarmac.xml");
        copyFileToInternalStorage("Tarmac.dat");
        
        Intent i = new Intent();
        i.setClassName(mClassToLaunchPackage, mClassToLaunch);
        startActivity(i);
    }
    
    private void copyFileToInternalStorage(String filename)
    {
        AssetManager assetManager = getAssets();
        
        InputStream in = null;
        OutputStream out = null;
        try
        {
            in = assetManager.open(filename);
            out = new FileOutputStream(new File(getFilesDir(), filename));

            byte[] buffer = new byte[1024];
            int read;
            while ((read = in.read(buffer)) != -1)
            {
                out.write(buffer, 0, read);
            }
            in.close();
            in = null;
            out.flush();
            out.close();
        }
        catch (Exception e)
        {
            Log.e(LOGTAG, "Failed to copy file");
        }
    }

 

This should be equivalent to what you also do, i.e. copying the dataset files at startup (both the .DAT and the .XML)

2. In ImageTargets.cpp, I load the Tarmac dataset with this line:

if (!dataSetTarmac->load("/data/data/com.qualcomm.QCARSamples.ImageTargets/files/Tarmac.xml",
              QCAR::STORAGE_ABSOLUTE))
    {
        LOG("Failed to load data set.");
        return 0;
    }

 

As you can see from the example path above, I use "/data/data/com.qualcomm.QCARSamples.ImageTargets/files/Tarmac.xml" which corresponds to the private internal data storage path of the sample app.

This works (the dataset gets loaded); 

perhaps you may want to try the same test, i.e. using the code above in the ImageTargetsNative example, and see if it works for you too.

 

Native activity

September 4, 2014 - 8:12am #6

Right. Since you use Internal path, have you tried QCAR::STORAGE_APP instead of QCAR::STORAGE_ABSOUTE  ?  

In the meantime, let me try a quick test with internal path and I'll get back to you.

 

Native activity

September 4, 2014 - 7:31am #5

 

I didn't have but tried it now and it doesn't make any difference. I can indeed load other files in the same directory.

Also the file is not on sd-card. We extract the files into the application folder at the beginning of our application.

I believe the path where we store the dataset is gotten from ((struct android_app*)state)->activity->internalDataPath

 

 

 

 

Native activity

September 3, 2014 - 12:24pm #4

Hi,

have you added the Android permission READ_EXTERNAL_STORAGE to your AndroidManifest ?

This permission is required in order to access a file stored on the external storage path (e.g. the SD card).

Also, have you tried placing the Datasets in a different file path, e.g. one of the following:

  • /sdcard/my_data_sets_directory_name/
  • /storage/sdcard0/my_data_sets_directory_name/
  • /sdcard/Android/data/your.app.package.name/files/
  • /storage/sdcard0/Android/data/your.app.package.name/files/

?

I have just tried loading StonesAndChips from /sdcard/my_datasets/ using the same C++ code and it seems to work properly.

Perhaps the issue could occur on some specific file paths, in which case we need to understnad why that happens.

Native activity

August 28, 2014 - 1:42pm #3

I didn't find the setInitParameters and init in the C++ API. I did however call the Java functions from C++ using JNI. And it actually seems to solve that problem.

Now I'm stuck on another problem trying to load the dataset.

bool b1 = QCAR::DataSet::exists("/data/data/com.eonreality.android.eonviewer/files/StonesAndChips.xml", QCAR::STORAGE_ABSOLUTE);

bool b2 = QCAR::DataSet::exists("/data/data/com.eonreality.android.eonviewer/files/StonesAndChips.dat", QCAR::STORAGE_ABSOLUTE);

bool b3 = dataSet->load("/data/data/com.eonreality.android.eonviewer/files/StonesAndChips.xml", QCAR::STORAGE_ABSOLUTE));

(The paths is of course not hardcoded like this, I show them like this for readability)

dataSet->load() fails and  b3==false. Bbut b1&&b2==true. So the file is definitely there.

I get this in the adb log:
E/AR      ( 9835): Dataset /data/data/com.eonreality.android.eonviewer/files/StonesAndChips.dat not loaded successfully. Please redownload your dataset from the Target Management System.

 
Any idea? I get the feeling the error maybe is a bit misleading and something else failes within the call but the actuall loading of the .dat file.
 
 

 

Native activity

August 19, 2014 - 2:30pm #2

Are you calling the QCAR init() and setInitParameters() before initializing the Tracker?

https://developer.vuforia.com/resources/api/comqualcommqcarqcar-class-reference-0

 

Log in or register to post comments