By raigex
on Tue, 01/22/2013 - 21:08
I have created a new project (since the samples play right) and wanted to build up the app semi from scratch (i used the ImageTargets files as a base). Now I have everything compiling but I have no idea why i get the Unsatisfied link Error for getOpenGleEsVersionNAtive.
Below is my LLScanner code
and below is the error I get./************************************************************************* Author: Piotr Leja* Purpose: QCAR scanner for Lulu and Lala,* Native Renderer Implementation* Date Created Wednesday January 16, 2013** Based On: QCAR Sample Image Targets by QualComm************************************************************************/ #include <jni.h>#include <android/log.h>#include <stdio.h>#include <string.h>#include <assert.h> /*//Dont think I need OpenGL but i will keep it anyway#ifdef USE_OPENGL_ES_1_1#include <GLES/gl.h>#include <GLES/glext.h>#else#include <GLES2/gl2.h>#include <GLES2/gl2ext.h>#endif*/ #include <QCAR/QCAR.h>#include <QCAR/CameraDevice.h>#include <QCAR/Renderer.h>#include <QCAR/VideoBackgroundConfig.h>#include <QCAR/Trackable.h>#include <QCAR/TrackableResult.h>#include <QCAR/Tool.h>#include <QCAR/Tracker.h>#include <QCAR/TrackerManager.h>#include <QCAR/ImageTracker.h>#include <QCAR/CameraCalibration.h>#include <QCAR/UpdateCallback.h>#include <QCAR/DataSet.h> #include "SampleUtils.h" #ifdef __cplusplusextern "C"{#endif // Screen dimensions:unsigned int screenWidth = 0;unsigned int screenHeight = 0; bool switchDataSetAsap = false; // Indicates whether screen is in portrait (true) or landscape (false) modebool isActivityInPortraitMode = false; // Indicate whether Phone supports continus autofocusbool isContinuousAutoOn = false; // Indicate whether Phone supports continus autofocusbool isInfintiyFocusOn = false; //Dataset for current Image Targets//There might be more datasets when we update app at another timeQCAR::DataSet* dataSetLALBookOne = 0; class ImageTargets_UpdateCallback : public QCAR::UpdateCallback{ virtual void QCAR_onUpdate(QCAR::State& /*state*/) { if (switchDataSetAsap) {/*Keeping as reference, for now there will be no update callbacks used to change Datasets switchDataSetAsap = false; // Get the image tracker: QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance(); QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>( trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER)); if (imageTracker == 0 || dataSetStonesAndChips == 0 || dataSetTarmac == 0 || imageTracker->getActiveDataSet() == 0) { LOG("Failed to switch data set."); return; } if (imageTracker->getActiveDataSet() == dataSetStonesAndChips) { imageTracker->deactivateDataSet(dataSetStonesAndChips); imageTracker->activateDataSet(dataSetTarmac); } else { imageTracker->deactivateDataSet(dataSetTarmac); imageTracker->activateDataSet(dataSetStonesAndChips); }*/ } }}; UpdateCallback updateCallback; JNIEXPORT int JNICALLextern "C" Java_net_vproductions_lal_ImageTargets_getOpenGlEsVersionNative(JNIEnv *, jobject){#ifdef USE_OPENGL_ES_1_1 return 1;#else return 2;#endif} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_setActivityPortraitMode(JNIEnv *, jobject, jboolean isPortrait){ isActivityInPortraitMode = isPortrait;} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_switchDatasetAsap(JNIEnv *, jobject){ switchDataSetAsap = true;} JNIEXPORT int JNICALLJava_net_vproductions_lal_ImageTargets_initTracker(JNIEnv *, jobject){ ///LOG("Java_net_vproductions_lal_ImageTargets_initTracker"); // Initialize the image tracker: QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance(); QCAR::Tracker* tracker = trackerManager.initTracker(QCAR::Tracker::IMAGE_TRACKER); if (tracker == NULL) { ///LOG("Failed to initialize Tracker."); return 0; } ///LOG("Successfully initialized Tracker."); return 1;} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_deinitTracker(JNIEnv *, jobject){ ///LOG("Java_net_vproductions_lal_ImageTargets_deinitTracker"); // Deinit the image tracker: QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance(); trackerManager.deinitTracker(QCAR::Tracker::IMAGE_TRACKER);} JNIEXPORT int JNICALLJava_net_vproductions_lal_ImageTargets_loadTrackerData(JNIEnv *, jobject){ ///LOG("Java_net_vproductions_lal_ImageTargets_loadTrackerData"); // Get the image tracker: QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance(); QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>( trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER)); if (imageTracker == NULL) { ///LOG("Failed to load tracking data set because the ImageTracker has not" // " been initialized."); return 0; } dataSetLALBookOne = imageTracker->createDataSet(); if (dataSetLALBookOne == 0) { //LOG("Failed to create a new tracking data."); return 0; } // Load the data sets: if (!dataSetLALBookOne->load("LuluAndLala.xml", QCAR::DataSet::STORAGE_APPRESOURCE)) { //LOG("Failed to load data set for book one."); return 0; } // Activate the data set: if (!imageTracker->activateDataSet(dataSetLALBookOne)) { //LOG("Failed to activate book one dataset."); return 0; } //LOG("Successfully loaded and activated data set."); return 1;} JNIEXPORT int JNICALLJava_net_vproductions_lal_ImageTargets_destroyTrackerData(JNIEnv *, jobject){ //LOG("net_vproductions_lal_ImageTargets_destroyTrackerData"); // Get the image tracker: QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance(); QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*>( trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER)); if (imageTracker == NULL) { //LOG("Failed to destroy the tracking data set because the ImageTracker has not" // " been initialized."); return 0; } if (dataSetLALBookOne != 0) { if (imageTracker->getActiveDataSet() == dataSetLALBookOne && !imageTracker->deactivateDataSet(dataSetLALBookOne)) { //LOG("Failed to destroy the tracking data set Lulu and Lala Book One because the data set " "could not be deactivated."); return 0; } if (!imageTracker->destroyDataSet(dataSetLALBookOne)) { //LOG("Failed to destroy the tracking data set Lulu and Lala Book One."); return 0; } //LOG("Successfully destroyed the data set Lulu and Lala Book One."); dataSetLALBookOne = 0; } return 1;} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_onQCARInitializedNative(JNIEnv *, jobject){ // Register the update callback where we handle the data set swap: QCAR::registerCallback(&updateCallback); // Comment in to enable tracking of up to 2 targets simultaneously and // split the work over multiple frames: // QCAR::setHint(QCAR::HINT_MAX_SIMULTANEOUS_IMAGE_TARGETS, 2);} JNIEXPORT void JNICALLJava_net_vproductions_lal_Renderer_renderFrame(JNIEnv *, jobject){ //LOG("Java_com_qualcomm_QCARSamples_ImageTargets_GLRenderer_renderFrame"); // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Get the state from QCAR and mark the beginning of a rendering section QCAR::State state = QCAR::Renderer::getInstance().begin(); // Explicitly render the Video Background QCAR::Renderer::getInstance().drawVideoBackground(); // Did we find any trackables this frame? for(int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++) { // Get the trackable: const QCAR::TrackableResult* result = state.getTrackableResult(tIdx); const QCAR::Trackable& trackable = result->getTrackable(); //LOG(trackable->getName());//jstring tmpName = env->NewStringUTF(trackable->getName());//env->CallBooleanMethod} QCAR::Renderer::getInstance().end();} voidconfigureVideoBackground(){ // Get the default video mode: QCAR::CameraDevice& cameraDevice = QCAR::CameraDevice::getInstance(); QCAR::VideoMode videoMode = cameraDevice.getVideoMode(QCAR::CameraDevice::MODE_DEFAULT); // Configure the video background QCAR::VideoBackgroundConfig config; config.mEnabled = true; config.mSynchronous = true; config.mPosition.data[0] = 0.0f; config.mPosition.data[1] = 0.0f; if (isActivityInPortraitMode) { ////LOG("configureVideoBackground PORTRAIT"); config.mSize.data[0] = videoMode.mHeight * (screenHeight / (float)videoMode.mWidth); config.mSize.data[1] = screenHeight; if(config.mSize.data[0] < screenWidth) { //LOG("Correcting rendering background size to handle missmatch between screen and video aspect ratios."); config.mSize.data[0] = screenWidth; config.mSize.data[1] = screenWidth * (videoMode.mWidth / (float)videoMode.mHeight); } } else { ////LOG("configureVideoBackground LANDSCAPE"); config.mSize.data[0] = screenWidth; config.mSize.data[1] = videoMode.mHeight * (screenWidth / (float)videoMode.mWidth); if(config.mSize.data[1] < screenHeight) { //LOG("Correcting rendering background size to handle missmatch between screen and video aspect ratios."); config.mSize.data[0] = screenHeight * (videoMode.mWidth / (float)videoMode.mHeight); config.mSize.data[1] = screenHeight; } } //LOG("Configure Video Background : Video (%d,%d), Screen (%d,%d), mSize (%d,%d)", videoMode.mWidth, videoMode.mHeight, screenWidth, screenHeight, config.mSize.data[0], config.mSize.data[1]); // Set the config: QCAR::Renderer::getInstance().setVideoBackgroundConfig(config);} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_initApplicationNative(JNIEnv* env, jobject obj, jint width, jint height){ //LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative"); // Store screen dimensions screenWidth = width; screenHeight = height; // Handle to the activity class: //jclass activityClass = env->GetObjectClass(obj); //LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_initApplicationNative finished");} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_deinitApplicationNative(JNIEnv* env, jobject obj){ //LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_deinitApplicationNative");//Deinit is not needed since no textures are used.} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_startCamera(JNIEnv *, jobject){ //LOG("Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargets_startCamera"); // Select the camera to open, set this to QCAR::CameraDevice::CAMERA_FRONT // to activate the front camera instead. QCAR::CameraDevice::CAMERA camera = QCAR::CameraDevice::CAMERA_DEFAULT; // Initialize the camera: if (!QCAR::CameraDevice::getInstance().init(camera)) return; // Configure the video background configureVideoBackground(); // Select the default mode: if (!QCAR::CameraDevice::getInstance().selectVideoMode( QCAR::CameraDevice::MODE_DEFAULT)) return; // Start the camera: if (!QCAR::CameraDevice::getInstance().start()) return; // Uncomment to enable flash //if(QCAR::CameraDevice::getInstance().setFlashTorchMode(true)) // //LOG("IMAGE TARGETS : enabled torch"); // Uncomment to enable infinity focus mode, or any other supported focus mode // See CameraDevice.h for supported focus modesif(QCAR::CameraDevice::getInstance().setFocusMode(QCAR::CameraDevice::FOCUS_MODE_CONTINUOUSAUTO){isContinuousAutoOn = true; //LOG("AR : enabled infinity focus"); } if(!isContinuousAutoOn && QCAR::CameraDevice::getInstance().setFocusMode(QCAR::CameraDevice::FOCUS_MODE_INFINITY)){isInfintiyFocusOn = true; //LOG("AR : enabled infinity focus");} // Start the tracker: QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance(); QCAR::Tracker* imageTracker = trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER); if(imageTracker != 0) imageTracker->start();} JNIEXPORT void JNICALLJava_net_vproductions_lal_ImageTargets_stopCamera(JNIEnv *, jobject){ //LOG("Java_net_vproductions_lal_ImageTargets_stopCamera"); // Stop the tracker: QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance(); QCAR::Tracker* imageTracker = trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER); if(imageTracker != 0) imageTracker->stop(); QCAR::CameraDevice::getInstance().stop(); QCAR::CameraDevice::getInstance().deinit();} JNIEXPORT jboolean JNICALLJava_net_vproductions_lal_ImageTargets_triggerFocus(JNIEnv*, jobject){if(!isInfintiyFocusOn && !isContinuousAutoOn)return QCAR::CameraDevice::getInstance().setFocusMode(QCAR::CameraDevice::FOCUS_MODE_TRIGGERAUTO) ? JNI_TRUE : JNI_FALSE;return JNI_FALSE;} JNIEXPORT void JNICALLJava_net_vproductions_lal_Renderer_initRendering( JNIEnv* env, jobject obj){ //LOG("Java_net_vproductions_lal_Renderer_initRendering"); // Define clear color glClearColor(0.0f, 0.0f, 0.0f, QCAR::requiresAlpha() ? 0.0f : 1.0f); /* // Now generate the OpenGL texture objects and add settings for (int i = 0; i < textureCount; ++i) { glGenTextures(1, &(textures[i]->mTextureID)); glBindTexture(GL_TEXTURE_2D, textures[i]->mTextureID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textures[i]->mWidth, textures[i]->mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) textures[i]->mData); }ImageTargetsifndef USE_OPENGL_ES_1_1 shaderProgramID = SampleUtils::createProgramFromBuffer(cubeMeshVertexShader, cubeFragmentShader); vertexHandle = glGetAttribLocation(shaderProgramID, "vertexPosition"); normalHandle = glGetAttribLocation(shaderProgramID, "vertexNormal"); textureCoordHandle = glGetAttribLocation(shaderProgramID, "vertexTexCoord"); mvpMatrixHandle = glGetUniformLocation(shaderProgramID, "modelViewProjectionMatrix"); texSampler2DHandle = glGetUniformLocation(shaderProgramID, "texSampler2D"); ImageTargetsendif*/} JNIEXPORT void JNICALLJava_net_vproductions_lal_Renderer_updateRendering( JNIEnv* env, jobject obj, jint width, jint height){ //LOG("Java_net_vproductions_lal_Renderer_updateRendering"); // Update screen dimensions screenWidth = width; screenHeight = height; // Reconfigure the video background configureVideoBackground();} #ifdef __cplusplus}#endif
01-16 13:57:02.797: W/dalvikvm(13765): No implementation found for native Lnet/vproductions/lal/ImageTargets;.getOpenGlEsVersionNative ()I......01-16 13:57:02.801: E/AndroidRuntime(13765): FATAL EXCEPTION: main01-16 13:57:02.801: E/AndroidRuntime(13765): java.lang.UnsatisfiedLinkError: getOpenGlEsVersionNative01-16 13:57:02.801: E/AndroidRuntime(13765): at net.vproductions.lal.ImageTargets.getOpenGlEsVersionNative(Native Method)01-16 13:57:02.801: E/AndroidRuntime(13765): at net.vproductions.lal.ImageTargets.getInitializationFlags(ImageTargets.java:364)01-16 13:57:02.801: E/AndroidRuntime(13765): at net.vproductions.lal.ImageTargets.onCreate(ImageTargets.java:347)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.app.ActivityThread.access$1500(ActivityThread.java:117)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.os.Handler.dispatchMessage(Handler.java:99)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.os.Looper.loop(Looper.java:130)01-16 13:57:02.801: E/AndroidRuntime(13765): at android.app.ActivityThread.main(ActivityThread.java:3683)01-16 13:57:02.801: E/AndroidRuntime(13765): at java.lang.reflect.Method.invokeNative(Native Method)01-16 13:57:02.801: E/AndroidRuntime(13765): at java.lang.reflect.Method.invoke(Method.java:507)01-16 13:57:02.801: E/AndroidRuntime(13765): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)01-16 13:57:02.801: E/AndroidRuntime(13765): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)01-16 13:57:02.801: E/AndroidRuntime(13765): at dalvik.system.NativeStart.main(Native Method)
I use ImageTargets.Java as a base (but i have changed so it loads the proper libraries).
Hi raigex, the unsatisfied
Hi raigex,
the unsatisfied link error usually means that you did not rebuilt the C++ code (using ndk-build) or perhaps you did not refresh the project in Eclipse after compiling the native code.
Are you sure you took those steps ?
Yes i took those steps, but i
Yes i took those steps, but i figured out the problem. I had commented out the second LOCAL_SRC_FILES to see if my paths were properly created (../../etc) and when i added my c++ code i never commented them back in.
OK, glad that you figured
OK, glad that you figured that out.