12

I've to add the native files .so, .mk, .sh, .cpp in my Project in Android Studio. In eclipse .so files are added in libs folder and other files in jni and obj folder and all working fine. But in Android studio As I've added .so files in jniLibs folder and made changes in .gradle file as below

 ndk{
                abiFilters 'armeabi', 'armeabi-v7a', 'x86'
            }
sourceSets.main {
        jniLibs.srcDir 'src/main/libs' //set libs as .so's location instead of jniLibs
        jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
    }

Below is the structure of my project and the files I need to add. There are jni and obj folder that contain the native code and I've to use that. Native files under jni, obj and jniLibs folders

I've seen the links available but they are outdated and nothing worked. Any help is appreciated.

Log after after doing the below changes:

sourceSets.main {
        jniLibs.srcDir 'src/main/libs' //set libs as .so's location instead of jniLibs
        jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
    }
    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }

Log:

Error while executing 'E:\Android_SDK\ndk-bundle\ndk-build.cmd' with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=E:\folder\sampleapp\app\src\main\jni\Android.mk NDK_APPLICATION_MK=E:\folder\sampleapp\app\src\main\jni\Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=1 APP_PLATFORM=android-16 NDK_OUT=E:/folder/app/build/intermediates/ndkBuild/debug/obj NDK_LIBS_OUT=E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
md "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib\armeabi-v7a" >NUL 2>NUL || rem
copy /b/y "E:\Android_SDK\ndk-bundle\build\\..\prebuilt\android-arm\gdbserver\gdbserver" "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib\armeabi-v7a\gdbserver" > NUL
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe [armeabi-v7a] "Gdbserver      ": "[arm-linux-androideabi] E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdbserver"
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe [armeabi-v7a] "Gdbsetup       ": "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup"
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe "directory E:/Android_SDK/ndk-bundle/build//../platforms/android-16/arch-arm/usr/include E:/folder/app/src/main/jni E:/Android_SDK/ndk-bundle/build//../sources/cxx-stl/system" >> E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe "set solib-search-path E:/folder/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a" > E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup
process_begin: CreateProcess(NULL, "", ...) failed.
make: *** No rule to make target `E:/folder/app/src/main/jni/SerialPort.c', needed by `E:/folder/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs-debug/serial_port/SerialPort.o'.  Stop.
Build command failed.
Error:executing external native build for ndkBuild E:\folder\sampleapp\app\src\main\jni\Android.mk
Build command failed.
Error while executing 'E:\Android_SDK\ndk-bundle\ndk-build.cmd' with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=E:\folder\sampleapp\app\src\main\jni\Android.mk NDK_APPLICATION_MK=E:\folder\sampleapp\app\src\main\jni\Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=0 APP_PLATFORM=android-16 NDK_OUT=E:/folder/app/build/intermediates/ndkBuild/release/obj NDK_LIBS_OUT=E:\folder\sampleapp\app\build\intermediates\ndkBuild\release\lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
make: *** No rule to make target `E:/folder/app/src/main/jni/SerialPort.c', needed by `E:/folder/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/serial_port/SerialPort.o'.  Stop.
process_begin: CreateProcess(NULL, "", ...) failed.
Error:executing external native build for ndkBuild E:\folder\sampleapp\app\src\main\jni\Android.mk
Naresh Sharma
  • 4,323
  • 7
  • 48
  • 68
  • 1
    https://developer.android.com/studio/projects/add-native-code.html Btw, don't post screenshots of code; post the code as text. – Michael May 30 '17 at 09:01
  • @Michael thanks for suggestion, but I don't thing the above code structure reveal anything. It's just to showing the project folder structure. :) – Naresh Sharma Jun 13 '17 at 05:58
  • Your screenshot does not show `jni.srcDirs = []`. If you have prebuilt libraries, you don't need `externalNativeBuild { ... }` block at all. From your screenshot again, it doesn't look like you have the `E:\folder\sampleapp\app\src\main\jni\Android.mk` file. To use the file structure on that picture, you should use `ndkBuild { path 'jni/Android.mk' }` – Alex Cohn Jun 13 '17 at 13:55
  • @AlexCohn I've added the jnisrcDirs=[] later on, after capturing that screen shot. The path for external build I've given is src/main/jni/Android.mk. In logcat I've just changed the name of the real project and folder. – Naresh Sharma Jun 13 '17 at 18:24

4 Answers4

8

First of all, make sure your source location, suites example. You have some issues. All native files should be in src/main/

../src/main
.........../jni # your cpp, header and mk files
.........../jniLibs # your folders with all libs
.........../java # other code

Then, make sure, you load your libs in static field before any Native usage, in Activity, Application, etc.

private static final String LIB_NAME = "libserial_port";
private static final String LIB_NAME_1 = "libzqcom";
static {
        System.loadLibrary(LIB_NAME);
        System.loadLibrary(LIB_NAME_1);
    }

UPD 1:

