As Gradle does not support apklib dependencies how can one migrate from apklib dependencies to aar dependencies? Is it possible to either manually or automatically convert apklib dependency to aar? If yes - how, if no - why not?
In this question I assume that I don't have original project for apklib, but rather the file itself.
apklib doesn't contain object files, only source files, so the only way it can be included in any project is by recompiling it. According to some docs you can read at:
Android dependencies : apklib vs aar files and https://plus.google.com/+ChristopherBroadfoot/posts/7uyipf8DTau
The apklib format was invented as a way to share Android code+resources. It’s essentially a zipped up Android library project, which was already the status quo for code+resource sharing.
And you can see in Chris Broadfoot's post that the task that generates the apklib just zips up the AndroidManifest.xml file and the src and res directories:
task apklib(type: Zip) {
appendix = extension = 'apklib'
from 'AndroidManifest.xml'
into('res') {
from 'res'
}
into('src') {
from 'src'
}
}
Note that his post is about creating an apklib from Gradle, which is a slightly weird thing to want to do, but it provides a pretty clear idea of how one of these things is structured.
The good news is that this is "standard" Android project structure as of when Eclipse was the primary IDE, and Android Studio knows how to import modules that look like this. So follow these steps:
Unpack your apklib into a temporary directory. It's in zip format, so something like unzip library.apklib should work.
Look at what's unpacked. You should see a directory containing AndroidManifest.xml, src, and res folders.
In Android Studio, inside an existing project, choose File > Import Module and point it at the directory from step 2.
Android Studio should manage the import by copying the files into your project in a new module, arranging them in its preferred directory structure, and will add a build.gradle file for the module.
At this point you're up and running. If you actually want the .aar file, then check to see if your new module is set up as a library module or an application module. In its build.gradle, if you've got apply plugin: 'com.android.library' then it's a library module, and Gradle will generate an .aar as part of the build: it will be in the build/outputs/aar directory after a successful build.
If your module imported as an app module and not a library (apply plugin: 'com.android.application', then change that apply plugin statement, and you may also need to remove the applicationId statement from the build file. Now it should compile as a library and generate a .aar.
Happy coding!
You cannot convert the apklib to aar. You have to update the dependencies manually to point to an aar file. The aar is compiled and contain lint and proguard rules which the apklib can't necessarily determine automatically.
You can read a bit more on the differences here:
Android dependencies : apklib vs aar files
Related
In my Android application project I am trying to avoid referencing an external Maven repository in my project from where I would load multiple .aar artifacts which make up one SDK.
Instead, I would like to put the .aar files into my project and then reference them from one of my Gradle Android library modules.
I already tried different approaches - none worked, though.
Approach 1: Composite build (includeBuild)
Inspired by https://stackoverflow.com/a/72672032/35689
Here my artifact(s) cannot be resolved by Gradle.
I also tried this in isolation with the sample project - for some reason it does not work with my artifacts. In the example there is only one .aar file which might be the reason.
Approach 2: One module per aar
Inspired by https://stackoverflow.com/a/70074787/356895
Here I end up with this error:
jetified-externallibrary-1.2.3/res/values/values.xml:113:5-122:13: AAPT: error: style attribute 'attr/shimmer_auto_start' not found.
You have to manually add all of the .aar file's dependencies to your project in order to make this work. You will also have to substitute the maven dependency with the .aar file manually.
The reason is that an individual .aar file does not contain any metadata like maven coordinates, version, dependencies, etc. Therefore Gradle cannot handle any of this for you automatically.
I am working on Salesforce Chatbot development for mobile applications. I have to develop it on xamarin(.Net). For that I need to have .Net libraries but those are doesn't seem to available.
Alternate way is to get .jar files of those Android libraries, add in .Net project and use it for development.
I am looking jar file for below configuration
allprojects {
repositories {
google()
jcenter()
maven {
url 'https://s3.amazonaws.com/salesforcesos.com/android/maven/release'
}
}
}
implementation 'com.salesforce.service:chat-ui:4.3.2'
I found above information here developer.salesforce.com/docs. I am unable to download .jar files for above configuration on internet.
Than I tried to develop sample project using above libraries in android studio and get .jar files from it. I have made the project. I want to get .jar files.
I have two question now
How to download .jar files for above configuration from internet OR
How can I download .jar files from android studio from sample project I created
Edit 1:
Below screenshot of ChatUIConfiguration from C# .dll, there is no create method. While create there for Android public static ChatUIConfiguration create. ChatUIConfiguration has 278 lines of code in android file and C# has only 100 lines. Am I missing any dependency or I need to add multiple jars from dependency folder?
After creating your sample project, you can get the .aar dependencies in Gradle based on this fine answer:
Add the following to the build.gradle file:
configurations {
customConfig.extendsFrom implementation
}
task copyLibs(type: Copy) {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
from configurations.customConfig
into "$project.rootDir/dependencies/"
}
Note the small addition regarding the duplicatesStrategy to avoid an error.
In Android Studio you can open the .gradle file, scroll to the .copyLibs task and click on the green arrow button on the left side.
This downloads the .aar files into a folder called dependencies. Among many others there is a file named chat-ui-4.3.2.aar.
Afterwards you can extract .jar files from .aar, just like described in this nice answer.
Manual Check
Finally if you want to do it manually or check against the .pom file: you can download the .pom file from here: https://s3.amazonaws.com/salesforcesos.com/android/maven/release/com/salesforce/service/chat-ui/4.3.2/chat-ui-4.3.2.pom
The other sub-dependencies are also listed there.
I built one android studio project. I wanted to use it as a library in another project. I followed below steps for same:
Changed apply plugin: 'com.android.application' to 'com.android.library'
Removed applicationId from defaultConfig{}
Clicked on sync
This gave me .aar file in build-->outputs-->aar-->myapp.aar
I imported this .aar file in my other test project. I followed below steps for this:
File-->New-->New module-->Import .jar/.aar package-->myapp.aar
In build.grade of test application added compile project(path: ':myapp')
Clicked on sync.
This produced one folder inside external libraries called myapp-unspecified.
There i get all res files but i did not get the class files inside classes.jar.
Inside classes.jar I only have MANIFEST.MF.
Am I doing something wrong or am I missing something??
Experienced the same problem. My issue was that I had removed a dependency from my library project (in this case, testCompile 'junit:junit:4.12'), but did not delete the directory and classes that referenced the APIs from that dependency. An aar file was output to the build folder, but I was not able to access its contents when I included it in my application project.
After deleting the unused classes and directories and re-syncing my library project, I was able to produce a working aar.
Ran into the same issue. The classes are actually there or at least were for me. All that I needed to do was right click the application I was importing my library into. Click open module settings. Then go to dependencies on the right side. Add your library there as well so that the java will compile will your application.
Question as in title. A similar question was asked here, and the only workaround that time was to publish the project into a local Maven repository.
Is this problem fixed (as claimed by some) in Android Studio 0.5.+? In its release note there is a statement that says "Support for source folders outside the module content root". Does that mean we can finally import the library from outside the project folder?
I tried File->Import Project.. but it doesn't work.
EDIT 2: See accepted answer for latest solution (as of 0.8.+)
EDIT:
My project directory structure has only one module main which looks like this
MyApp
main
build.gradle
src
build.gradle
settings.gradle
The library project directory has only one module named like lib (they are all auto-generated when creating a new library project)
MyLibrary
lib
build.gradle
src
build.gradle
settings.gradle
The following line is added into MyApp/settings.gradle:
include ':main', '..:MyLibrary'
The following is added into MyApp/main/build.gradle:
dependencies {
compile project(':..:MyLibrary')
}
The result is the following error:
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':main'.
> Configuration with name 'default' not found.
As a side note, the library project MyLibrary itself can compile without error. The problem seems to be settings.gradle not being able to recognize the library project structure.
(as of version 2.1+):
Below are the steps that I took to share library source outside of the project directory. Instead of plain Java library, my code is compiled as Android module, but that library module is not contained inside the main project. It is fine with me as long as there are no code duplications and I only need to maintain one set of library code for all projects:
File->new Project. Give a name to your library project (here I use LibraryProject). Continue the remaining steps to create a normal project (since this is intended as a library, I chose "add no activity")
By default, Android studio creates the module named as "app" inside the project folder. To prevent names collision with the actual application module, rename the module to something else (Right click "app" module at left panel->Refactor->Rename).
In the build.gradle inside your library module folder, change the top line
apply plugin: 'com.android.application'
to
apply plugin: 'com.android.library'
and then remove the "applicationId" line under "defaultConfig". Also, since this is a library, remove the xlmns:... namespace and <application ..> body from Manifest.xml as well.
That's all for the library part. Now, to create/modify your main application:
If it is a new project, first create new project File->new Project->ApplicationName.
Open settings.gradle (there should only be one such file in every project) and include the following line (note the missing leading semi-colon in library module):
include ':app', '..:LibraryProject:yourLibraryModule'
Then go to File->Project Structure.
Under the tab "Dependencies" click the green "+" button at right. Select "Module dependency". Choose your library module, then click OK.
You should now be able to use the library classes in your application.
ALTERNATIVE METHOD
If, for some reason, there are still problems with the above method, you can try the following (suggested in [here][1]):
Repeat steps 1 to 4 above. By default the main and external (library) project look something like this:
/MainProject
+ build.gradle
+ settings.gradle
+ app/
+ build.gradle
+ src/
/LibraryProject
+ build.gradle
+ settings.gradle
+ app/
+ build.gradle
+ src/
As usual, refactor the modules name (in android studio right-click module->refactor->rename) to something less confusing, such as
/MainProject
+ build.gradle
+ settings.gradle
+ MainModule/
+ build.gradle
+ src/
/LibraryProject
+ build.gradle
+ settings.gradle
+ LibraryModule/
+ build.gradle
+ src/
Modify the settings.gradle in MainProject:
include ':LibraryModule', ':app'
project(':LibraryModule').projectDir = new File(settingsDir, '../LibraryProject/LibraryModule')
Sync the project and you're done.
Note on Proguard
Currently you should not use a proguard on external library projects/modules. Instead, you replace the following (original answer [here][2])
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
debug {
minifyEnabled false
}
}
with the following (in build.gradle of the library):
buildTypes {
release {
consumerProguardFiles 'proguard-project.txt'
}
}
where proguard-project.txt is the file that contains the proguard rules for your library project.
[1]: https://stackoverflow.com/a/17490233/1919013
[2]: https://stackoverflow.com/a/31031491
Yes, it works now in 0.5.0. There isn't a friendly UI to it (Import Project isn't what you want, as that creates an entirely new project; Import Module is still broken; see https://code.google.com/p/android/issues/detail?id=62122), but you can set up your build files to make it work.
Let's say you have a directory structure that looks like this:
MyApp
appmodule
build.gradle
src
main
java
build.gradle
settings.gradle
MyPlainJavaLibrary
build.gradle
src
java
Note that MyPlainJavaLibrary isn't underneath the MyApp directory in the filesystem.
Set up your settings.gradle file like so:
include ':appmodule', '..:MyPlainJavaLibrary'
and include a dependency to it in build.gradle like this (don't forget the leading colon):
dependencies {
...
compile project(':..:MyPlainJavaLibrary')
}
This works for me. In my Project viewer, I now see MyApp and MyPlainJavaLibrary as two root-level module directories in the view, and I can make java import statements work across module boundaries and such.
Note that in this default setup, this shared module will only have a single build output folder that will be shared among all the projects using it. This may or may not be what you want. If you'd like to have a different output directory for each project using the shared module, you can probably do some magic with the output directory in the sourceSet; if you want help with this, I'd recommend trying it out on your own and posting a question with details on your work if you get stuck.
You can only have one settings.gradle file per project, so this isn't going to take a whole other multimodule Gradle project and bring in all the modules in one fell swoop; you'll need to bring them in individually. However, it should satisfy the use case of using a module in multiple projects.
I wanted to do something similar for my Android Wear project, where you have mobile and wear modules. In Android Studio 1.5.1, you can do File->New->Module and pick Android Library as your module. This will take care of many of the settings described above and put your library inside your existing Android Wear project.
To make full use of Android Studio, I would recommend initially creating a normal android project. Then, within that project, add a Module "android library" type, and (optionally) a "java library" (if you have code you want to use that may be common to Android applications and to server side code).
Using this mechanism, you do not need to manipulate and modify gradle and manifest files.
I also wanted to use the same collection of classes across projects, I found an easier way.
Put the class files you want to use in their own folder outside all of your project folders.
Make a symlink(linux) or shortcut(win) to this folder and copy it to:
~/src/main/java/com/yourco/yourproject/
in each of your project folders.
You now have a package of all your commonly used classes synced on all your projects. You're welcome.
You are able to use module(as a shared source code base)apply plugin: 'com.android.library' in the project.
[Project vs Module]
When using Unity3d, "native" (pure-java) Android functionality can be accessed via Plugin. As described in the documentation,
There are several ways to create a Java plugin but the result in each case is that you end up with a .jar file containing the .class files for your plugin
When I create an Android Application Project in eclipse, and set it is a library, it automatically generates a .jar file in the bin folder. I understand that this is a temporary file in the context of the Android toolchain, but this is the file that Unity needs in order to see the classes and build up it's own internal JNI magic. (The entire process is outlined very well here in case more clarity is needed on that process.)
Unfortunately, as near as I can tell, Android Studio does not generate this file. Is there a way I can tell it to give me this file, or perhaps some other way to generate code that Unity will be able to use?
With Unity 5.3+ you no longer need to build a .jar, instead you can use the .aar file that is automatically created by an Android Studio Android Library module. I found this a lot easier than getting the jar method to work:
In your Android Studio project, create an Android Library module: File > New > New Module > Android Library
make sure your minSdkVersion and targetSdkVersion match your Unity project setup
Add your classes etc to the module and build
A successful build should create a .aar file in build/outputs/aar/ e.g. my module creates mkunityplugin-release.aar
Open your Unity project, then drag the .aar file directly onto Assets/Plugins/Android in your Project view. This creates an asset which you can view in the inspector; it will show info on the plugin and the Android platform should be checked
Build your Unity project for Android. My first attempt failed because I had a different targetSdkVersion so I got a build error saying the manifests could not be merged; I fixed that in my Android Studio build.gradle and then it worked
This is where I first heard that .aar could be used directly https://www.reddit.com/r/Unity3D/comments/3eltjz/how_to_add_an_android_library_project_folder_to/
Yes, you can use Android Studio to generate your jars from a Library.
In my case the jar file was located very well hidden in the app build folder, under
<ProjectRootDir>/<AppModuleName>/build/exploded-aar/<ProjectName>/<LibraryModuleName>/unspecified/classes.jar
My example setup for this:
A app module containing nothing but a minimal Android App (Including a MainActivity)
A library module that contains the library code
Add a dependency from your app to your library e.g. add: compile project(':library')
If you build your app now it will also build the library and your apps build folder will contain the jar file under the location I explained above (in my case: PROJECT_ROOT/app/build/exploded-aar/SampleLibrary/library/unspecified/classes.jar).
You can create a jar file using Android Studio.
Just add these tasks in your app's build.gradle file.
//task to delete the old jar
task deleteOldJar(type: Delete) {
delete 'build/libs/AndroidPlugin.jar'
}
//task to export contents as jar
task exportJar(type: Copy) {
from('build/intermediates/bundles/release/')
into('release/')
include('classes.jar')
///Give whatever name you want to give
rename('classes.jar', 'AndroidPlugin.jar')
}
exportJar.dependsOn(deleteOldJar, build)
Once you add the above lines you can export the jar using the task of the same name.
You can go through this post on TGC here on how to create an Android Plugin For Unity using Android Studio
Simple way:
Create new Android Studio Project
File > New > New Module and select Android Library
Copy <UnityPath>\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar to <project path>\<Android Library Module name>\compileOnly (create this folder before)
Add this jar as Library
Open this Module Settings
Set Compile Only
Build > Make Module <Android Library Module name>
Result
Jar-path: <project path>\<Android Library Module name>\build\intermediates\intermediate-jars\debug\classes.jar
Aar-path: <project path>\<Android Library Module name>\build\outputs\aar
Change apply plugin: 'com.android.application' to apply plugin: 'com.android.library'. In the build.gradle under app.
I'm not really sure about Android Studio but in ADT I use the export functionality by right-clicking on the project. With this you can create your .jar and place it wherever you want. Unity needs it to be on a specific folder to see it when running on a device (unfortunately I don't remember it well, but it should be something like Assets/Plugins/Android).