68

In Eclipse I can add a source folder to my Android project as a "linked source folder". How do I achieve the same thing in Android Studio?

Or is it possible to add an external folder to build in Gradle?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Erik Z
  • 4,660
  • 6
  • 47
  • 74

7 Answers7

108

In your build.gradle file, add the following to the end of the Android node:

android {
    ....
    ....

    sourceSets {
        main.java.srcDirs += 'src/main/<YOUR DIRECTORY>'
    }

}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
fabrizotus
  • 2,958
  • 2
  • 21
  • 27
  • 1
    Really helpful. Why put `sourceSets` in the scope of `android`? My `dependencies` is out of it. – CopperCash Jun 24 '14 at 07:12
  • 5
    But this solution deals only with the Java files. What about all the resources that under 'src' as well - the drawable, layouts, strings, etc. How to be able to put them in an external folder? – GyRo Feb 09 '15 at 10:20
  • For appengine, sourceSets must be at root level - not nested within. Rather strange that it would be one way for android modules and another way for appengine modules. – Tom Apr 24 '15 at 21:48
  • I take it there's no support for the include/exclude options that Eclipse has. Too bad. – Brian White May 26 '15 at 00:08
  • I don't have android block in my build.gradle. Should I add? – Deckard Jan 13 '16 at 09:11
  • 2
    @Deckard There should be an android block in the build.gradle of the module "app", not in the root build file. – user905686 Jul 25 '16 at 12:04
  • Note that also absolute paths can be used - the directories then appear next to the existing "src" directory in Android Studio, not inside. When symlinking them inside *and* adding them as source dirs, one gets "duplicate class" errors. See also my comment to the symlink answer. – user905686 Jul 25 '16 at 17:50
  • 1
    @GyRo You can do the same for resources files: in sourceSets add the line `main.res.srcDirs += ''` – FlorianT Aug 20 '17 at 16:10
  • I have no idea what an "Anrdriod node" is. Thereore your score now is -1. – Niklas Rosencrantz Nov 26 '17 at 11:58
  • What about native sources? `main.WhatGoesHere.srcDirs += 'src/'` – l33t Jan 25 '23 at 00:44
24

The right answer is:

android {
    ....
    ....

    sourceSets {
        main.java.srcDirs += 'src/main/<YOUR DIRECTORY>'
    }
}

Furthermore, if your external source directory is not under src/main, you could use a relative path like this:

sourceSets {
    main.java.srcDirs += 'src/main/../../../<YOUR DIRECTORY>'
}
Rafa Viotti
  • 9,998
  • 4
  • 42
  • 62
lyfshadyboss
  • 267
  • 3
  • 3
  • Regarding relative paths - I wonder if it is possible to use some sort of gradle variables, eg. srcDirs += "$(ProjectDir)/mylib/src"? I'm new to Gradle and have no idea if it supports anything like this. – Tom Apr 24 '15 at 16:46
  • 5
    You can omit the `src/main/../../` prefix since the dots cancel the path components. – Brian White May 25 '15 at 20:43
  • @BrianWhite how do I specify a source set on another machine? `sourceSets { main.java.srcDirs += 'src/main/\\10.51.70.21\me\myco\apps\myapp\src' }` – likejudo Aug 30 '16 at 02:37
  • I don't expect you can since, as far as I know, it just uses the OS `open()` to access files. You could use something like `nfs` or `smb` to mount remote directories right into the file system but that's not specific to Android Studio. – Brian White Aug 31 '16 at 00:09
  • While this solution works, I found that it will not work if you have a project made up from several modules and more than one module wants to reference the same external source code. It appears that only one module can reference external source files. This is a shame, as I had intended on having a common src folder that I could use to share constants without the need to create a jar or aar file. – Johann Dec 30 '19 at 12:05
  • The relative path usage worked well for me with an external C++ native library, just had to make sure I set the `cmake { } ` path in Gradle to relative also. Thanks. –  Aug 08 '21 at 17:43
2

You can add a source folder to the build script and then sync. Look for sourceSets in the documentation here: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Basic-Project

I haven't found a good way of adding test source folders. I have manually added the source to the .iml file. Of course this means it will go away everytime the build script is synched.

tom
  • 694
  • 4
  • 10
2

While sourceSets allows you to include entire directory structures, there's no way to exclude parts of it in Android Studio (as of version 1.2), as described in Exclude a class from the build in Android Studio.

Until Android Studio gets updated to support include/exclude directives for Android sources, symbolic links work quite well. If you're using Windows, native tools such as junction or mklink can accomplish the equivalent of symbolic links on Unix-like systems. Cygwin can also create these with a little coercion. See: Git symbolic links in Windows and How to make a symbolic link with Cygwin in Windows 7.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Brian White
  • 8,332
  • 2
  • 43
  • 67
  • 5
    Unfortunately, I get the following behaviour in Android Studio 2.1.2 with symlinks: the files are shown next to the project files and with a clean build it works. But every normal build after changes in the symlinked directories gives a gradle error: "Unable to find source java class: '//MyClass.java' because it does not belong to any of the source dirs: [list of src dirs including ".../src/main/java" where in a package folder the symlink resides]". – user905686 Jul 25 '16 at 17:22
  • 4
    @user905686 Yes! Holy cow. It's taken me hours to find somebody else running into this same problem. Like you said, symlinks work on a clean "rebuild" but not on subsequent runs. It's far too time consuming so I've just updated my settings to reference the actual directory instead of symlinking. Kind of a pain but it makes development way faster. – Joshua Pinter Jan 09 '17 at 19:35
  • 1
    I have added bug report https://issuetracker.google.com/issues/65343978, but I'm not sure if it will be accepted as a bug. – Vojtěch Sázel Sep 04 '17 at 14:30
2

Here’s a complete Java module Gradle file that correctly generates and references the built artefacts within an Android multi-module application:

buildscript {
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath "net.ltgt.gradle:gradle-apt-plugin:0.15"
    }
}

apply plugin: "net.ltgt.apt"
apply plugin: "java-library"
apply plugin: "idea"

idea {
    module {
        sourceDirs += file("$buildDir/generated/source/apt/main")
        testSourceDirs += file("$buildDir/generated/source/apt/test")
    }
}

dependencies {

    // Dagger 2 and Compiler
    compile "com.google.dagger:dagger:2.15"
    apt "com.google.dagger:dagger-compiler:2.15"
    compile "com.google.guava:guava:24.1-jre"

}

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hector
  • 4,016
  • 21
  • 112
  • 211
1

This is for Kotlin DSL (build.gradle.kts):

android {
    sourceSets["main"].java.srcDirs("src/main/myDirectory/code/")
    sourceSets["main"].resources.srcDirs("src/main/myDirectory/resources/")

    // Another notation:
    // sourceSets {
    //     getByName("main") {
    //         java.srcDirs("src/main/myDirectory/code/")
    //         resources.srcDirs("src/main/myDirectory/resources/")
    //     }
    // }
}
Mahozad
  • 18,032
  • 13
  • 118
  • 133
  • @PeterMortensen I updated the link. Thanks for pointing that out. Mmm... and forgive me if I have not used the proper article. – Mahozad May 03 '22 at 05:45
0

If you're not using Gradle (creating a project from an APK, for instance), this can be done through the Android Studio UI (as of version 3.3.2):

  • Right-click the project root directory and pick Open Module Settings
  • Hit the + Add Content Root button (center right)
  • Add your path and hit OK

In my experience (with native code), as long as your .so files are built with debug symbols and from the same absolute paths, breakpoints added in source files will be automatically recognized.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jeremy Nikolai
  • 285
  • 2
  • 13