Android Studio - include and consume .so library - java

I need to use some native libraries(.so) in my android project. According to some answers here in StackOverflow about this topic, I created a jniLibs folder in app/src/main and put there my files:
armeabi/my_lib.so
armeabi-v7a/my_lib.so
x86/my_lib.so
Then, in my activity class I use:
static {
System.loadLibrary("my_lib");
}
But when I run the app, an UnsatisfiedLinkError exception is generated. If this is important to be noticed, I don't have an Android.mk file, and I haven't changed anything that has to do with this in my gradle files. So, the only think I did is to copy-paste my .so files in jniLibs and to write the code above in my activity. So what might be the cause of this problem? Am I missing something?
EDIT
This is my gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 15
buildToolsVersion "23.0.3"
compileOptions.encoding = 'ISO-8859-1'
defaultConfig {
applicationId "my.package"
minSdkVersion 4
targetSdkVersion 4
ndk {
moduleName "my_so_lib"
}
}
sourceSets {
main {
jni.srcDirs = ["libs"]
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
debug {
debuggable true
}
}
splits {
abi {
enable true
reset()
include 'x86', 'armeabi-v7a', 'mips', 'armeabi'
universalApk false
}
}
}

Solution 1
Create Folder "jniLibs" inside "src/main/"
Put all your .so libraries inside "src/main/jniLibs" folder
Folder structure looks like :
|--app:
|--|--src:
|--|--|--main
|--|--|--|--jniLibs
|--|--|--|--|--armeabi
|--|--|--|--|--|--.so Files
Can you please confirm that you have this hierarchy ?
No extra code requires just sync your project and run your application.
Reference
https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main
Solution 2
Add both code snippets in your module gradle.build file as a dependency:
compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
How to create this custom jar:
task nativeLibsToJar(type: Jar, description: 'create a jar archive of the native libs') {
destinationDir file("$buildDir/native-libs")
baseName 'native-libs'
from fileTree(dir: 'libs', include: '**/*.so')
into 'lib/'
}
tasks.withType(Compile) {
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
source

Thank you guys for helping but it was a stupid problem. When I imported my .so files under jniLibs, they were named like libSONAME.so. In these lines of code:
static {
System.loadLibrary("libSONAME");
}
we should not use System.loadLibrary("libSONAME");, but just System.loadLibrary("SONAME");.
Then, just build the project and everything was OK.
Thank you all for helping. I hope this will save time to someone else.

What is your gradle version? If you have a 0.7.3 or a newer version then the next article should help you:
Click here!

Related

How to have ALL Android Studio 3.5 source files NOT be in usual location in project tree but on a separate drive

I'd like to keep my java source files (i.e., those that I will create or edit) on an external or a second internal drive, separated from the hundreds (or thousands) of files created during compilation. Let all project files be on drive C: except my editable source files.
Let's call the drive to put the sources on X:.
Here is a normal AS 3.5 project tree for C:\users\me\AndroidStudioProjects\myProject:
and here is the ...\app\src folder:
I don't want to have the entire app folder on drive X: because app (notably app\build\intermediates) will contain hundreds (likely thousands) of files and folders.
I just want the very small ...\app\src folder on X: partly for the purpose of having a 90% smaller backup size for projects.
It seems like this would be a common thing for an AS user to want, but lots of Googling hasn't shown much in the way of concrete specific examples.
For better or worse, here's what my build.gradle file has (d)evolved into:
apply plugin: 'com.android.application'
buildscript
{
repositories
{
jcenter()
google()
}
dependencies
{
classpath 'com.android.tools.build:gradle:3.5.0'
}
}
android
{
compileSdkVersion 26
defaultConfig
{
applicationId "com.dslomer64.sqhell"
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "3.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes
{
release
{
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies
{
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2',
{
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
}
I didn't write any of it. I only took what compilation produced, changing only whatever the latest build error caused me to change.
Yes, I need to learn gradle. But not today, please.
I suspect sourceSets may be where to stick something like X:\AndroidStudioProjects\myProject\src, where src will contain the main folder shown in the second picture. And I gather that the 'src' or 'srcdir' keyword should precede that path.
EDIT
Here's what I've come up with so far:
sourceSets
{
main
{
java { srcDir 'X:\\AndroidStudioProjects\\myProject\\src\\main' }
}
}
End Edit
Surely there are a relatively few lines inside a new block in my existing build.gradle file that could be added to accomplish the task. Surely someone on SO has done this very thing. Please provide or share the required block and any other changes that may also be required.
I will most certainly appreciate the gift.

How to Add and Use an AAR in AndroidStudio Project

I am trying to use a custom aar in my android project. I found dozens of examples in StackOverflow and the Web. Many failed at build, none worked. The clearest was at
http://kevinpelgrims.com/blog/2014/05/18/reference-a-local-aar-in-your-android-project/
That came closest to working.
Here's what I did
Successfully created a very simple AAR (Ref.aar) from Ref.java
// Ref.java
package com.ramrod.Ref;
public class Ref {
// Square an integer
public static int
square(int val) {
return (val * val);
}
}
Created a test project (RefTest)
Created folder 'libs' under RefTest/app
Added Ref.aar to libs
File->New->New Module->Import .JAR/.AAR Package.
Selected Ref.jar as filename->Finish (appeared successful).
Modified build.gradle
// build.gradle (Module: app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.ramrod.RefTest"
minSdkVersion 11
targetSdkVersion 15
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
compile( name:'Ref', ext:'aar' )
}
}
Sync build.gradle (all)
Added reference to Ref.aar method (square) to onCreate in RefTest main activity.
int sq = Ref.square( 2 );
Build->Clean then Build->Rebuild.
This produced error: cannot find symbol variable Ref
I'm sure I'm doing something naive or just plain dumb, but I can't see it.
Any help appreciated.
You should:
1) create aar library and just put it in libs directory ( without "File->New->New Module->Import .JAR/.AAR Package" )
2) add to build.gradle (Module: app)
dependencies {
...
implementation fileTree(include: ['*.aar'], dir: 'libs')
...
}
After that you can use Ref.square(int);
Your apk will contain after build:
When you import an AAR from built in helper tools using Import aar/jar option,
studio creates a module with this aar.
So at this state you can see something similar to the state mentioned below.
When display panel is Android,
Change your panel mode to Project and open your testaar , you can actually see a build.gradle file for your module and the corresponding aar.
That is why your statement
compile( name:'Ref', ext:'aar' )
was not working.
To add this aar to your project(after using import aar/jar), what you can do is to first add the module to the settings.gradle (Project settings file)
include ':app', ':testaar'
then directly add to your application level build.gradle file
implementation project(':testaar')
2)Another way is to
Right-click on your Application Module ->Select Open Module Settings -> Select the Module -> Go to Dependencies tab
P.S you can also open this window from Build->Edit Libraries and Dependencies
You will come across a window as below
Click on the small + icon, then Module option and finally add the required module(testaar)
Sync your code and voila it will start working now.

Android aar library doesn't contain dependencies

i saw similar questions, but not found accepted answers.
Problem - i have my own android library with some tiny functions.
My library uses others - f.e. Hawk (no sql database).
My library gradle file:
apply plugin: 'com.android.library'
buildscript {
repositories {
maven { url "https://www.jitpack.io" }
}
}
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'library.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.0.2'
compile 'com.github.orhanobut:hawk:1.23'
testCompile 'junit:junit:4.12'
}
Library works fine. And if i use it as project inside another project - it work too. But when i generate *.aar file (with gradle -> assembleRelease) and include into separate project - it fails. Project see ONLY MY library's class. Hawk com.orhanobut.hawk package and ofc others (if i will use then) are not visible. So ClassNotFoundException comes.
If i remove
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'library.pro'
the result doesnt change.
I tried to add the following line into proguard file (library.pro)
-keep class com.orhanobut.hawk {public *;}
-keep class com.orhanobut.hawk.* {public *;}
Result is the same.
So i have two question:
1 - what should i do to make my main project see my library's third party dependencies?
2 - is is possible to obfuscate my library's code (only mine, not dependencies)?
what should i do to make my main project see my library's third party dependencies?
The aar file doesn't contain the transitive dependencies and doesn't have a pom file which describes the dependencies used by the module.
It means that, if you are importing a aar file using a flatDir repository you have to specify the dependencies also in your project.
You should use a maven repository, private or public, to avoid the issue.
In this case, gradle downloads the dependencies using the pom file which will contains the dependencies list.
Another way to solve the problem of dependencies is to get the jar files of the dependencies you want to use and place them in the libs folder of your module. This will copy all the your dependency jars into your library's jar or aar.
Note that I have emphasized jar because you cannot include aar file in libs folder, gradle still doesn't support aar file inside aar out of the box. There are a few gradle plugins like fataar which solve that problem.

