145

I am trying to migrate a project from Eclipse but nothing I have tried is working. In Eclipse I have 3 projects (2 android app projects and 1 android library project). The 2 app projects depend on the library project. When I do the gradle export I get 3 projects that don't work. I am open to restructuring the project but haven't found any documentation on how this should be done.

Is there a way to make the 3 projects that Eclipse exports work together? Am I better off restructuring things and if so is documentation for how this should be done?

Update

I have uploaded the entire project to GitHub https://github.com/respectTheCode/android-studio-library-example

Update 1

Based the suggestions from Padma Kumar this is what I have tried.

  1. Create a new Project called MyApp
  2. Click File > New Module, choose Android Library and name it MyLib
  3. Click Build > Make Project

The build fails with this error

Module "MyLib" was fully rebuilt due to project configuration/dependencies changes
Compilation completed with 1 error and 0 warnings in 19 sec
1 error
0 warnings
/.../MyApp/MyLib/build/bundles/debug/AndroidManifest.xml
Gradle: <manifest> does not have package attribute.

I then added a package attribute to the manifest making it

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.mylib" >

After building I get this error

Module "MyApp" was fully rebuilt due to project configuration/dependencies changes
Compilation completed with 2 errors and 0 warnings in 13 sec
2 errors
0 warnings
/.../MyApp/MyLib/src/main/java/com/example/mylib/MainActivity.java
Gradle: package R does not exist
Gradle: package R does not exist

Adding dependency doesn't seem to have any impact on the error. Continuing from above

  1. Click File > Project Structure > Modules > MyApp-MyApp
  2. Switch to Dependencies Tab
  3. Click + > Module Dependency and pick MyLib
  4. Click Apply and OK
  5. Click Build > Make Project

Update 2

Based the suggestions from Ethan this is where we get

The 2 sub project build.gradle seem to have all of the correct parts and the only difference is the plugin line bellow is the MyApp/build.gradle.

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
apply plugin: 'android'

dependencies {
    compile files('libs/android-support-v4.jar')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 16
    }
}

The root project build.gradle was empty so I added the two projects like this

dependencies {
    compile project(":MyLib")
    compile project(":MyApp")
}

I now get this error when building

Gradle:
FAILURE: Build failed with an exception.
* Where:
Build file '/Users/kevin/GitHub/AppPress/MyApp/build.gradle' line: 2
* What went wrong:
A problem occurred evaluating root project 'MyApp'.
> Could not find method compile() for arguments [project ':MyLib'] on root project 'MyApp'.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

Update 3

Big thanks Ethan for solving this.

  1. Add compile project(':SubProjects:MyLib') to the MyLib/build.gradle
  2. Remove compile files('libs/android-support-v4.jar') from the MyLib/build.gradle
  3. Close project and Import the root project from gradle

Update 4

As of 0.1.2 you can now include compile "com.android.support:support-v4:13.0.0" instead of compile files('libs/android-support-v4.jar'). Since it is coming from mavin now you can include this in multiple projects without problems.

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.4.2'
    }
}

apply plugin: 'android'

dependencies {
    compile "com.android.support:support-v4:13.0.0"

    compile project(':SubProjects:MyLib')
}

Update 5

As of 0.1.3 there is now a "Sync Project" button in the toolbar. You can click that instead of reimporting your project after making changes to .gradle files.

