android studio experimental ndk c library - android

I built some test c and c++ programs using gradle following these examples
I was also able to setup android studio with the experimental features to build a android project calling native functions with the help of this answer
I know that I can build this project using the android.useDeprecatedNdk=true
and provide my android.mk file for android studio to compile and build the app.
Is it possible with the experimental feature to build this same program? This project is built with CMAKE and there are some compilation steps that output files that needs to link. ndk-build creates these files but I can't find a way to do it with with android experimental features.
I am attempting for testing purposes and to build a non trivial example of building a more complex project. I decided to try to build the zlib library.
Here is my build.gradle
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.1"
defaultConfig.with {
applicationId = "me.test.testnative_exp"
minSdkVersion.apiLevel = 10
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
buildConfigFields.with {
create() {
type = "int"
name = "VALUE"
value = "1"
}
}
}
}
compileOptions.with {
sourceCompatibility=JavaVersion.VERSION_1_7
targetCompatibility=JavaVersion.VERSION_1_7
}
android.ndk {
moduleName = "hello-jni"
cppFlags += "-I${file("src/main/jni/zlib")}".toString()
stl = "stlport_static"
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles += file('proguard-rules.pro')
}
}
android.sources {
main {
java {
source {
srcDir 'src'
}
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:design:23.0.1'
}
my project structure is
app/
build/
libs/
src/
src/main/testActivity.java
jni/zlib <- the zlib folder is the one that I downloaded from the zlib website.
jni/hello-jni.c
After syncing the build.gradle I get a link error on the header in file:
infbak9.c cannot find #include "zutil.h"
but both files are in the zlib directory under jni.
Is it possible to use the android studio experimental ndk build to compile this project?

there is good project in github that i use its structure in mine, it is nice example for start on "how use experimental(v_0.4.0) plugin in complex project?" :
https://github.com/frogermcs/FlatBuffs
*there are zlib in android NDK, just add appropriate cflag and ldLibs.add("z") in gradle. and in your native code include <zlib.h>
and a good experimental gradle config from google :
https://github.com/googlesamples/android-ndk/blob/229cbe86238d401bb06166b8dfadec8198532589/native-codec/app/build.gradle

you might check this repo for a group of samples:
https://github.com/googlesamples/android-ndk
your issue might be able to fixed by adding something as[from Teapot sample there]:
cppFlags.addAll(['-I' + "${ndkDir}/sources/android/cpufeatures",'-I' + file('src/main/jni/ndk_helper')])
just replace the directory with your own path "zutil.h" etc. you may also use the latest gradle-experimental version to simplify your script -- like removing ".with" for defaultConfig.with, delete java 7 version section( the latest android studio could handle java 8 ), those ".toString()" thing is also wordy so the samples have changed style to use "+" [those is not problem for your build error though]

Related

Debugging C++/native library modules not working with Android Studio (Cmake used)

I'm having trouble debugging C++ files of my library module.
Is this possible in general?
The debugging works fine if the application project contains the c++ code.
But I want to move the C++ Code to a library module.
The Error Message while starting the session:
Now Launching Native Debug Session
Attention! No symbol directories found - please check your native debug configuration
gradle file of my lib:
apply plugin: 'com.android.library'
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 16
targetSdkVersion 21
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
arguments "-DANDROID_PLATFORM_LEVEL=${11}",
'-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_static'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-annotations:24.2.0'
}
In the run configuration the debugger is set to auto
Additions:
Im using:
Gradle : 2.2.3
Android Studio : 2.2.3
in the LLLB Console, i checked the breakpoint List with:
breakpoint list -v
all my checkpoints are listed there.
Not Working Breakpoint
1: file = 'C:\android-dev\...\test.cpp', line = 19, exact_match = 0
..thats all
Working Breakpoint
1: file = 'C:\android-dev\...\test.cpp', line = 19, exact_match = 0
1.1:
module = C:\android-dev\...\test.so
compile unit = gl_code.cpp
function = testFunc(..)
location = C:\android-dev\...\test.cpp:16
address = 0x0000007f871d068c
resolved = true
hit count = 1
The reason seems to be, that a release version of the lib is created,
which does not support debugging, even if the app is built with debug options.
Solution:
To solve this issue, do the following workaround. It ensures that a debug version is built.
In your apps build.gradle change:
compile project(':nativelib')
to
compile project(path: ':nativelib' , configuration: 'debug')
In the libs build.gradle add:
android {
publishNonDefault true //this line
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
...
}
...
}
Updates:
See the google issue for updates:
https://code.google.com/p/android/issues/detail?id=222276
I had the same error ("Attention! No symbol directories found - please check your native debug configuration."). My solution was (Android Studio 3.2):
Run → Edit Configuration → "Debugger" tab → add your working path to Symbol Directories.
I had the similar issue with my own libraries some months ago because I thought that if I added the -g (gcc) flag it would generate the debug symbols, as the desktop (linux, unix kernel) apps.
But, actually it does not work to generate debug symbols.
I see that you use Cmake as a external build tool and clang compiler.
So in my case I configure my cmake script with gcc but out of gradle scripting, but I think it will be the same, I add -mapcs-frame in the CMAKE_CXX_FLAGS.
externalNativeBuild {
cmake {
arguments "-DANDROID_PLATFORM_LEVEL=${11}",
'-DANDROID_TOOLCHAIN=gcc',
'-DANDROID_STL=gnustl_static',
'DCMAKE_CXX_FLAGS=-mapcs-frame'
}
}
I know that if you use clang compile may be this flag could not work. But my idea was to share my experience with android native debugging.
I Hope this clues could help you.
Cheers.
Unai.
In my case, it was because of co-worker who changed the visibility of symbols.
set(CMAKE_CXX_FLAGS -fvisibility=hidden)
After changing the above code to be applied only in release build, debugger(including breakpoints) works fine.

