Android Studio "Current NDK support is deprecated" - android

As of Jan 2015 the NDK support for Android studio is still unusable.
A cryptic message says: "Alternative will be provided in the future."
I'd like to know what's gradle/google direction on this is since it's impossible to plan a proper development plan at the moment.
Version 0.7+: They suggested to still use ndk-build / ant
Version 0.8+: They've introduced a minimal NDK support
Version 1.0.0: It looked like NDK support was going to be official
Version 1.0.2: It now looks like NDK support is deprecated.
My questions are:
Is everyone reverting to ndk-build and hand made android.mk files?
Is anyone using the currently deprecated method on 1.0.0+ (gradle ndk support) on a serious size project?
What sort of direction the "Alternative will be provided in the future" would go? Is is possible for any insider to answer that without breaking any company rules?
Edit: it's not a duplicate because it was referring to the evolution of Android Studio and NDK, the other question refers to a very ancient version of Android Studio as I've detailed in my post the NDK support has changed drastically from version to version without a clear direction, up to now with the release of 1.3

Update from Google I/O 2015
Android Studio v1.3 Preview - We are releasing a new version of Android
Studio. Most notable is a much requested feature from our Android NDK
& game developers: code editing and debugging for C/C++ code. Based on
JetBrains Clion platform, the Android Studio NDK plugin provides
features such as refactoring and code completion for C/C++ code
alongside your Java code. Java and C/C++ code support is integrated
into one development experience free of charge for Android app
developers. Update to Android Studio v1.3 via the Canary channel and
let us know what you think.
Source from android developers blog here.
New Update 30/7/2015 -> Android Studio v1.3 Released
As a part of the Android 1.3 stable release, we included an Early
Access Preview of the C++ editor & debugger support paired with an
experimental build plugin. See the Android C++ Preview page for
information on how to get started. Support for more complex projects
and build configurations is in development.
Quoted from android developers blog here.
Added Features:
Code completion
Code navigation (go to declaration, jump between header and
implementation, etc)
Quick fixes
Intentions
Refactoring
Source format
Debugging
...
For steps on how to use it, look here.

I invoke the command line, not sure where I got this from, it's basically your first option, reverting to ndk-build with hand made android.mk. Fine if you don't want to control ndk abiFilters by product flavour.
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
ndk {
moduleName "glues"
}
}
sourceSets.main {
jniLibs.srcDir 'src/main/libs' //set .so files location to libs
jni.srcDirs = [] //disable automatic ndk-build call
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'-j', Runtime.runtime.availableProcessors(),
'all',
'NDK_DEBUG=1'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'clean'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
}
I only see those warnings if I setup abiFilter on the productFlavors:
productFlavors {
x86 {
ndk {
abiFilter "x86"
}
}
mips {
ndk {
abiFilter "mips"
}
}
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
}
arm {
ndk {
abiFilter "armeabi"
}
}
fat
}
Note, older gradle plugin versions used android.plugin.ndkFolder rather than android.ndkDirectory. For more info, see: http://tools.android.com/tech-docs/new-build-system/migrating-to-1-0-0

NDK will be fully supported since Android Studio 1.3, including native debugging.

android.useDeprecatedNdk=true
in your gradle.properties

Related

How can I codesign a 64-bit Android APK using the Gradle Experimental Plugin?