How to add an .so file to an Android Studio 1.5 project?

This seems to be a popular problem with Android: I have a precompiled .so file that I would like to access via the JNI, but I cannot get Android Studio (in my case version 1.5) to build the project in a way that makes this file accessible. Like the other people asking this question, I hit an UnsatisfiedLinkError when calling System.loadLibrary():
static {
System.loadLibrary("NativeLib");
}
There are several questions like this one on StackOverflow, and the solutions appear to focus on two techniques, neither of which work for me:
Creating a main/jniLibs directory: Several people say that if you create a folder called /app/src/main/jniLibs and within that a folder for your target (I tried all of armeabi, armeabi-v7, and arm64-v8a), Android Studio will find the library. See also This question. If I do this, the native call in my java code remains highlighted in red with tooltip text, 'Cannot resolve corresponding JNI function Java_my_function_etc'. The tooltip reference is identical to my method call, which I generated with the javah utility.
Modifying build.gradle Another proposed solution is to point to the location of the .so file by making a modification to build.gradle. In my case, I tried setting jniLibs.srcDirs to /src/main/jniLibs, and 'jniLibs' while the .so file in question was located in /app/src/main/jniLibs/armeabi, /app/src/main/jniLibs/armeabi-v7a, and /app/src/main/jniLibs/arm64-v8a. My gradle file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.my.application"
minSdkVersion 21
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['jniLibs']
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile files('libs/commons-lang3-3.1.jar')
}
A third technique which appears to have emerged from a Google Groups posting in 2013 involves packaging the .so files into a jar and including the jar file in the project. I unzipped my APK file and found that the .so files are included in ./lib/armeabi, ./lib/armeabli-v7a, and ./lib/arm64-v8a. I didn't try this technique because it seems obsolete, and unnecessary since my .so files are making it into the APK.
I'm out of things to try. Is there any other technique for including a native .so in an Android Studio project? Is there anything I could have overlooked in the above two techniques? Has Android Studio changed in some critical way since the linked questions were answered?