respectTheCode
  • 42,348
  • 18
  • 73
  • 86
  • I made a pull request for your github project. There were 2 simple changes. Remove the content from your /build.gradle. { I did this because you didn't define what kind of project it was, so it was complaining about not knowing what to to with it }, then I added the dependency from :SubProject:MyLib to :SubProject:MyApp. I then ran ./gradlew :SubProject:MyApp:iD (iD maps to installDebug). I also had to remove the duplicate libs/android-support-v4.jar. Since it's not a 'real' dependency, you can't have it in two places. – Ethan May 23 '13 at 19:25
  • I commented on the pull request. https://github.com/respectTheCode/android-studio-library-example/pull/1 – respectTheCode May 23 '13 at 21:02
  • 1
    It's worth mentioning, if you add `compile 'com.google.android:support-v4:r6'` to each of your projects and the maven plugin (like in the build.gradle example below) instead of the `compile files('libs/android-support-v4.jar')` gradle will realize that both projects include the same thing and will only include it once. – Ethan May 24 '13 at 15:56
  • @respectTheCode I sent a pull request to clean up your sample github project a bit. Thanks for sharing! – JohnnyLambada Apr 05 '14 at 00:35
  • Possible duplicate of [Android studio, gradle and NDK](http://stackoverflow.com/questions/16667903/android-studio-gradle-and-ndk) – Cameron Lowell Palmer Feb 23 '17 at 08:53

4 Answers4

117

Note: This answer is a pure Gradle answer, I use this in IntelliJ on a regular basis but I don't know how the integration is with Android Studio. I am a believer in knowing what is going on for me, so this is how I use Gradle and Android.

TL;DR Full Example - https://github.com/ethankhall/driving-time-tracker/

Disclaimer: This is a project I am/was working on.

Gradle has a defined structure ( that you can change, link at the bottom tells you how ) that is very similar to Maven if you have ever used it.

Project Root
+-- src
|   +-- main (your project)
|   |   +-- java (where your java code goes)
|   |   +-- res  (where your res go)
|   |   +-- assets (where your assets go)
|   |   \-- AndroidManifest.xml
|   \-- instrumentTest (test project)
|       \-- java (where your java code goes)
+-- build.gradle
\-- settings.gradle

If you only have the one project, the settings.gradle file isn't needed. However you want to add more projects, so we need it.

Now let's take a peek at that build.gradle file. You are going to need this in it (to add the android tools)

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.3'
    }
}

Now we need to tell Gradle about some of the Android parts. It's pretty simple. A basic one (that works in most of my cases) looks like the following. I have a comment in this block, it will allow me to specify the version name and code when generating the APK.

build.gradle

apply plugin: "android"
android {
        compileSdkVersion 17
        /*
        defaultConfig {
            versionCode = 1
            versionName = "0.0.0"
        }
        */
    }

Something we are going to want to add, to help out anyone that hasn't seen the light of Gradle yet, a way for them to use the project without installing it.

build.gradle

task wrapper(type: org.gradle.api.tasks.wrapper.Wrapper) {
    gradleVersion = '1.4'
}

So now we have one project to build. Now we are going to add the others. I put them in a directory, maybe call it deps, or subProjects. It doesn't really matter, but you will need to know where you put it. To tell Gradle where the projects are you are going to need to add them to the settings.gradle.

Directory Structure:

Project Root
+-- src (see above)
+-- subProjects (where projects are held)
|   +-- reallyCoolProject1 (your first included project)
|       \-- See project structure for a normal app
|   \-- reallyCoolProject2 (your second included project)
|       \-- See project structure for a normal app
+-- build.gradle
\-- settings.gradle

settings.gradle:

include ':subProjects:reallyCoolProject1'
include ':subProjects:reallyCoolProject2'

The last thing you should make sure of is the subProjects/reallyCoolProject1/build.gradle has apply plugin: "android-library" instead of apply plugin: "android".

Like every Gradle project (and Maven) we now need to tell the root project about it's dependency. This can also include any normal Java dependencies that you want.

build.gradle

dependencies{
    compile 'com.fasterxml.jackson.core:jackson-core:2.1.4'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.1.4'
    compile project(":subProjects:reallyCoolProject1")
    compile project(':subProjects:reallyCoolProject2')
}

I know this seems like a lot of steps, but they are pretty easy once you do it once or twice. This way will also allow you to build on a CI server assuming you have the Android SDK installed there.

NDK Side Note: If you are going to use the NDK you are going to need something like below. Example build.gradle file can be found here: https://gist.github.com/khernyo/4226923

build.gradle

task copyNativeLibs(type: Copy) {
    from fileTree(dir: 'libs', include: '**/*.so' )  into  'build/native-libs'
}
tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'

tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
  pkgTask.jniDir new File('build/native-libs')
}

Sources:

  1. http://tools.android.com/tech-docs/new-build-system/user-guide
  2. https://gist.github.com/khernyo/4226923
  3. https://github.com/ethankhall/driving-time-tracker/
Ethan
  • 6,883
  • 3
  • 33
  • 41
  • 1
    Thanks @Ethan this does fill in some of the blanks. Android Studio was only missing the root project build.gradle. I wil update the question with the error I am getting now. – respectTheCode May 23 '13 at 18:32
  • 1
    I tried cloning your driving time tracker repo and importing the project but is wouldn't compile. – respectTheCode May 23 '13 at 19:19
  • I forgot something, I made a new request – Ethan May 23 '13 at 19:26
  • 1
    Hi @Ethan, it seems that you are experienced with Gradle, would you mind assisting with my issue as well: http://stackoverflow.com/questions/17479076/android-studio-add-external-project-to-buildpath – TacB0sS Jul 04 '13 at 23:48
  • @Ethan Can you help with a [dependency problem](http://stackoverflow.com/questions/19245855/noclassdeffounderror-using-jackson-2-2-x-on-android-with-gradle) with Gradle for Android please? – JJD Oct 08 '13 at 14:54
8

I just had a very similar issues with gradle builds / adding .jar library. I got it working by a combination of :

  1. Moving the libs folder up to the root of the project (same directory as 'src'), and adding the library to this folder in finder (using Mac OS X)
  2. In Android Studio, Right-clicking on the folder to add as library
  3. Editing the dependencies in the build.gradle file, adding compile fileTree(dir: 'libs', include: '*.jar')}

BUT more importantly and annoyingly, only hours after I get it working, Android Studio have just released 0.3.7, which claims to have solved a lot of gradle issues such as adding .jar libraries

http://tools.android.com/recent

Hope this helps people!

Joel Balmer
  • 1,428
  • 2
  • 19
  • 21
  • 1
    This issue is talking about Andriod Libraries not Java .jar libraries. – respectTheCode Dec 04 '13 at 17:13
  • 2
    True! However, my problem did involving gradle builds and android studio and this post was similar enough to have helped lead me towards my solution - just thought I'd spread the good news incase anyone else was led to this question, and was in the same position me. – Joel Balmer Dec 04 '13 at 17:21
3

Here is my solution for mac users I think it work for window also:

First go to your Android Studio toolbar

Build > Make Project (while you guys are online let it to download the files) and then

Build > Compile Module "your app name is shown here" (still online let the files are
download and finish) and then

Run your app that is done it will launch your emulator and configure it then run it!

That is it!!! Happy Coding guys!!!!!!!

Henula
  • 47
  • 2
1

Gradle Build Tools 2.2.0+ - Everything just works

This is the correct way to do it

In trying to avoid experimental and frankly fed up with the NDK and all its hackery I am happy that 2.2.x of the Gradle Build Tools came out and now it just works. The key is the externalNativeBuild and pointing ndkBuild path argument at an Android.mk or change ndkBuild to cmake and point the path argument at a CMakeLists.txt build script.

android {
    compileSdkVersion 19
    buildToolsVersion "25.0.2"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 19

        ndk {
            abiFilters 'armeabi', 'armeabi-v7a', 'x86'
        }

        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11'
                arguments '-DANDROID_TOOLCHAIN=clang',
                        '-DANDROID_PLATFORM=android-19',
                        '-DANDROID_STL=gnustl_static',
                        '-DANDROID_ARM_NEON=TRUE',
                        '-DANDROID_CPP_FEATURES=exceptions rtti'
            }
        }
    }

    externalNativeBuild {
        cmake {
             path 'src/main/jni/CMakeLists.txt'
        }
        //ndkBuild {
        //   path 'src/main/jni/Android.mk'
        //}
    }
}

For much more detail check Google's page on adding native code.

After this is setup correctly you can ./gradlew installDebug and off you go. You will also need to be aware that the NDK is moving to clang since gcc is now deprecated in the Android NDK.

Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126