Make sure you already installed Android NDK Source for Native Android project.

From Android SDK Settings

GensaGames
  • 5,538
  • 4
  • 24
  • 53
  • App Crashes immediately after adding this System.loadLibrary() code – Naresh Sharma Jun 13 '17 at 05:43
  • @NareshSharma There is only one way to load native Libs, via`System.loadLibrary()`, I suppose you doing something wrong, and received Linkify Exception, because Source cannot find you library with that name. – GensaGames Jun 13 '17 at 07:46
  • NDK is downloaded and path given in local.properties file – Naresh Sharma Jun 13 '17 at 19:01
  • @NareshSharma Then I don't see problem, I build every project with my C/C++ source with any problem. Just with official doc, nothing special https://developer.android.com/studio/projects/add-native-code.html – GensaGames Jun 13 '17 at 20:03
  • Any changes we need to do for .mk file in gradle ? – Naresh Sharma Jun 13 '17 at 21:13
  • @NareshSharma Please check, you loaded your .mk files in Gradle. Here is probably same issue. https://stackoverflow.com/questions/27833530/how-to-use-my-own-android-mk-file-with-android-sudio – GensaGames Jun 14 '17 at 07:47
4

Adding on to GensaGames' answer, if you have a .mk file you are using to build the native libraries, in order to add it to the build process you must specify the path to that file in the module-level build.gradle file, in the android{ } block:

externalNativeBuild {
    ndkBuild {
        path 'path/to/Android.mk'
    }
}

As a note, the directory structure suggested by GensaGames isn't strictly necessary for Android Studio - you can put your .mk and .cpp files anywhere you like as long as you specify their directory in build.gradle or Android.mk.

Andrew Farm
  • 178
  • 1
  • 14
3

For native development, you should have main/jni folder which is you should put your libraries and native sources inside it and build them in this folder. Before you should create two files, Android.mk and Application.mk. Android.mk is for building native libs (modules), adding flags and etc. You can build static and shared libraries in Android.mk. When you build your C sources, it creates static library (.a). But these libraries not for using in Java side. You can only use them for creating shared libraries (.so). For this, you should build your C++ sources, and if you want, you can add your static libraries to this.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))

LOCAL_MODULE := myLibrary

LOCAL_SHARED_LIBRARIES := cpufeatures opencv_imgproc opencv_core 

LOCAL_C_INCLUDES := $(LOCAL_PATH)/c-files

LOCAL_SRC_FILES := $(LOCAL_PATH)/myJni.cpp

include $(BUILD_SHARED_LIBRARY)

--- 1st line returns main/jni path.

--- 2nd line clear all old LOCAL_*** variables.

--- 3th line build modules for each arch's which are declared there.

--- 4th line shows module name, when you build it, NDK automatically add lib and .so extensions to it (libmyLibrary.so).

--- 5th line adds other shared libraries, which you need their sources in your native sources.

--- 6th line adds C files to your module.

--- 7th line shows your C++ sources which you try to build.

--- 8th line is building command.

In Application.mk you can give commands something like, your project in release mode or debug mode. And you should give arch's in this file. For example APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 and etc.

When you try to build libraries and use them in java side, you should do some operations.

1.Check your ndk path in local.properties file in project folder. It shows ndk-bundle path for building makefiles.

ndk.dir=/Users/../Library/Android/sdk/ndk-bundle

2.Check build scripts in gradle file. This script shows where shared libs should be located:

sourceSets.main {
    jni.srcDirs = []
    jniLibs.srcDir 'src/main/libs'
}

3.And show your makefile path to gradle.

externalNativeBuild {
   ndkBuild {
      path 'src/main/jni/Android.mk'
   }
}

I think my answer will help you for understanding some details. For addition, you can take a look these answers also.

  1. For calling native methods: Enter!
  2. For linking shared libraries: Enter!
  3. Answer copied from my other answer: Enter!
JavadKhan
  • 625
  • 6
  • 18
2

I think I've reproduced the error in Android Studio using a simple JNI project. The thing that triggered this specific error ("make: *** No target...") for me was having an incorrect path to one of the source files in Android.mk. (If the paths are correct, the build should succeed; if you leave a source file out completely, you'll get a linker error.) For example, if I specify an incorrect path to one of my sources, this error happens:

make: *** No rule to make target `/Users/afarm/AndroidStudioProjects/Mktest/app/src/main/cp/stringdep.cpp', needed by `/Users/afarm/AndroidStudioProjects/Mktest/app/build/intermediates/ndkBuild/debug/obj/local/armeabi/objs-debug/native-lib/src/main/cp/stringdep.o'.  Stop.

which looks like the error you described above. Android.mk is not finding your SerialPort.c, so I would guess the path to SerialPort.c stored Android.mk is incorrect. Keep in mind that the paths stored in Android.mk are relative to the Android.mk file itself, not to the root directory.

Andrew Farm
  • 178
  • 1
  • 14