I have a MyLocationService library, which has dependency from huawei_location_service.Inside I have HMSLocationService class which is the only one using huawei_location_service classes and I use relfection to access that class. Meaning is, if we run app on Huawei and if there is dependency from huawei_location_service, I will get location, otherwise will not. And application should run perfectly on non-hauwei devices without dependency from huawei_location_service.
So when I build MyLocationService.aar I removed huawei_location_service dependency from it's pom file. After that I created a new application and added dependency from MyLocationService.aar. When I check dependencies with command gradlew app:dependencies I don't see any dependency from huawei, but when I create an apk and analyze it, in classes.dex there are classes from huawei_location_service.
Question: How it is possible? And is there any other way to achieve what I want?
P.S. I analyzed also MyLocationService.aar, didn't find any huawei dependency. Is there another way to check dependencies of *.aar files instead of pom or analyzing tool of android studio?
So if someone will be mistaken as me, this answer will help.
The repositories and classes I saw in classes.dex were not coming from hms libraries. As I have imports in my custom classes, that imports' texts were the reason I was seeing huawei folder in classes.dex. Also take attention on the size, and you can see that they are kind of 20 bytes.
So I removed the imports, generate my library again, created apk and analyzed it and woala, no huawei folder is visible.
P.S. *.aars doesn't contain any library if you not put transitive=true. And you need to add dependencies required by your lib in your own applicaiton.
P.S.S. If you have locally or globally publishing your library, maven(Gradle uses maven) creates metadata, so called POM file, as a helper to identify all dependencies that the library needs.
Related
I'm trying to build an app bundle but I'm getting the following error:
File 'root/lib/x86_64-MacOSX-gpp/jni/libjunixsocket-native-2.0.4.jnilib' uses reserved file or directory name 'lib'.
For what I've seen from similar questions, this issue is normally solved juggling dependencies or files in the project structure, but in this case it seems to point to a native library involved in app architecture if i'm not mistaken. Any ideas how to solve this?
It looks like you are adding a dependency as a jar instead of an aar.
The aar contains the information of what files should be considered as Android resources, native libraries, etc. in the app. A jar is just a plain list of files without Android concept. Because the jar you're depending on contains a directory lib, the files would normally end up being considered as native libraries, but because the files come from a jar instead of an aar, the build system warns that it's unlikely to be a native library and may have unintended consequences at runtime.
Try to package that library as an .aar instead of a .jar. See this documentation: https://developer.android.com/studio/projects/android-library
Edit:
Note that this file could not be loaded by the Android platform if it was included as is in the APK, so even though the previous build systems would allow you to put anything in an APK, the Android App Bundle is more restrictive to ensure that you don't accidentally put unnecessary files which would increase unnecessarily the size of your app.
Ok it is working now! Steps I used to found the problem (thanks for pointing me in the right direction #Pierre)
Run a gradle build --scan from your terminal or go to the Gradle tab in Android Studio, select :app, help , androidDependencies to see your dependency graph.
Search the dependency graph for the library name related to the problem ( in my case I searched for socket, there was no match for libjunixsocket for example).
Going upwards on the dependency tree I realized it was caused by the 'io.voucherify.android.client:voucherify-android-sdk:2.1.0' dependency.
I just added #aar at the end of the dependency implementation, and I managed to build the app bundle.
implementation 'io.voucherify.android.client:voucherify-android-sdk:2.1.0#aar'
I'm using many applications in one project like :
So i have some questions here, Application must implement iterated libraries ?
Assume i have com.android.support:appcompat in my "app" gradle and have the same one in my "opencv-java" gradle the apk will compiled with both libraries and double the size?
If no, then what happened in compiling process?
If yes, How i can avoid this, is there a way or some thing?
Update :
If i have libraries (e.g: "volley", "support" etc..) in my app "gradle" and also i used it in my open-cv "gradle", that's make me able to remove those libraries from app "gradle", it's seems that main app that used compile project(':another-app') in "gradle" can use another-app libraries, with codes and assets, every thing.
the apk will compiled with both libraries and double the size?
No.
then what happened in compiling process?
Well, one of two things:
If you use compile "com.android.support:appcompat-v7" consistently, Gradle will only use one copy of that dependency.
Your build could fail with an error message complaining about duplicate Java classes, stemming from the duplicate libraries. This would happen if you are not actually using com.android.support:appcompat-v7 in one place, but instead are adding appcompat-v7 by some other means (e.g., directly compiling against a copy of that library project).
What can't happen is your double-the-size scenario, as you cannot have two copies of the same Java class in a single APK.
I was wondering what is the recommended way of including library projects in an Android Studios gradle like this:
First way:
compile 'de.greenrobot:greendao:2.1.0'
Second way:
compile files('libs/greendao-2.0.0.jar')
and what are the pros and cons.
In the first case gradle is completely handling the process of dependency management, i.e. downloading the jar and including it in your project.
In the second case you have to manually download the jar and include it in the libs folder.
The simpler and preferred way is the first.
First way: compile 'de.greenrobot:greendao:2.1.0'
PRO:
Easy, quick to update
CON:
Internet connection required when updating your gradle file
Second way: compile files('libs/greendao-2.0.0.jar')
PRO:
You can make changes to the library and those won't be overwritten.
Like Qian Sijianhao said, it's quicker to build.
CON:
More work to set up, update
In most cases I think you want to go with the first way.
Trust me, the second way will save lots of your building time.
By the way , time is money.
In the first way, i.e:
compile 'de.greenrobot:greendao:2.1.0'
compile 'com.library.sample:library:x.x.x'
Gradle will finding these dependencies, and making them available in your build. If your dependencies have a dependencies, gradle will also finding them and include it for the project. So you don't need to manually add all the dependencies.
Quoting from Gradle documentation:
7.1. What is dependency management?
Very roughly, dependency management is made up of two pieces. Firstly,
Gradle needs to know about the things that your project needs to build
or run, in order to find them. We call these incoming files the
dependencies of the project. Secondly, Gradle needs to build and
upload the things that your project produces. We call these outgoing
files the publications of the project. Let's look at these two pieces
in more detail:
Most projects are not completely self-contained. They need files built
by other projects in order to be compiled or tested and so on. For
example, in order to use Hibernate in my project, I need to include
some Hibernate jars in the classpath when I compile my source. To run
my tests, I might also need to include some additional jars in the
test classpath, such as a particular JDBC driver or the Ehcache jars.
These incoming files form the dependencies of the project. Gradle
allows you to tell it what the dependencies of your project are, so
that it can take care of finding these dependencies, and making them
available in your build. The dependencies might need to be downloaded
from a remote Maven or Ivy repository, or located in a local
directory, or may need to be built by another project in the same
multi-project build. We call this process dependency resolution.
Note that this feature provides a major advantage over Ant. With Ant,
you only have the ability to specify absolute or relative paths to
specific jars to load. With Gradle, you simply declare the “names” of
your dependencies, and other layers determine where to get those
dependencies from. You can get similar behavior from Ant by adding
Apache Ivy, but Gradle does it better.
Often, the dependencies of a project will themselves have
dependencies. For example, Hibernate core requires several other
libraries to be present on the classpath with it runs. So, when Gradle
runs the tests for your project, it also needs to find these
dependencies and make them available. We call these transitive
dependencies.
Gradle will store the downloaded library to your USER_HOME/.gradle. In Linux, it will store it in /home/user/.gradle/caches/modules-2/. in Mac it will store it in ~/.gradle/caches/modules-2/.
By the way, if you have used the library, you can set Android Studio to use a local cache of the library.
In the second way, you need to manually add the library for your project. And you also need to include all the remaining dependencies of the library. This is so error prone.
I understand this might be an extremely obvious and ridiculous question to ask, but please excuse me as I'm a beginner. I want to integrate this file into my project so I can call its methods:
https://github.com/RomainPiel/Shimmer-android
The question is, what do I do with it? Is it considered a "module", "library" or "file"? Should I manually copy the source files and create new classes in my project, and then call the methods from there? This would be the most straight-forward but in the "how to use" section in that package, it was mentioned "compile 'com.romainpiel.shimmer:library:1.4.0#aar'"
What I tried:
I downloaded the file as a .zip and then File->New->Import Module then navigated to the unzipped file. I believe I'm then supposed to add "compile 'com.romainpiel.shimmer:library:1.4.0#aar'" so I went to the gradle file to try to add it.
There are two: build.gradle (Module:app) and (Project:ProjectName).
I've tried adding to either and\or both and got this error: (Error:9,0) The project 'ProjectName' may be using a version of Gradle that does not contain the method. Did I do something wrong? Is it supposed to be this easy?
I would be extremely grateful to anyone who can point me in the right direction :)
You have three option
Using the GitHub Desktop you can clone the project and open it like a local project. Every change you make will be tracked. You can then commit and push using the GitHub Desktop. It's all UI and simple to use.
https://desktop.github.com
On Android Studio, when you open it, you'll see this, select GitHub and continue by adding your credentials.
You can then commit and push directly from that.
Using the terminal / command line.
If you are new, I recommend the first. It's simple to use and you get a hang of using it as it is the same steps with any project on any IDE you use.
Note: Downloading it as zip and then using it a bad idea because you're making it difficult on yourself because you can't keep track of changes and you'll have to re-upload everything every time. Which defeats the purpose of version control
If that GitHub account is not yours, then you'll have to fork the project, this way you'll have a separate version of the code on you GitHub on which you can modify. If it is yours then you're good.
Typically, you do not want to include external source code manually. This inhibits your build tool's (i.e. Gradle's) ability to manage that source code. It's very easy in Gradle to, say, set the version (like you have done by specifying "1.4.0") and then later remind yourself what version you have by merely looking at your build.gradle file. However, how would you go about doing that with raw source code? Typically developers do NOT put the version number of the source code in the actual source code - that's what they use their version control system (e.g. git) for, usually with tags.
Another aspect of Gradle is downloading and caching (and compiling) the external project for you. So that's nice.
With that said, you typically want to put that "compile..." line in your module's build.gradle file. Not the Project's build.gradle.
A module corresponds to your application (or library) that you are building or using. Some project's have multi-module configurations, where one module acts as a dependency for another (or several others). A Project in gradle is more of a 'meta' configuration that you can apply to all of your modules. The gradle docs recommend you focus on your module's configuration first and adjust the Project's configuration only if you have a specific need and reason to do so.
For the error you mentioned, you might have some unnecessary configurations in your build.gradle file, or the tool version numbers might not reflect what's on your system - if you copied and pasted from the internet, you might want to correct this by letting your IDE generate that file (the brute-force approach would be to create a new project entirely, and use its build.gradle files as a reference). Before you do that, you might want to check if your IDE provides any warnings inside that file.
You have to add the dependency to your module's gradle file.
There are two gradle file present in an android project. One is the project gradle and the second is the module gradle for each individual module.
You just have to copy the given
compile '......' in the dependency block.
I have the osmdroid code from github and have it in an Android Studio project, with top-level structure like so:
+OpenStreetMapViewer
+osmdroid-android
+osmdrod-packager
+osmdroid-third-party
+sample
+Gradle Scripts
Then I added my own module:
+OpenStreetMapViewer
+MyModule
+osmdroid-android
+osmdrod-packager
+osmdroid-third-party
+sample
+Gradle Scripts
MyModule has an Activity (an AppCompatActivity) and it runs just fine. Now I want to use the class MapActivity from OpenStreetMapViewer in MyModule
So I add the dependency to the build.gradle for MyModule
dependencies {
...
compile project(':OpenStreetMapViewer')
}
This doesn't' seem to work because:
- When trying to use MapActivity in MyModule, it doesn't know where to find it
- I get this warning:
Warning:Dependency org.osmdroid:OpenStreetMapViewer:5.0-SNAPSHOT on project emnrdstickylistheaders resolves to an APK archive which is not supported as a compilation dependency.
File: D:\Users\myusername\AndroidstudioProjects\osmdroid-stickylist\OpenStreetMapViewer\build\outputs\apk\OpenStreetMapViewer-release-unsigned.apk
How do I do this?
I'll get flak for this, but if importing a class from another APK is what you need to do, then don't use gradle. Maven can do it via the maven-android-plugin https://github.com/simpligility/android-maven-plugin. In fact, that's what osmdroid does for the integration tests. It's an APK project that depends on an APK. Of course, the downside to this is that the support for using maven as a build tool with android studio is terrible. It's slightly better with Intellij, but still has a number of open issues, such as this one https://youtrack.jetbrains.com/issue/IDEA-145825
The real question should be, "is this the right approach?" (importing an APK as a dependency). To which, I'd answer, considering the state of the current build tool support with gradle, no. You are probably better off either copying the relevant portions of the MapActivity into your own project or starting from scratch and only import the libraries you need as dependencies. In other words, your gradle file should contain this (which is here: https://github.com/osmdroid/osmdroid/wiki/How-to-add-the-osmdroid-library-via-Gradle) :
dependencies {
compile 'org.osmdroid:osmdroid-android:5.0.1#aar'
}
and then follow the rest of the how to guides located on the osmdroid wiki here: https://github.com/osmdroid/osmdroid/wiki/How-to-use-the-osmdroid-library for how to use it to suite your needs.
There's a number of ways to go about making osmdroid bend to your needs. If you can't make it do what you want, open an issue on github. I am a contributor and have write access and can help out.