Migrate Native Module from Gradle Experimental Plugin to Stable Gradle

I have an Android Library project which has a part in C/C++ via Android NDK.
The project started half of a year ago so we chose to use Experimental Plugin because of better NDK support.
I'm using gradle-experimental:0.8.2right now. I have a com.android.model.native module and i would like to migrate it to gradle:2.2.0. The only option i see in Gradle Android Plugin DSL is:
AppExtension: android extension for com.android.application projects.
LibraryExtension: android extension for com.android.library projects.
TestExtension: android extension for com.android.test projects.
So the question is how to make a pure native module in gradle with stable gradle plugin?
Here is my current native module:
apply plugin: 'com.android.model.native'
apply from: "../config.gradle"
def config = ext.configuration
model {
android {
compileSdkVersion = config.compileSdkVersion
buildToolsVersion = config.buildToolsVersion
defaultConfig {
minSdkVersion.apiLevel = config.minimumSdkVersion
targetSdkVersion.apiLevel = config.targetSdkVersion
versionCode = 1
versionName = '1.0'
}
ndk {
moduleName = 'apicore'
platformVersion = config.minimumSdkVersion
cppFlags.add("-std=c++11")
cppFlags.add("-pthread")
cppFlags.add("-fexceptions")
cppFlags.add("-frtti")
stl = "gnustl_static"
abiFilters.addAll(config.targetPlatforms)
ldLibs.addAll(['android', 'log'])
}
sources {
main {
jni {
source {
//include "someFile.txt"
// This is ignored.
exclude "main.cpp"
exclude "misc/APITest.cpp"
exclude "misc/APITest.h"
}
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file('proguard-android.txt'))
}
}
}
}
You will need to create CMakeLists.txt or Android.mk to build your "libapicore.so", if you want to move to stable gradle plugin.
I think you should do next steps:
For easy migration move your .h, .c, .cpp to the
root_folder_of_project\app\src\main\cpp
Also add there CMakeLists.txt. It should look like:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
add_library(apicore SHARED
#here add your cpp sources
mysource1.cpp
mysource2.cpp
#do not include main.cpp misc/APITest.cpp misc/APITest.h
)
#include libraries needed for apicore lib
target_link_libraries(apicore
android
log
)
Now rewrite your app's build.gradle and point it to CMakeLists.txt:
apply plugin: 'com.android.application'
android {
compileSdkVersion = 25
buildToolsVersion = '25.0.2'
defaultConfig {
applicationId = 'com.your.app'
minSdkVersion 16
targetSdkVersion 25
ndk {
abifilters 'armeabi-v7a' /*,'armeabi', etc.*/
}
externalNativeBuild {
cmake {
arguments '-DANDROID_PLATFORM=android-19',
'-DANDROID_TOOLCHAIN=clang', /*or gcc*/
'-DANDROID_CPP_FEATURES=rtti',
'-DANDROID_CPP_FEATURES=exceptions',
'-DANDROID_STL=gnustl_static' /*CMake uses by default*/
}
}
}
buildTypes {...}
externalNativeBuild {
cmake {
path 'src/main/cpp/CMakeLists.txt'
}
}
}
dependencies {...}
With this you will build your android application with your native "libapicore.so" inside.
I just migrated my project from Gradle Experimental Plugin to Gradle plugin for Android. The current Gradle plugin for Android still not provide something what com.android.model.native extension provided from the experimental plugin which is an ability to create a pure native module. I have to realise that i don't even need that. What i did to replace the com.android.model.native module is i made a library module where i handle the native code and building of my native libraries and i just copy the native libraries where i need them. Of course the module generate the .aar but thats not a problem i just don't use it.