I am developing a Android apps using Open Frameworks, a C++ framework which supports Android. Its Android projects use the Gradle experimental plugin to allow C++. I have been able to get these to build unsigned APK's that run just fine (using Android Studio 2.3.2, 3.0, 3.5 or 3.5.1, Experimental Gradle Plugin 0.9.3, and Gradle distribution 3.3.0). But now I need to codesign them and include 64-bit versions to post them to the Android Store.
The Gradle Experimental Plugin has always required a specific single version of Gradle distribution for each of its own versions. And the current doc page for the plugin says that we can "keep using experimental plugin 0.11.0 with Android Studio 3.0 or later", but I seem to be blocked from code-signing by the above in Android Studio 3.5 and 3.5.1.
When I try to use the latest versions of Android Studio (version 3.5 or 3.5.1) to "Generate Signed APK", I get stopped by "Gradle version 4.1 is required.".
When I try to use older versions of Android Studio (version 2.3.2 or 3.0) to "Generate Signed APK", I can build 32-bit codesigned APKs, but I don't know how to build 64-bit APKs. The documentation I have found doesn't seem to apply to the Gradle files I have from Open Frameworks.
Notes on my attempts to get a handle on this:
(As I think I understand it, Gradle Plugin version is different from Gradle distribution version as mapped in this table.)
The only source I have found anywhere for what version of Gradle distribution to use with Gradle Experimental plugin 0.11.0, is this answer to a related question. I asked the answerer what version of Android Studio they were using and they said 3.1, but did not mention codesigning (I've now asked them about that).
It looks like the "Android Gradle Plugin" version is always the same as the Android Studio version, so there seems to be no way to run Android Gradle Plugin version 3.0 with Android Studio 3.5.1, correct?
So based on the above, I tried:
Android Studio (and therefore Gradle Plugin version) 2.3.2 with Experimental Gradle 0.9.3 using Gradle distribution 3.3.0 (codesigns 32-bit APKs - don't know how to do 64-bit)
Android Studio (and therefore Gradle Plugin version) 3.0.0 with Experimental Gradle 0.9.3 using Gradle distribution 3.3.0 (codesigns 32-bit APKs - don't know how to do 64-bit)
Android Studio (and therefore Gradle Plugin version) 3.0.0 with Experimental Gradle 0.11.0 using Gradle distribution 4.1.0 - I get a Gradle error:
*Gradle sync failed: Exception thrown while executing model rule: BaseComponentModelPlugin.Rules#createVariantData(ModelMap<AndroidBinaryInternal>, ModelMap<AndroidComponentSpec>, TaskManager) > afterEach()
Consult IDE log for more details (Help | Show Log) (21s 58ms)*
I found supposed documentation of how to create 64-bit signed APKs with Gradle HERE, but the format suggested for listing ABI filters:
ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
Resulted in an error, and Open Frameworks' project build.gradle tries to include all ABIs as seen in the android.productFlavors section near the bottom of the build.gradle as shown below:
def ofRoot(){ return '../../../' }
// Load common functions
apply from: ofRoot()+"libs/openFrameworksCompiled/project/android/common-functions.gradle"
buildscript {
apply from: "../../../libs/openFrameworksCompiled/project/android/ndk-verify.gradle"
repositories {
jcenter()
}
dependencies {
// Using the gradle-experimental version that supports c++
classpath 'com.android.tools.build:gradle-experimental:0.9.3'
}
}
allprojects {
repositories {
jcenter()
}
}
apply plugin: 'com.android.model.application'
model {
android {
// openFrameworks currently only supports compiling against SDK 19
compileSdkVersion = 23
buildToolsVersion = "25.0.3"
defaultConfig.with {
minSdkVersion.apiLevel = 23
targetSdkVersion.apiLevel = 28
versionCode = 4
versionName = "0.1.1"
}
}
android.ndk {
moduleName = ofAppModuleName()
toolchain = buildToolchain()
stl = compilerStl()
platformVersion = "21"
}
android.sources {
main {
jni {
source {
srcDirs= appSrcDirs(ofRoot())
includes = srcIncludes(ofRoot())
excludes = srcExcludes(ofRoot())
}
// Link to openFrameworks
dependencies {
project ":openFrameworksProject" linkage "static"
}
}
manifest {
source {
srcDirs = [ "." ]
}
}
res {
source {
srcDirs = [ "res" ]
}
}
java {
source {
srcDirs = [ "srcJava" ]
}
}
aidl {
source{
srcDirs = ['srcJava']
}
}
renderscript{
source{
srcDirs = ['srcJava']
}
}
jniLibs {
source {
srcDirs = ['libs']
}
}
assets {
source {
srcDirs = ['bin/data'] + addonData(ofRoot())
}
}
}
}
android.lintOptions {
abortOnError = false
}
android.buildTypes {
release {
minifyEnabled = false
}
}
// Setup the different types of flavors (arm / x86),
// and add linker flags based on that
android.productFlavors {
getAbis().each { abi ->
create(getFlavorName(abi)) {
ndk {
abiFilters.add(abi)
cppFlags.addAll(coreCppFlags(abi, ofRoot()))
cppFlags.addAll(addonCppFlags(abi, ofRoot()))
ldLibs.addAll(coreLdLibs(abi, ofRoot()))
ldLibs.addAll(addonLdLibs(abi, ofRoot()))
ldFlags.addAll(coreLdFlags(abi, ofRoot()))
ldFlags.addAll(addonLdFlags(abi, ofRoot()))
}
}
}
}
}
dependencies {
addonJavaDependencies(ofRoot()).each { dep ->
compile(project(path: dep[1] ))
}
compile project(path: ':ofAndroidLib')
}
But this results in only 32-bit Arm and 386 ABI options in the codesign APK wizard.
Can anyone tell me how to build a codesigned 64-bit APK using Android Studio (any version) for the Experimental plugin?
There are tools to sign apk using the command prompt and using zipalign. Here's the Documentation
https://developer.android.com/studio/build/building-cmdline#sign_manually
I believe that zipaline will still work using the experimental.
or you can use a 3rd party app that can sign 64-bit apps like this
https://github.com/patrickfav/uber-apk-signer
this plugin signs application with 64-bit architecture.
I managed to eventually get it to work after many days of head-banging, with help on the Open Frameworks forum. It involved not just code-signing but using a version of OpenFrameworks that supports 64-bit builds, and a large number of specific settings and steps.
My notes on the steps, versions and settings that finally worked are here: https://forum.openframeworks.cc/t/notes-on-steps-i-took-to-successfully-get-a-64-bit-apk-published-to-the-google-app-store/33722
Meanwhile, if anyone has any other useful information the subject, please share it in an answer here. I'll give the bounty to the most useful/relevant answer other than mine.

How to include a .so library and .c files in Android Studio 1.5

How can I add a .so library in Android Studio and make calls to it through a .c file with native code?
I have googled for a week and I've tried every posible solution I've found but nothing.
The sites are this, this, this, this, and more...
I arrived to make calls to a native .c file but I cannot include the .so library because Android studio cannot find it.
I don't want to use the new experimental gradle yet.
The environment configuration is the next one:
Android Studio 1.5
Gradle 2.8
Android plugin version 1.3.0
JDK 1.8.0
This is part of my code and gradle configuration:
GRADLE FILE
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
....
ndk {
moduleName "ffmpegkit"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
PROJECT STRUCTURE
INCLUDE STATEMENTS IN .C FILE
As you can see, "libavcodec.so" is not found but the project structure is the correct according to some solutions I've found.
Does anybody know how can I solve this problem and use these .so libraries with .c files?
Thank you very much!
I assume your .c file is somewhere under ffmpegkit directory in your project. You copied the ffmpeg binaries to your project's jniLibs, too. So far so good.
You need to provide the path to ffmpeg include files so that your .c files could compile. You also must list the libraries that the linker needs to find the external references of libffmpegkit.so that you are building:
defaultConfig {
....
ndk {
moduleName "ffmpegkit"
abiFilter "armeabi"
cFlags "-I/qqq/ffmpeg"
ldLibs "-llog -L src/main/libs", "avformat", "avcodec", "avutil"
}
}
Make sure that the ffmpeg libraries are compiled with a compatible Android toolchain! Note that the order in which ffmpeg libraries are listed is important. Like, libavformat depends on libavcodec, therefore it should go before.

Android NDK - multlib support using gradle

My question is directed towards native Android development for 64bit Android systems.
I am looking for a way to configure the support of 32bit compiled native libraries at a 64bit Android system using the gradle build system. The libraries the application should use are only available as 32bit build. It would be very time consuming and error prone to port these libraries to 64bit.
Hence, I want to configure gradle to deploy these prebuilt 32bit binaries and to use a 32bit version of the Android application as well.
The current configuration leads to the following error:
E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: <application_name>, PID: 2170
java.lang.UnsatisfiedLinkError:
dalvik.system.PathClassLoader
[DexPathList[[zip file "/data/app/<application_name>/base.apk"],
nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]]
enter code here`couldn't find "libmynativelibrary.so"
at java.lang.Runtime.loadLibrary(Runtime.java:366)
It seems as though the PathClassLoader looks in the wrong directories. I checked the provided apk file and it is lacking the libraries. There is no lib folder inside the apk. The build system does not seam to include the 32bit libraries.
Since there is only one prebuild version for armv7 these libraries are in app/src/main/jnilibs folder.
I have to add that this setup works perfectly for any 32bit Android system. I tried it with the emulator and a physical device before.
How should one activate the multiarch 32/64bit support using gradle? Or how is it possible to deploy a 32bit application to a 64bit Android system using Android Studio/gradle?
I searched the web and found one link concerning the topic, but it is referring to the older build system: https://source.android.com/source/64-bit-builds.html. I do not know how to adopt the description to gradle.
I am using Android Studio (Build: 141.1989493, June 6, 2015).
The project/build.gradle is untouched. The app/build.gradle file looks like this:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "<application_name>"
minSdkVersion 1
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
debug {
debuggable true
}
}
productFlavors {
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
}
fat
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
The concept of mulilib is only for projects that are part of an Android system build and you shouldn't set the android:multiarch option as you only have 32bit libs since this option is only for apps that are providing both 32 and 64bit libraries to other installed application.
64-bit Android systems support 32-bit applications directly. You only need to properly package your app, with your .so files inside lib/(armeabi-v7a,x86,...) of the APK, as for any Android devices.
At the install time, the libs of the architecture that is preferred by the device will be installed. ie: if there is no x86_64 folder, the x86 libs will be installed / if there is no arm64-v8a folder, the armeabi-v7a libs will be installed, and your app will run in 32-bit mode.
If you don't have anything under lib, that means Android Studio doesn't know about your .so files. By default it will look for them inside jniLibs/(armeabi-v7a,x86,...), hence you should place them there or change sourceSets.main.jniLibs.srcDir to the directory of your choice.
In order to get 32bit application deployment for 64bit Android system one needs to define a armv7 productFlavor and a subfolder inside the jniLibs folder naming the corresponding architecture.
Product flavor definition in app/build.gradle:
android {
productFlavors {
armv7 { ndk { abiFilter "armeabi-v7a" } }
fat
}
}
Native library structure: 
app/src/main/jniLibs/armeabi-v7a

Using NDK in Android Studio with outside C++ sources

So far into my foray with using NDK with Android Studio, I've written the Java Wrapper, generated the header file, and filled in some functions in the corresponding c++ file in JNI folder.
What I'm trying to do right now is to get a simple build going so that I can verify things work. My project relies on some c++ source files located outside of my entire android project. Do I build those source files somehow from within Android? How do I access them? Is there anything I need to do from Gradle?
I'm incredibly new to building projects with across multiple sources, so I have no idea what to do. Apologies if the questions don't make sense. Any help is greatly appreciated (:
http://ph0b.com/android-studio-gradle-and-ndk-integration/
user ph0b has many SO posts on NDK.
read this person's various posts on the subj ( AS + NDK )
IMO - You can follow strategy 'import NDK proj' from src dirs used for eclipse/NDK android project and AS 0.8.+ will get you almost all the way there with normal "File/Import project" dialog.
After the AS import is done, the NDK stuff will be at:
./root/module/src/main/jni
Java packages will be at
./root/module/src/main/java
Verify that the import to AS did NOT do auto-update on the "Android.mk" file that you input to the import process because you will need it and not any auto gen'd file from AS.
In AS gradle.build file ...
make sure
buildToolsVersion "19.1.0"
and add following as per the earlier links:
ndk {
moduleName "audioboo-ogg"
}
}
flavorDimensions "abi"
productFlavors {
x86 {
ndk {
abiFilter "x86"
}
}
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
}
}
sourceSets {
main {
jni.srcDirs = [] /*disable automatic ndk-build call */
}
}
task ndkBuild(type: Exec) {
commandLine '$NDK_HOME/android-ndk-r9[a-z]/ndk-build', '-C', file('src/main/jni').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
You then will have option of doing CLI NDK build in the jni folder, OR just using gradle integrated build that will use the "ndkBuild" task from gradle file.

Android studio, gradle and NDK

I am very new to this whole gradle and Android Studio support. I have managed to convert my android project to gradle using the export option.
But I am looking for some documentation or start point how to integrate the NDK build into the gradle build process.
If possible I also need some sort of "after" stage that copies the build binaries (.so files) to the asset directory.
We have released a first version of the integration as a preview in 1.3: http://tools.android.com/tech-docs/android-ndk-preview
The integration will stay a preview even after 1.3 becomes final. No current ETA as to when it'll be final (as of 2015/07/10).
More information here: http://tools.android.com/tech-docs/android-ndk-preview
UPDATE: The Android Studio with NDK support is out now: http://tools.android.com/tech-docs/android-ndk-preview
For building with a script the gradle solution below should work:
I am using my build script and added to my file (Seems to work for 0.8+): This seems to be equivalent to the solution below (but looks nicer in the gradle file):
android {
sourceSets {
main {
jniLibs.srcDirs = ['native-libs']
jni.srcDirs = [] //disable automatic ndk-build
}
}
}
The build unfortunately does not fail if the directory is not present or contains no .so files.
With the update of Android Studio to 1.0, the NDK toolchain support improved immensely (note: please read my updates at the bottom of this post to see usage with the new experimental Gradle plugin and Android Studio 1.5).
Android Studio and the NDK are integrated well enough so that you just need to create an ndk{} block in your module's build.gradle, and set your source files into the (module)/src/main/jni directory - and you're done!
No more ndk-build from the command line.
I've written all about it in my blog post here: http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/
The salient points are:
There are two things you need to know here. By default, if you have external libs that you want loaded into the Android application, they are looked for in the (module)/src/main/jniLibs by default. You can change this by using setting sourceSets.main.jniLibs.srcDirs in your module’s build.gradle. You’ll need a subdirectory with libraries for each architecture you’re targeting (e.g. x86, arm, mips, arm64-v8a, etc…)
The code you want to be compiled by default by the NDK toolchain will be located in (module)/src/main/jni and similarly to above, you can change it by setting sourceSets.main.jni.srcDirs in your module’s build.gradle
and put this into your module's build.gradle:
ndk {
moduleName "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
cFlags "-std=c++11 -fexceptions" // Add provisions to allow C++11 functionality
stl "gnustl_shared" // Which STL library to use: gnustl or stlport
}
That's the process of compiling your C++ code, from there you need to load it, and create wrappers - but judging from your question, you already know how to do all that, so I won't re-hash.
Also, I've placed a Github repo of this example here: http://github.com/sureshjoshi/android-ndk-swig-example
UPDATE: June 14, 2015
When Android Studio 1.3 comes out, there should be better support for C++ through the JetBrains CLion plugin. I'm currently under the assumption that this will allow Java and C++ development from within Android Studio; however I think we'll still need to use the Gradle NDK section as I've stated above. Additionally, I think there will still be the need to write Java<->C++ wrapper files, unless CLion will do those automatically.
UPDATE: January 5, 2016
I have updated my blog and Github repo (in the develop branch) to use Android Studio 1.5 with the latest experimental Gradle plugin (0.6.0-alpha3).
http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/
http://github.com/sureshjoshi/android-ndk-swig-example
The Gradle build for the NDK section now looks like this:
android.ndk {
moduleName = "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
cppFlags.add("-std=c++11") // Add provisions to allow C++11 functionality
cppFlags.add("-fexceptions")
stl = "gnustl_shared" // Which STL library to use: gnustl or stlport
}
Also, quite awesomely, Android Studio has auto-complete for C++-Java generated wrappers using the 'native' keyword:
However, it's not completely rosy... If you're using SWIG to wrap a library to auto-generate code, and then try to use the native keyword auto-generation, it will put the code in the wrong place in your Swig _wrap.cxx file... So you need to move it into the "extern C" block:
UPDATE: October 15, 2017
I'd be remiss if I didn't mention that Android Studio 2.2 onwards has essentially 'native' (no pun) support for the NDK toolchain via Gradle and CMake. Now, when you create a new project, just select C++ support and you're good to go.
You'll still need to generate your own JNI layer code, or use the SWIG technique I've mentioned above, but the scaffolding of a C++ in Android project is trivial now.
Changes in the CMakeLists file (which is where you place your C++ source files) will be picked up by Android Studio, and it'll automatically re-compile any associated libraries.
In Google IO 2015, Google announced full NDK integration in Android Studio 1.3.
It is now out of preview, and available to everyone: https://developer.android.com/studio/projects/add-native-code.html
Old answer: Gradle automatically calls ndk-build if you have a jni directory in your project sources.
This is working on Android studio 0.5.9 (canary build).
Download the NDK
Either add ANDROID_NDK_HOME to your environment variables or add ndk.dir=/path/to/ndk to your local.properties in your Android Studio project. This allows Android studio to run the ndk automatically.
Download the latest gradle sample projects to see an example of an ndk project. (They're at the bottom of the page). A good sample project is ndkJniLib.
Copy the gradle.build from the NDK sample projects. It'll look something like this. This gradle.build creates a different apk for each architecture. You must select which architecture you want using the build variants pane.
apply plugin: 'android'
dependencies {
compile project(':lib')
}
android {
compileSdkVersion 19
buildToolsVersion "19.0.2"
// This actual the app version code. Giving ourselves 100,000 values [0, 99999]
defaultConfig.versionCode = 123
flavorDimensions "api", "abi"
productFlavors {
gingerbread {
flavorDimension "api"
minSdkVersion 10
versionCode = 1
}
icecreamSandwich {
flavorDimension "api"
minSdkVersion 14
versionCode = 2
}
x86 {
flavorDimension "abi"
ndk {
abiFilter "x86"
}
// this is the flavor part of the version code.
// It must be higher than the arm one for devices supporting
// both, as x86 is preferred.
versionCode = 3
}
arm {
flavorDimension "abi"
ndk {
abiFilter "armeabi-v7a"
}
versionCode = 2
}
mips {
flavorDimension "abi"
ndk {
abiFilter "mips"
}
versionCode = 1
}
fat {
flavorDimension "abi"
// fat binary, lowest version code to be
// the last option
versionCode = 0
}
}
// make per-variant version code
applicationVariants.all { variant ->
// get the version code of each flavor
def apiVersion = variant.productFlavors.get(0).versionCode
def abiVersion = variant.productFlavors.get(1).versionCode
// set the composite code
variant.mergedFlavor.versionCode = apiVersion * 1000000 + abiVersion * 100000 + defaultConfig.versionCode
}
}
Note that this will ignore your Android.mk and Application.mk files. As a workaround, you can tell gradle to disable atuomatic ndk-build call, then specify the directory for ndk sources manually.
sourceSets.main {
jniLibs.srcDir 'src/main/libs' // use the jni .so compiled from the manual ndk-build command
jni.srcDirs = [] //disable automatic ndk-build call
}
In addition, you'll probably want to call ndk-build in your gradle build script explicitly, because you just disabled the automatic call.
task ndkBuild(type: Exec) {
commandLine 'ndk-build', '-C', file('src/main/jni').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
I found "gradle 1.11 com.android.tools.build:gradle:0.9.+" supports pre-build ndk now, you can just put the *.so in the dir src/main/jniLibs.
when building gradle will package the ndk to the right place.
here is my project
Project:
|--src
|--|--main
|--|--|--java
|--|--|--jniLibs
|--|--|--|--armeabi
|--|--|--|--|--.so files
|--libs
|--|--other.jar
As Xavier said, you can put your prebuilts in /src/main/jniLibs/ if you are using gradle 0.7.2+
taken from: https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ
As of now (Android Studio v0.8.6) it's quite simple. Here are the steps to create a "Hello world" type app:
Download the Android NDK and put the root folder somewhere sane -- in the same location as the SDK folder, perhaps.
Add the following to your local.properties file:
ndk.dir=<path-to-ndk>
Add the following to your build.gradle file inside of the defaultConfig closure, right after the versionName line: ndk { moduleName="hello-world" }
In your app module's main directory, create a new folder called jni.
In that folder, create a file called hello-world.c, which you'll see below.
See the example Activity code below for an example of how to call a method (or is it a function?) in hello-world.c.
hello-world.c
#include <string.h>
#include <jni.h>
jstring
Java_me_mattlogan_ndktest_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
return (*env)->NewStringUTF(env, "Hello world!");
}
MainActivity.java
public class MainActivity extends Activity {
static {
System.loadLibrary("hello-world");
}
public native String stringFromJNI();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String testString = stringFromJNI();
TextView mainText = (TextView) findViewById(R.id.main_text);
mainText.setText(testString);
}
}
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "me.mattlogan.ndktest"
minSdkVersion 15
targetSdkVersion 20
versionCode 1
versionName "1.0"
ndk {
moduleName "hello-world"
}
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
Find the full source code of a very similar app here (minus the NDK).
If you're on unix the latest version (0.8) adds ndk-build. Here's how to add it:
android.ndk {
moduleName "libraw"
}
It expects to find the JNI under 'src/main/jni', otherwise you can define it with:
sourceSets.main {
jni.srcDirs = 'path'
}
As of 28 JAN 2014 with version 0.8 the build is broken on windows, you have to disable the build with:
sourceSets.main {
jni.srcDirs = [] //disable automatic ndk-build call (currently broken for windows)
}
An elegant workaround is shown in https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J.
Basically you create a jar which contains "lib/armeabi/yourlib.so" and then include the jar in the build.
A good answer automating the packaging of readily compiled .so-files is given in another (closed) thread. To get that working, I had to change the line:
from fileTree(dir: 'libs', include: '**/*.so')
into:
from fileTree(dir: 'src/main/libs', include: '**/*.so')
Without this change the .so files were not found, and the task for packaging them would therefore never run.
The answer from #plaisthos broke in the latest gradle version, but there is still a way to do it.
Create a native-libs directory in the root of your project directory and copy all y our libs into this directory.
Add the following lines to your build.gradle. Build and be happy.
task copyNativeLibs(type: Copy) {
from(new File(project(':<your project>').getProjectDir(), 'native-libs')) { include '**/*.so' }
into new File(buildDir, 'native-libs')
}
tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }
clean.dependsOn 'cleanCopyNativeLibs'
This is the code i use to build using android-ndk from gradle. For this add ndk directory path in gradle.properties ie . add ndkdir=/home/user/android-ndk-r9d and put all jni files in a folder native in src/main/ as you can see from code posted below. It will create jar with native libs which you can use normally as in System.loadLibrary("libraryname");
dependencies {
compile fileTree(dir: "$buildDir/native-libs", include: '*.jar')
}
task ndkBuild(type: Exec) {
commandLine "$ndkdir/ndk-build", "--directory", "$projectDir/src/main/native", '-j', Runtime.runtime.availableProcessors(),
"APP_PLATFORM=android-8",
"APP_BUILD_SCRIPT=$projectDir/src/main/native/Android.mk",
"NDK_OUT=$buildDir/native/obj",
"NDK_APP_DST_DIR=$buildDir/native/libs/\$(TARGET_ARCH_ABI)"
}
task nativeLibsToJar(type: Jar, description: 'create a jar with native libs') {
destinationDir file("$buildDir/native-libs")
baseName 'native-libs'
from fileTree(dir: "$buildDir/native/libs", include: '**/*.so')
into 'lib/'
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn nativeLibsToJar
}
nativeLibsToJar.dependsOn 'ndkBuild'
I have used the following code to compile native dropbox libraries, I am using Android Studio v1.1.
task nativeLibsToJar(type: Zip) {
destinationDir file("$buildDir/native-libs")
baseName 'native-libs'
extension 'jar'
from fileTree(dir: 'src/main/libs', include: '**/*.so')
into 'lib/'
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
I have used ndk.dir=/usr/shareData/android-ndk-r11b // path of ndk in local.properties file in android studio project. and
add this line : android.useDeprecatedNdk=true in gradle.properties file in android studio project.
More information here: http://tools.android.com/tech-docs/android-ndk-preview
To expand on what Naxos said (Thanks Naxos for sending me in the right direction!), I learned quite a bit from the recently released NDK examples and posted an answer in a similar question here.
How to configure NDK with Android Gradle plugin 0.7
This post has full details on linking prebuilt native libraries into your app for the various architectures as well as information on how to add NDK support directly to the build.gradle script. For the most part, you shouldn't need to do the work around zip and copy anymore.
Here are the steps that I used to get the NDK working in my Android Studio project.
I used this tutorial to help me out
https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio
In order to use NDK you must add a NDK line to local.properties. So under your sdk.dir add
ndk.dir=C\:\\MyPathToMyNDK\ndk
In my apps build.gradle I have the following code
ndk {
moduleName "myLib"
ldLibs "log"
stl "gnustl_shared"
cFlags "-std=c++11 -frtti -fexceptions -pthread"
}
moduleName is the name you want to give your native code. I believe this is what the shared library will be called. ldLibs allows me to log to LogCat, stl is the stl that you want to import. There are lots of options, same as the Eclipse NDK. (http://www.kandroid.org/ndk/docs/CPLUSPLUS-SUPPORT.html)
cFlags are still a certain amount of black magic for me. I have not found a good source for all the options and what they give me. Search around StackOverflow for anything you need, that is where I found it. I do know that the c++11 allows me to use the new c++ 11 standard.
Here is an example of how I log to LogCat from the native code
__android_log_print(ANDROID_LOG_DEBUG, "TestApp", "Adding - String %d has a field name of %s and a value of %s", i, lKeyUTF8.c_str(), lValueUTF8.c_str());
configure project in android studio from eclipse: you have to import eclipse ndk project to android studio without exporting to gradle and it works , also you need to add path of ndk in local.properties ,if shows error then add
sourceSets.main {
jniLibs.srcDir 'src/main/libs'
jni.srcDirs = [] //disable automatic ndk-build callenter code here
}
in build.gradle file then create jni folder and file using terminal and run it will work
Now that Android Studio is in the stable channel, it is pretty straightforward to get the android-ndk samples running. These samples use the ndk experimental plugin and are newer than the ones linked to from the Android NDK online documentation. Once you know they work you can study the build.gradle, local.properties and gradle-wrapper.properties files and modify your project accordingly. Following are the steps to get them working.
Go to settings, Appearance & Behavior, System Settings, Android SDK, selected the SDK Tools tab, and check Android NDK version 1.0.0 at the bottom of the list. This will download the NDK.
Point to the location of the newly downloaded NDK. Note that it will be placed in the sdk/ndk-bundle directory. Do this by selecting File, Project Structure, SDK Location (on left), and supplying a path under Android NDK location. This will add an ndk entry to local.properties similar to this:
Mac/Linux: ndk.dir=/Android/sdk/ndk-bundle
Windows: ndk.dir=C:\Android\sdk\ndk-bundle
I have successfully built and deployed all projects in the repository this way, except gles3gni, native-codec and builder. I'm using the following:
Android Studio 1.3 build AI-141.2117773
android-ndk samples published July 28, 2015 (link above)
SDK Tools 24.3.3
NDK r10e extracted to C:\Android\sdk\ndk-bundle
Gradle 2.5
Gradle plugin 0.2.0
Windows 8.1 64 bit
NDK Builds and gradle (basic)
Generally building with the NDK is as simple as correctly specifying an ndkBuild path to Android.mk or cmake path to CMakeLists.txt. I recommend CMake over the older Android.mk because Android Studio's C/C++ support is based upon CLion and it uses CMake as its project format. This in my experience has tended to make the IDE more responsive on larger projects. Everything compiled in your project will be built and copied into the APK automatically.
apply plugin: 'com.android.library'
android {
compileSdkVersion 19
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 19
ndk {
abiFilters 'armeabi', 'armeabi-v7a', 'x86'
// 64-bit support requires an Android API level higher than 19; Namely 21 and higher
//abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
externalNativeBuild {
cmake {
arguments '-DANDROID_TOOLCHAIN=clang',
'-DANDROID_PLATFORM=android-19',
'-DANDROID_STL=gnustl_static',
'-DANDROID_ARM_NEON=TRUE'
}
}
}
externalNativeBuild {
cmake {
path 'src/main/jni/CMakeLists.txt'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
Adding prebuilt libraries to the project (advanced)
Static libraries (.a) in your NDK build will automatically be included, but prebuilt dynamic libraries (.so) will need to be placed in jniLibs. This can be configured using sourceSets, but you should adopt the standard. You DO NOT NEED any additional commands in build.gradle when including prebuilt libraries.
The layout of jniLibs
You can find more information about the structure in the Android Gradle Plugin User Guide.
|--app:
|--|--build.gradle
|--|--src:
|--|--|--main
|--|--|--|--java
|--|--|--|--jni
|--|--|--|--|--CMakeLists.txt
|--|--|--|--jniLibs
|--|--|--|--|--armeabi
|--|--|--|--|--|--.so Files
|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--.so Files
|--|--|--|--|--x86
|--|--|--|--|--|--.so Files
You can then validate the resulting APK contains your .so files, typically under build/outputs/apk/, using unzip -l myApp.apk to list the contents.
Building shared libraries
If you're building a shared library in the NDK you do not need to do anything further. It will be correctly bundled in the APK.
Just add this lines to app build.gradle
dependencies {
...
compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
}
task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') {
destinationDir file("$buildDir/native-libs")
baseName 'native-libs'
extension 'jar'
from fileTree(dir: 'libs', include: '**/*.so')
into 'lib/armeabi/'
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
now.I can load the so success!
1.add the .so file to this path
Project:
|--src
|--|--main
|--|--|--java
|--|--|--jniLibs
|--|--|--|--armeabi
|--|--|--|--|--.so files
2.add this code to gradle.build
android {
splits {
abi {
enable true
reset()
include 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a', 'armeabi'
universalApk false
}
}
}
3.System.loadLibrary("yousoname");
goodluck for you,it is ok with gradle 1.2.3
If your project exported from eclipse,add the codes below in gradle file:
android {
sourceSets{
main{
jniLibs.srcDir['libs']
}
}
}
2.If you create a project in Android studio:
create a folder named jniLibs in src/main/ ,and put your *.so files in the jniLibs folder.
And copy code as below in your gradle file :
android {
sourceSets{
main{
jniLibs.srcDir['jniLibs']
}
}
}
While I believe SJoshi (oracle guy) has the most complete answer, the SWIG project is a special case, interesting and useful one, at that, but not generalized for the majority of projects that have done well with the standard SDK ant based projects + NDK. We all would like to be using Android studio now most likely, or want a more CI friendly build toolchain for mobile, which gradle theoretically offers.
I've posted my approach, borrowed from somewhere (I found this on SO, but posted a gist for the app build.gradle: https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841 ). In a nutshell, I recommend the following:
Don't upgrade your project to the latest gradle build
Use com.android.tools.build:gradle:1.5.0 in your Project root
Use com.android.application in your app project
Make sure gradle.properties has: android.useDeprecatedNdk=true (in case it's complaining)
Use the above approach to ensure that your hours and hours of effort creating Android.mk files won't be tossed away. You control which targets arch(s) to build. And these instructions are kind to Windows users, who should theoretically be able to build on windows without special issues.
Gradle for Android has been a mess in my opinion, much as I like the maven concepts borrowed and the opinionated structure of directories for a project. This NDK feature has been "coming soon" for almost 3+ years.

Categories

Resources