I'm making a jni Function in android to generate file checkSum using BoringSSL.
So I built boringssl to shared Library for use Prebuilt Library in Android studio.
The build output like this.
I copied the *.so file to my project src/main/jniLibs/lib
and BoringSSL include folder to src/main/jni
I referenced this project and apply to my projects.
https://github.com/googlesamples/android-ndk/tree/master/hello-libs
My build.gradle file like this.
I'm using gradle-experimental:0.7.0( and Window10, Android Studio 2.1.2 )
apply plugin: 'com.android.model.application'
model {
repositories {
libs(PrebuiltLibraries) {
boringssl {
headers.srcDir "src/main/jni/include/openssl"
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("src/main/jniLibs/lib/libcrypto.so")
sharedLibraryFile = file("src/main/jniLibs/lib/libssl.so")
}
}
}
}
android {
compileSdkVersion = 24
buildToolsVersion = '24.0.1'
defaultConfig {
applicationId = 'yein.a'
minSdkVersion.apiLevel = 19
targetSdkVersion.apiLevel = 24
versionCode = 1
versionName = '1.0'
}
ndk {
moduleName = 'hello-libs'
ldLibs.addAll(['android', 'log'])
}
sources {
main {
jni {
dependencies {
library 'boringssl' linkage 'shared'
}
}
jniLibs{
source{
srcDir "src/main/jniLibs/lib"
}
}
}
}
productFlavors{
create("arm"){
ndk.abiFilters.add("armeabi-v7a")
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file('proguard-android.txt'))
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.1.1'
}
This is my project structure.
I think I properly apply the example projects, because it is not occurred gradle sync error.
And when I use MD5 function Android Studio auto complete function name like this.
But I click run it occurred error like this...
I searched a lot project in google,github, and of course stackoverflow previous answers but I still not solve my problem.
I tried change gradle version but other gradle version occurred error in auto generated jni function except gradle-experimental:0.7.0.
Could anyone point me in the right direction or even a solution?
Thanks for read my Question.
you can try to call the java API from JNI, there is a nice tutorial here, Google recommends on this site you should call the java API or you can link the libraries as you did.
If you can't or don't want to call the java API you can always use CRC32 instead of MD5, CRC32 uses the libz library and that library is already on the NDK files. CRC32 in C.
#include <zlib.h>
int checkSumCRC32(char *text){
long n = crc32(0, (const void*)text, strlen(text));
printf("CRC32 %d", n);
return n;
}
Remember to add ldLibs.addAll(['z']) to your Gradle file
In case you need MD5 and BoringSSL this is my gradle.build file for BoringSSL.
Note: I am using the 3 libraries you compile on ubuntu, libssl.a libcrypto.a and libdecrepit.a
Note2: I am using com.android.tools.build:gradle-experimental:0.7.0-alpha4
apply plugin: 'com.android.model.application'
model {
repositories {
libs(PrebuiltLibraries) {
libcrypto {
headers.srcDir "./main/jni/include/openssl"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/${targetPlatform.getName()}/crypto/libcrypto.a")
}
}
libssl {
headers.srcDir "./main/jni/include/openssl"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/${targetPlatform.getName()}/ssl/libssl.a")
}
}
libdecrepit {
headers.srcDir "src/main/jni/include/openssl"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("src/main/jni/${targetPlatform.getName()}/decrepit/libdecrepit.a")
}
}
}
}
android {
compileSdkVersion = 23
buildToolsVersion = "22.0.1"
defaultConfig {
applicationId = "net.app"
minSdkVersion.apiLevel = 9
targetSdkVersion.apiLevel = 23
versionCode = 1
}
ndk {
platformVersion = 21
moduleName = "modulename"
toolchain = "clang"
abiFilters.addAll([ 'armeabi-v7a'])
CFlags.addAll(["-fvisibility=hidden", "-fpic"])
ldLibs.addAll(['log', 'z', 'android']) //Libreria llog, lz y landroid
}
sources {
main {
jni{
dependencies {
library "libcrypto" linkage "static"
library "libssl" linkage "static"
library "libdecrepit" linkage "static"
}
}
}
}
}
}
I haven't used MD5 but I have used SHA256 using boringSSL and it works fine. You can use it too as a checksum method. This is my method for SHA256.
char *sha256(char *str){
unsigned char hash[SHA256_DIGEST_LENGTH];
char *output = (char *) malloc(sizeof(char)*((SHA256_DIGEST_LENGTH*2)+1));
if (output == NULL) {
return NULL;
}
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str, strlen(str));
SHA256_Final(hash, &sha256);
int i;
for(i = 0; i < SHA256_DIGEST_LENGTH; i++){
sprintf(&output[i*2], "%02x", (unsigned int)hash[i]);
}
return output;
}
Related
I have 4 gradle build files: when I build in android studio I am constantly having the error:
No signature of method:
org.gradle.model.ModelMap.getDefaultProguardFile() is applicable for
argument types: (java.lang.String) values: [proguard-android.txt]
file 1
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.9.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
file 2
apply plugin: 'com.android.model.native'
model {
android {
compileSdkVersion = 25
buildToolsVersion = '25.0.0'
defaultConfig {
minSdkVersion.apiLevel = 17
targetSdkVersion.apiLevel = 25
versionCode = 1
versionName = '1.0'
}
ndk {
moduleName = 'fpextractor'
platformVersion = 17
toolchain = "clang"
stl = 'gnustl_static' //std::mutex not in gnustl_static
cppFlags.add('-std=c++11')
abiFilters.addAll(['armeabi', 'armeabi-v7a', 'x86'])
//abiFilters.addAll(['armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64']) //this is default
//abiFilters.addAll(['armeabi'])
ldLibs.addAll(['android', 'log', 'atomic', 'z'])
}
}
}
// This is just copy out the header file and built lib into distribution
// directory for clint application to use; it is a small overhead of this sample:
// both lib and app are put inside one project space [save maintenance time]
task(distributeLib, type : Copy) {
// trigger build library
dependsOn assemble
into '../distribution/fpextractor/'
from('src/main/jni/fp_extractor.h') {
into 'include/'
}
from('build/outputs/native/release/lib') {
into 'lib/'
}
}
file 3
apply plugin: 'com.android.model.native'
model {
android {
compileSdkVersion = 25
buildToolsVersion = '25.0.0'
defaultConfig {
minSdkVersion.apiLevel = 17
targetSdkVersion.apiLevel = 25
versionCode = 1
versionName = '1.0'
}
ndk {
moduleName = 'nativeaudio'
platformVersion = 17
toolchain = "clang"
stl = 'gnustl_static' //std::mutex not in gnustl_static
cppFlags.add('-std=c++11')
abiFilters.addAll(['armeabi', 'armeabi-v7a', 'x86'])
//abiFilters.addAll(['armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64']) //this is default
//abiFilters.addAll(['armeabi-v7a'])
ldLibs.addAll(['android', 'log', 'OpenSLES', 'atomic'])
}
}
}
// This is just copy out the header file and built lib into distribution
// directory for clint application to use; it is a small overhead of this sample:
// both lib and app are put inside one project space [save maintenance time]
task(distributeLib, type : Copy) {
// trigger build library
dependsOn assemble
into '../distribution/nativeaudio/'
from('src/main/jni/buf_manager.h') {
into 'include/'
}
from('src/main/jni/android_debug.h') {
into 'include/'
}
from('src/main/jni/debug_utils.h') {
into 'include/'
}
from('src/main/jni/audio_common.h') {
into 'include/'
}
from('src/main/jni/audio_recorder.h') {
into 'include/'
}
from('build/outputs/native/release/lib') {
into 'lib/'
}
}
file 4
apply plugin: 'com.android.model.application'
// Root of 3rd party lib(s): location could be anywhere on the host system
def lib_distribution_root = '../distribution'
model {
repositories {
libs(PrebuiltLibraries) {
// Configure one pre-built lib: shared
nativeaudio {
// Inform Android Studio where header file dir for this lib
headers.srcDir "${lib_distribution_root}/nativeaudio/include"
// Inform Android Studio where lib is -- each ABI should have a lib file
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("${lib_distribution_root}/nativeaudio/lib/${targetPlatform.getName()}/libnativeaudio.so")
}
}
fpextractor {
// Inform Android Studio where header file dir for this lib
headers.srcDir "${lib_distribution_root}/fpextractor/include"
// Inform Android Studio where lib is -- each ABI should have a lib file
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("${lib_distribution_root}/fpextractor/lib/${targetPlatform.getName()}/libfpextractor.so")
}
}
// Configure another pre-built lib: shared;[change to static after Studio supports]
// static lib generation. USING static lib is supported NOW, for that case,
// simple change:
// SharedLibaryBinary --> StaticLibraryBinary
// sharedLibraryFile --> staticLibraryFile
// *.so --> *.a
//gperf {
// headers.srcDir "${lib_distribution_root}/gperf/include"
// binaries.withType(SharedLibraryBinary) {
// sharedLibraryFile = file("${lib_distribution_root}/gperf/lib/${targetPlatform.getName()}/libgperf.so")
// }
//}
}
}
android {
compileSdkVersion = 25
buildToolsVersion = '25.0.0'
defaultConfig {
applicationId='com.gfk.mediawatchapp'
minSdkVersion.apiLevel = 17
targetSdkVersion.apiLevel = 25
versionCode = 22
versionName = '255.0.4'
// Enabling multidex support.
//multiDexEnabled true
}
ndk {
platformVersion = 17
moduleName = 'mwlib'
toolchain = "clang"
stl = 'gnustl_static'
cppFlags.add('-std=c++11')
ldLibs.addAll(['android', 'log', 'OpenSLES', 'atomic'])
//build a default combined apk including all ABIs.
//abiFilters.addAll(['armeabi-v7a'])
abiFilters.addAll(['armeabi', 'armeabi-v7a', 'x86']) //this is default
}
sources {
main {
jni {
dependencies {
library 'nativeaudio' linkage 'shared'
library 'fpextractor' linkage 'shared'
// if gperf were *.a, change shared --> static
//library 'gperf' linkage 'shared'
}
}
jniLibs {
// for shared lib, lib need to be pushed to the target too
// Once libs are copied into app/src/main/jniLibs directory,
// Android Studio will pack them into APK's lib/ directory
// Here we like to avoid another duplication by pointing
// to the files that containing our libs' distribution location
// so the same file is used by compiler at host, also packed
// into APk to be used at Target (phone/tablet)
source {
srcDir "${lib_distribution_root}/nativeaudio/lib"
srcDir "${lib_distribution_root}/fpextractor/lib"
//srcDir "${lib_distribution_root}/gperf/lib"
}
}
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles.add(file('proguard-android.txt'))
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
}
dependencies {
println rootProject.getName()
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:support-v4:25.3.1'
compile 'commons-net:commons-net:3.5'
//compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.google.android.gms:play-services-appindexing:9.8.0'
compile 'com.amazonaws:aws-android-sdk-core:2.4.2'
compile 'com.amazonaws:aws-android-sdk-s3:2.4.2'
compile 'com.amazonaws:aws-android-sdk-ddb:2.4.2'
compile 'com.amazonaws:aws-android-sdk-cognitoidentityprovider:2.4.2'
}
// Unnecessary dependency management:
// Make sure the libs are available when begin compiling application project
// This could be ignored because in real scenario, the pre-built libs are
// already given to us before creating application.
tasks.whenTaskAdded { task ->
if (task.name.contains('compile')) {
task.dependsOn ':nativeaudio:distributeLib'
task.dependsOn ':fpextractor:distributeLib'
}
}
Please: Can anyone help me to understand why I have always the following error:
No signature of method:
org.gradle.model.ModelMap.getDefaultProguardFile() is applicable for
argument types: (java.lang.String) values: [proguard-android.txt]
Gradle experimental does not include getDefaultProguardFile() since it does not have any version of ProGuard config by default.
You can use move the lines from your proguard-android.txt to proguard-rules.pro and then change this line:
proguardFiles.add(file('proguard-android.txt'))
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
into this:
proguardFiles.add(file('proguard-rules.pro'))
For me adding a manifest with
jar {
manifest {
attributes 'Main-Class': com.package.to.main.Class
}
}
helped.
See here: Creating runnable JAR with Gradle
My goal is to build an Android Library embedding the superpowered library. This library provide Android static libraries (.a files) and C++ headers.
I already created a module (with type Android Library) so it use the superpowered library :
I configured graddle so it allows NDK / JNI
I included .a files and headers related to superpowered
In my Java class, I set the native method, which maps to cpp methods.
To create this module I highly used the Cross Example sample provided by superpowered. It is an Android App, and for now as a first step, I just want to break it into 2 parts : an App and an Android library.
In my Android application, I added dependency to this module. But when I call a method which calls a JNI method, I obtain this error :
E/art: No implementation found for void
com.example.mylib.MyDSP.onPlayPause(boolean)
(tried Java_com_example_mylib_MyDSP_onPlayPause
and Java_com_example_mylib_MyDSP_onPlayPause__Z)
Any ideas on why it does not work ?
Sources :
In Android lib :
My java class MyDSP (MyDSP.java) :
package com.example.mylib;
public class MyDSP {
public void CallJniCppMethod() {
this.onPlayPause(true);
}
private native void onPlayPause(boolean play);
static {
System.loadLibrary("SuperpoweredExample");
}
}
In the cpp file : SuperpoweredExample.cpp (SuperpoweredExample.cpp)
extern "C" JNIEXPORT void Java_com_example_mylib_MyDSP_onPlayPause(JNIEnv * __unused javaEnvironment, jobject __unused obj, jboolean play) {
//example->onPlayPause(play);
// We do nothing, but it's OK,
// Just want to see if the JNI call does not throw exception
}
The h file : SuperpoweredExample.h (SuperpoweredExample.h
)
void onPlayPause(bool play);
The graddle configuration for the lib (build.gradle) :
apply plugin: 'com.android.model.library'
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def superpowered_sdk_path = properties.getProperty('superpowered.dir')
model {
repositories {
libs(PrebuiltLibraries) {
superpowered { // this is where you declare the "superpowered" static library
headers.srcDir "${superpowered_sdk_path}"
binaries.withType(StaticLibraryBinary) { // attaching library files to each platform
def platformName = targetPlatform.getName()
if (platformName == "armeabi-v7a") {
staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidARM.a")
} else if (platformName == "arm64-v8a") {
staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidARM64.a")
} else if (platformName == "x86") {
staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidX86.a")
} else if (platformName == "x86_64") {
staticLibraryFile = file("${superpowered_sdk_path}/libSuperpoweredAndroidX86_64.a")
}
}
}
}
}
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
minSdkVersion.apiLevel = 21 // more than 95% of all active Android devices
targetSdkVersion.apiLevel = 21
versionCode 1
versionName "1.0"
}
}
android.ndk { // your application's native layer parameters
moduleName = "SuperpoweredExample"
platformVersion = 21
stl = "c++_static"
CFlags.addAll(["-O3", "-fsigned-char"]) // full optimization, char data type is signed
cppFlags.addAll(["-fsigned-char", "-I${superpowered_sdk_path}".toString()])
ldLibs.addAll(["log", "android", "OpenSLES"]) // load these libraries: log, android, OpenSL ES (for audio)
abiFilters.addAll(["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]) // these platforms cover 99% percent of all Android devices
}
android.sources.main.jni {
source {
srcDir "jni"
srcDir "${superpowered_sdk_path}/AndroidIO"
}
dependencies {
library "superpowered" linkage "static" // this is where you attach the "superpowered" static library to your app
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.1.1'
}
Note :
All my sources are available on Github : https://github.com/DelattreAdixon/Superpowered-Android-Lib
In order to build it/run it, you will have to change le local.properties content so it match you ndk/sdk/superpowered paths.
If you are using experimental gradle, It take care of create cpp file, create functions inside this files and linked it with your java class.
Try deleting cpp file, click on private native void onPlayPause(boolean play) to mark it and them alt+intro, It show a dialog to auto-generate cpp file and the function inside it.
I have added 2 .so prebuilt libraries to a new project in Android Studio which is using the experimental gradle plugin (com.android.tools.build:gradle-experimental:0.6.0-beta5).
My build.gradle file looks like this:
apply plugin: 'com.android.model.application'
model {
repositories {
prebuilt(PrebuiltLibraries) {
gstplayer {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("libs/libgstplayer.so")
sharedLibraryFile = file("libs/libgstreamer_android.so")
}
}
}
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.myexample.gstreamertest2"
minSdkVersion.apiLevel 19
targetSdkVersion.apiLevel 23
versionCode 1
versionName "1.0"
buildConfigFields {
create() {
type "int"
name "VALUE"
value "1"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file('proguard-rules.pro'))
}
}
ndk {
moduleName "gstplayer"
}
productFlavors {
create("flavor1") {
applicationId "com.app"
}
}
// Configures source set directory.
sources {
main {
// jni {
// source {
// srcDirs = ['src/main/jni']
// }
// }
jniLibs {
dependencies {
library "gstplayer"
}
}
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
}
Gradle build is successful, but I can't find instructions anywhere on how to reference these libraries. I know that you can create public native String getInfoFromJni() in your Java file and reference native .c files in your jni folder, and I have been able to get this working, but I don't know how to do something similar with .so libraries.
How do I access the methods in the .so libraries from java?
You should create a wraper c lib:
1.- Change the name of the moduleName to avoid conflicts:
ndk {
moduleName "gstplayerwrapper"
}
2.- Load your wrapper lib in your activity
static{
System.loadLibrary("EcoLogSIL");
}
3.- Built your project
4.- Create a function which call the wrapper and press alt+intro
5.- You should have a new function inside gtsplayerwrapper.c and here you can call libgstplayer.so
JNIEXPORT void JNICALL
Java_your_activty_name_call_1wrapper(JNIEnv *env, jobject instance) {
// YOUR CODE HERE
}
Don't forget to import the library inside gtsplayerwrapper.c
EDIT add headers
repositories {
prebuilt(PrebuiltLibraries) {
gstplayer {
headers.srcDir "src/main/jni/include"
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("libs/libgstplayer.so")
sharedLibraryFile = file("libs/libgstreamer_android.so")
}
}
}
}
Create this folder in your project and copy there .h files
I am attempting to add a native library to my existing application. My goal is to have the C++ library compile in it's own module in Android Studio using the plugin without manual steps (if possible). I have tried a multitude of suggestions and gotten hints that there is an issue with the build system for copying libraries between modules into the build. I have not been able to solve the problem.
Here are the relevant parts (and some) of my setup:
Android Studio:
Gradle Version: 2.10
Project File Structure:
myproject
+libmodule
| +src/main
| | +java
| | | `-MyWrapper.java
| | `jni
| | `-MyJNI.cpp
| `-build.gradle
+appmodule
| +src/main
| | `java
| | `-MyClass.java
| `-build.gradle
+gradle/wrapper
| `-gradle-wrapper.properties
+-build.gradle
`-settings.gradle
myproject/settings.gradle:
include ':appmodule', ':libmodule'
myproject/build.gradle:
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha9'
}
}
allprojects {
repositories {
mavenCentral()
}
}
gradle-wrapper.properties:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
myproject/libmodule/build.gradle:
apply plugin: 'com.android.model.library'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 23
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file("proguard-rules.txt"))
proguardFiles.add(file("proguard-android.txt"))
}
}
android.ndk {
moduleName = "MyLibrary"
stl = "gnustl_shared"
cppFlags.add("-nostdinc++")
cppFlags.add("-I\$(NDK)/sources/cxx-stl/stlport/stlport")
cppFlags.add("-fexceptions")
cppFlags.add("-frtti")
cppFlags.add("-fpermissive")
ldFlags.add("-nodefaultlibs")
ldFlags.add("-Lsrc/main/jniLibs/armeabi-v7a")
ldLibs.add("c")
ldLibs.add("m")
ldLibs.add("dl")
ldLibs.add("log")
ldLibs.add("gcc")
}
android.productFlavors {
create("arm") {
ndk.abiFilters.add("armeabi")
}
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
create("arm8") {
ndk.abiFilters.add("arm64-v8a")
}
create("x86") {
ndk.abiFilters.add("x86")
}
create("x86-64") {
ndk.abiFilters.add("x86_64")
}
create("mips") {
ndk.abiFilters.add("mips")
}
create("mips-64") {
ndk.abiFilters.add("mips64")
}
create("all")
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.1.1'
}
myproject/appmodule/build.gradle:
apply plugin: 'com.android.model.application'
buildscript {
repositories {
mavenCentral()
}
dependencies {
}
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile project(':libmodule')
// Support Libraries
// Maven Provided Libraries
compile fileTree(dir: 'libs', include: ['*.jar'])
}
model {
android {
compileSdkVersion = 23
buildToolsVersion = '23.0.2'
defaultConfig.with {
applicationId = "com.me.myandroidapp"
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 23
}
}
android.dexOptions {
jumboMode = true
}
android.packagingOptions {
//Some specific removals for an included lib from maven
}
android.lintOptions {
checkReleaseBuilds = false
abortOnError = false
}
android.buildTypes {
debug {
debuggable = true
minifyEnabled = false
buildConfigFields.with {
create() {
type = "boolean"
name = "SCREENSHOTS"
value = "true"
}
}
buildConfigFields.with {
create() {
type = "boolean"
name = "DEBUGGABLE"
value = "true"
}
}
proguardFiles.add(file("proguard-rules.txt"))
proguardFiles.add(file("proguard-android.txt"))
}
release {
debuggable = false
minifyEnabled = true
buildConfigFields.with {
create() {
type = "boolean"
name = "SCREENSHOTS"
value = "false"
}
}
buildConfigFields.with {
create() {
type = "boolean"
name = "DEBUGGABLE"
value = "false"
}
}
proguardFiles.add(file("proguard-rules.txt"))
proguardFiles.add(file("proguard-android.txt"))
}
}
android.productFlavors {
create("prod") {
applicationId = "com.me.myandroidapp"
}
create("dev") {
applicationId = "com.me.myandroidapp"
}
create("beta") {
applicationId = "com.me.myandroidapp"
}
create("staging") {
applicationId = "com.me.myandroidapp"
}
}
}
if (project.hasProperty("MyProject.properties") && new File(project.property("MyProject.properties")).exists()) {
// Get properties in the property file
Properties props = new Properties()
props.load(new FileInputStream(file(project.property("MyProject.properties"))))
model {
android {
signingConfigs {
//several configs here
}
}
android.buildTypes {
release {
signingConfig = signingConfigs.release
}
}
}
}
MyWrapper.java:
package com.me.androidwrapper;
public class MyWrapper {
private native String doItNatively(String stringinput);
public String doIt(String stringinput) {
return doItNatively(stringinput);
}
static {
System.loadLibrary("MyLibrary");
}
}
myjni.cpp:
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_me_androidwrapper_MyWrapper_doItNatively(JNIEnv *env, jobject instance, jstring stringinput_) {
// C++ happens here
}
}
MyClass.java:
// Weird behavior for IDE adding dependency module happens here:
import com.me.androidwrapper.MyWrapper;
public class MyClass {
public String makeItHappen(String inputstring) {
MyWrapper mywrapper = new myWrapper();
return mywrapper.doIt(inputstring);
}
}
There are no android.mk files in the JNI.
From a cleaned project gradle executes successfully. When I run Make Module on appmodule I get the error:
Error:(5, 37) error: package com.me.androidwrapper does not exist
...and the import statement from MyClass.java is highlighted.
As noted above in the code for MyClass.java, Android Studio offers a quick fix for including a dependency for Module "libmodule" and if I select it the IDE drops the errors. The IDE then resolves the project links correctly if I command-click through the package, class or methods.
I have followed a number of solutions on StackOverflow and in groups for the plugin. There is mention of the new experimental plug-in and build system not copying native libraries between modules in several of them and I have tried methods that set up a aar/jar module as an intermediary. I have also tried methods for manually copying the aar file into the module lib and referencing it as a file or as an aar. Most of these methods have not worked, the best result I have had is to have a successful build, but the application crashes not finding libMyLibrary.so
I have successfully tested the project by including the JNI directly into the appmodule Module using gradle 2.8 with android experimental plugin 0.4.0. This is not a very good solution as the module is complex and the C++ code is maintained separately. The 0.4.0 plugin fails as a multi-module, the library's .so does not package.
There are gaps in my knowledge of the new experimental plugin and I know it has bugs, it is incomplete and some features are still in discussion. Any assistance in tracking down my mistake, or providing a comprehensive work around to the plugin's lack of features would be greatly appreciated.
If you want to add some native libraries to your existing application in Android studio, you can do it in three standard ways. Please read this link https://stackoverflow.com/a/35369267/5475941. In this post I explained how to import your JAR files in Android studio and I explained all possible ways step by step with screenshots. I hope it helps.
I have a native library which I am trying to build with gradle. If I invoke the ndk-build command from the gradle file, I am able to build the native library. But if I try to use the ndk build functionality built in the android gradle plugin I an unable to build.
I get fatal error: android_native_app_glue.h: No such file or directory
The relevant section of the gradle file is:
buildTypes.debug.jniDebugBuild true
defaultConfig {
ndk {
moduleName 'myModule'
stl 'gnustl_static'
cFlags '-UNDEBUG -Werror -Wunused-variable -Wunused-but-set-parameter -Wtype-limits -Wmissing-field-initializers -Wreturn-type -Wuninitialized'
ldLibs 'log', 'GLESv2'
}
productFlavors {
armv7{
ndk {
abiFilter 'armeabi-v7a'
}
}
}
}
Is there a way to tell the ndk build where to find the android_native_app_glue.h file?
On a side note, is there a way to pass the verbose flag to ndk-build, the equivalent of ndk-build V=1 ?
I had the same issue and I fixed it by adding "-I{path_to_android-ndk}/sources/android/native_app_glue" to cFlags, see here
As of:
gradle-experimental:0.6.0-alpha2
gradle-2.9-all.zip
One way to do it (Or to integrate any code that can be compiled and link as a static library) is to create in your project a new module, and change the gradle file of that module to be:
apply plugin: 'com.android.model.library'
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkDir = properties.getProperty('ndk.dir')
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
minSdkVersion.apiLevel = 21
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "0.0.1"
}
compileOptions.with {
sourceCompatibility=JavaVersion.VERSION_1_7
targetCompatibility=JavaVersion.VERSION_1_7
}
}
android.ndk {
moduleName = "native-activity"
cppFlags.add("-Werror")
ldLibs.addAll(["log", "android"])
stl = "gnustl_static"
ldFlags.add("-c")
}
android.sources {
main {
jni {
source {
srcDir "${ndkDir}/sources/android/native_app_glue"
}
}
}
}
}
Then in your module's gradle.mk you should just add:
apply plugin: 'com.android.model.application'
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkDir = properties.getProperty('ndk.dir')
model {
android {
[...]
}
android.ndk {
[...]
cppFlags.add("-I${file("${ndkDir}/sources/android/native_app_glue")}".toString())
}
android.sources {
main {
jni {
dependencies {
project ":native-activity" linkage "static"
}
}
}
}
}
dependencies {
compile project(':native-activity')
}
One way to do this is to add it to your LOCAL_C_INCLUDES in Android.mk, like this:
LOCAL_C_INCLUDES += /path/to/ndk/sources/android/native_app_glue
Make sure the path is correct, by doing an ls on /path/to/ndk/sources/android/native_app_glue/native_app_glue.h
add these line in your cMakeList.txt file
//line1
include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
//line2
add_library(native_app_glue STATIC
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
also add native_app_glue in target_link_libraries.
It come in effect only after click on RUN or shift + F10
Add to cmake
include(AndroidNdkModules)
android_ndk_import_module_native_app_glue()
target_link_libraries(
native_app_glue
)