Gradle Android Maven Plugin doesn't create the pom file automatically

I would like to know how to create a pom file with "Gradle Android Maven Plugin".
I followed the steps on http://www.gradle.org/docs/current/userguide/maven_plugin.html (chapter "Convention Methods"). I also created the directory "buildDir" and get no errors. The App was build successfully but nevertheless the pom file doesn't exist. I am using Android Studio IDE.
Is it possible that the newpom.xml file exists on runtime only and does not exist in my project folder buildDir after runtime? Maybe I am looking for something which can't be found.
My app/build.gradle looks like this:
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
defaultConfig {
minSdkVersion 16
targetSdkVersion 19
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
apply plugin: 'maven'
task writeNewPom << {
pom {
project {
inceptionYear '2008'
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution 'repo'
}
}
}
}.writeTo("$buildDir/newpom.xml")
}
dependencies {
compile 'com.android.support:support-v4:+'
compile 'com.google.code.gson:gson:2.2.4'
compile 'com.android.support:appcompat-v7:+'
compile files('libs/retrofit-1.5.1.jar')
}
Can someone tell me if I missed something? :)
Best Regards,
Philip
No need to create buildDir manually, it has default value and refer to /build folder that place in same folder as build.gradle file.
Did you run follow command?
gradle writeNewPom
after run it I got newpom.xml file in projectroot/build folder, BUT it contains no dependencies however I have dependencies in build.gradle file.

Categories

Resources