Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Link .so library in android studio project

As the title suggests I am trying to link a native .so to an android studio project. I have gone through the docs in android developer website and some more articles but unsuccessful in connecting the .so file with the project.

Whenever I try to run the code I get the following error

CMake Error: The following variables are used in this project, but they are set to NOTFOUND. Please set them or make sure they are set and tested correctly in the CMake files: testlib

Here is my CMake file

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

add_library(testlib SHARED IMPORTED)

set_property(TARGET testlib PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so")

#find_path(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/RemoteDesktop.h)
find_library(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so)

#add_library(remote SHARED IMPORTED)

#set_target_properties(remote PROPERTIES IMPORTED_LOCATION libs/${ANDROID_ABI}/libremotedesktop_client.so )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib}

                       ${testlib})

target_include_directories()

I have four .so files each for arm64, armeabi, armeabi-v7a, x86. I have harcoded the armeabi-v7a lib in the path, android studio is throwing the above mentioned error when I do that. My actual aim is to dynamically load the library based on the chip in the phone. I am pretty sure that my current code is not achieving that.

Here are my queries

  1. How to solve the error that I am getting? I have tried giving both relative and absolute path but to no avail I am getting the same error.

  2. How do I add a .so and a .h file into a native android studio project? That has variations based on the chip on which the code is running?

  3. When I directly add the .h file to the native folder I can reference the classes and functions in that header in my C code but I am unable to run the code. I have a getInstance() method in the .h file. Whenever I call the getInstance() function it says undefined refernce to getInstance(). What I understand from that is the '.h' file is linked correctly but the definition of the function of the .h files which are actually present in the .so files are not linked. I believe this will be solved if question 1 and 2 are answered.

  4. Is it necessary for all native android projects to have a .mk file? I didn't add one to my project and think it might be one of the cause for the error that I am getting.

like image 651
Nirmal Raj Avatar asked Feb 04 '18 18:02

Nirmal Raj


2 Answers

You don't need find_library in your case. For log, the library is resolved by NDK for you; for libremotedesktop_client.so, you know the exact path.

Here is the CMakeLists.txt that will work for you:

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

add_library(remote SHARED IMPORTED)

set_property(TARGET remote PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/${ANDROID_ABI}/libremotedesktop_client.so")

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       log

                       remote)

Note that using full path (E:/project…) in CMake script is not the best practice; you probably can express the path to this library somehow relative to the path of your CMakeLists.txt, which is ${CMAKE_CURRENT_SOURCE_DIR}.

like image 107
Alex Cohn Avatar answered Nov 01 '22 04:11

Alex Cohn


1-2). First of all, add set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) at the start of your CMakeLists.txt (just after cmake_minimum_required(...)) to allow another search paths for libraries. After this you can find lib just using standard find_library:

find_library(FOO_LIBRARY
         foo # Lib's full name in this case - libfoo.so
         PATHS path/to/lib/)
if (NOT FOO_LIBRARY)
    message(FATAL_ERROR "Foo lib not found!")
endif()

You can use variable ANDROID_ABI to get particular library version, if directory with libraries organised in this way:

- path/to/lib
       - armeabi-v7a
           - libfoo.so
       - arm64-v8a
           - libfoo.so
       - x86
           - libfoo.so
       - x86_64
           - libfoo.so

So, search path in this case:path/to/lib/${ANDROID_ABI}/

To include headers in project just use include_directories:

include_directories(path/to/headers)

4). .mk files only needed if you use ndk-build (so you don't need any)

like image 44
Van der Deken Avatar answered Nov 01 '22 06:11

Van der Deken