NDK module not included in final APK

I've inherited a really messy android project with a lot of NDK dependencies and having a lot of problems with getting gradle to correctly link and include all .so and .a files into the resulting apk.
The project consists of some java code that sets up some activities and call into a big NDK library, built from C++ which in turn links with a dosens of 3rd party library (prebuilt or built from source).
I have managed to make it build with the latest gradle experimental plugin, but for some reason, my module isn't included in the apk while my 3rd party .so files are even though I can see that gradle have built my module into a .so file which it have placed in the build directory.
My build.gradle looks like this:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "22.0.1"
defaultConfig.with {
applicationId = "<removed>"
minSdkVersion.apiLevel = 7
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
ndk {
moduleName = "XM"
CFlags.add("-I${file("src/main/jni")}".toString())
cppFlags.addAll(["-I${file("../../3rd_part/android/osg")}".toString()])
cppFlags.addAll(["-I${file("../../3rd_part/android/opus")}".toString()])
ldFlags.add("-L${file("src/main/jniLibs/armeabi-v7a")}".toString())
ldLibs.addAll(["osgdb_jpeg", "osgdb_freetype", "jpeg","argsub_es", "jnigraphics", "android", "log"])
stl = "gnustl_shared"
abiFilters.add("armeabi-v7a")
}
sources {
main {
jni {
source {
srcDir "../../core"
srcDir "src/main/jni"
}
}
}
}
lintOptions.abortOnError = false
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:23.0.0'
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.android.support:design:23.0.0'
compile 'com.wunderlist:sliding-layer:1.1.1'
}
So to sum up my question: why does gradle build my module (libXM.so), place it into build/libs/xM/shared/armeabi-v7a/debug, but not include it into my final apk file?
I didn't get several things: if you want to build a shared library with gradle, then you have to use apply plugin: 'com.android.model.library' and not application
If you want to build an application and use prebuilt library, then you have to write something like this:
sources {
main {
jni {
source {
srcDir "../../core"
srcDir "src/main/jni"
}
dependencies{
library "XM" linkage "shared"
}
And, of course, to set ldFlags previously.

How can I create aar file in android studio 1.3.1 while I've made the project without activity [duplicate]

I'd like to create an aar file for my library in Android Studio, i would've gone with a jar option but my library has resources.
Any idea how to create an aar file from a library?
If your library is set up as an Android library (i.e. it uses the apply plugin: 'com.android.library' statement in its build.gradle file), it will output an .aar when it's built. It will show up in the build/outputs/aar/ directory in your module's directory.
You can choose the "Android Library" type in File > New Module to create a new Android Library.
If you are still not seeing your aar file, select Build > Rebuild Project.
Retrieve exported .aar file from local builds
If you have a module defined as an android library project you'll get .aar files for all build flavors (debug and release by default) in the build/outputs/aar/ directory of that project.
your-library-project
|- build
|- outputs
|- aar
|- appframework-debug.aar
- appframework-release.aar
If these files don't exist start a build with
gradlew assemble
for macOS users
./gradlew assemble
Library project details
A library project has a build.gradle file containing apply plugin: com.android.library. For reference of this library packaged as an .aar file you'll have to define some properties like package and version.
Example build.gradle file for library (this example includes obfuscation in release):
apply plugin: 'com.android.library'
android {
compileSdkVersion 21
buildToolsVersion "21.1.0"
defaultConfig {
minSdkVersion 9
targetSdkVersion 21
versionCode 1
versionName "0.1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Reference .aar file in your project
In your app project you can drop this .aar file in the libs folder and update the build.gradle file to reference this library using the below example:
apply plugin: 'com.android.application'
repositories {
mavenCentral()
flatDir {
dirs 'libs' //this way we can find the .aar file in libs folder
}
}
android {
compileSdkVersion 21
buildToolsVersion "21.0.0"
defaultConfig {
minSdkVersion 14
targetSdkVersion 20
versionCode 4
versionName "0.4.0"
applicationId "yourdomain.yourpackage"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
}
}
}
dependencies {
compile 'be.hcpl.android.appframework:appframework:0.1.0#aar'
}
Alternative options for referencing local dependency files in gradle can be found at: http://kevinpelgrims.com/blog/2014/05/18/reference-a-local-aar-in-your-android-project
Sharing dependencies using maven
If you need to share these .aar files within your organization check out maven. A nice write up on this topic can be found at: https://web.archive.org/web/20141002122437/http://blog.glassdiary.com/post/67134169807/how-to-share-android-archive-library-aar-across
About the .aar file format
An aar file is just a .zip with an alternative extension and specific content. For details check this link about the aar format.
just like user hcpl said but if you want to not worry about the version of the library you can do this:
dependencies {
compile(name:'mylibrary', ext:'aar')
}
as its kind of annoying to have to update the version everytime. Also it makes the not worrying about the name space easier this way.
To create AAR
while creating follow below steps.
File->New->New Module->Android Library and create.
To generate AAR
Go to gradle at top right pane in android studio follow below steps.
Gradle->Drop down library name -> tasks-> build-> assemble or assemble release
AAR will be generated in build/outputs/aar/
But if we want AAR to get generated in specific folder in project directory with name you want, modify your app level build.gradle like below
defaultConfig {
minSdkVersion 26
targetSdkVersion 28
versionCode System.getenv("BUILD_NUMBER") as Integer ?: 1
versionName "0.0.${versionCode}"
libraryVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = "/../../../../release/" + ("your_recommended_name.aar")
}
}
}
Now it will create folder with name "release" in project directory which will be having AAR.
Updated Answer
In Latest releases specific path is not supported.Please add below code in library's build.gradle and rebuild project.After Rebuilding "aar",change project structure from Android to Project->navigate to your library->build->outputs->aar
android {
defaultConfig {
minSdkVersion ..
targetSdkVersion ..
versionCode ...
versionName "1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
libraryVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = "${archivesBaseName}_${variant.name}_${defaultConfig.versionName}.aar"
}
}}
To import "aar" into project,check below link.
How to manually include external aar package using Gradle for Android
After following the first and second steps mentioned in the hcpl's answer in the same thread, we added , '*.aar'], dir: 'libs' in the our-android-app-project-based-on-gradle/app/build.gradle file as shown below:
...
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
...
Our gradle version is com.android.tools.build:gradle:3.2.1
btw #aar doesn't have transitive dependency. you need a parameter to turn it on:
Transitive dependencies not resolved for aar library using gradle
Finally got the solution here - https://stackoverflow.com/a/49663101/9640177
implementation files('libs/aar-file.aar')
Edit
I had one more complication - I had set minifyEnabled true for the library module.
[JAR vs AAR]
.jar is generated by apply plugin: 'java-library'
.aar is generated by apply plugin: 'com.android.library'
File -> New -> New Module... -> Android Library
If you have correctly set up for publishing, then you can just run this command to generate aar files.
./gradlew publishReleasePublicationToMavenLocal
This will generate a aar file inside <module-dir>/build/output/aar directory.
Now you can use this library in other local projects also. Add this in the project gradle in which you want to use this aar module
implementation fileTree(dir: '<location-to-library>/build/outputs/aar/', include: ['*.aar', '*.jar'], exclude: [])
Build ---> Build bundle/apk
.aar file will be generated in build/outputs/aar folder.

build native openCV sources with Android Studio and NDK

I am trying to include some native cpp sources in my android app. I'm using Android Studio 1.0 with the gradle build system. I have three modules: my android app, the android opencv libs, the cpp sources (in the jni folder)
The build process gives me the following error:
D:\NVPACK\android-ndk-r10c\sources\cxx-stl\gnu-libstdc++\4.9\include\bits\stl_pair.h
Error:(96, 12) error: redefinition of 'struct std::pair<_T1, _T2>'
Error:(214, 5) error: redefinition of 'template<class _T1, class _T2> bool std::operator==(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)'
... and some other redefinitions with some other errors in other files.
It seems that the include paths are partially wrong or that there are duplicated headers (stl_pair.h) in the NDK This is my build.gradle file:
apply plugin: 'com.android.library'
android {
compileSdkVersion 21
buildToolsVersion "21.1.1"
defaultConfig {
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName "1.0"
ndk{
moduleName "Native"
cFlags "-I'D:\\OpenCV-2.4.10-android-sdk\\sdk\\native\\jni\\include' " +
"-I'D:\\NVPACK\\android-ndk-r10c\\sources\\cxx-stl\\gnu-libstdc++\\4.9\\include' " +
"-I'D:\\NVPACK\\android-ndk-r10c\\sources\\cxx-stl\\gnu-libstdc++\\4.9\\libs\\armeabi-v7a\\include'"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
}
In cFlags I point to the openCV sources and to the c++ standard sources as described here. This works all fine until the above error.
I have only a very basic understanding of the whole build process when dealing with cpp sources as I normally work with c# .net or android (without native sources).
From my understanding the ndk-build should give me some .so files that I can use in my app. But the build of the natives failes. Am I missing something in the process?
edit: I switched to eclipse and could build and run the code. Maybe I try to switch back to android studio in the future, but this is not so important.

Categories

Resources