¿Cómo construir una biblioteca de Android con Android Studio y gradle?

144

Estoy tratando de migrar un proyecto desde Eclipse, pero nada de lo que he intentado funciona. En Eclipse tengo 3 proyectos (2 proyectos de aplicaciones de Android y 1 proyecto de biblioteca de Android). Los 2 proyectos de la aplicación dependen del proyecto de la biblioteca. Cuando hago la exportación de Gradle obtengo 3 proyectos que no funcionan. Estoy abierto a reestructurar el proyecto, pero no he encontrado ninguna documentación sobre cómo debería hacerse.

¿Hay alguna manera de hacer que los 3 proyectos que Eclipse exporta trabajen juntos? ¿Estoy mejor reestructurando las cosas y, si es así, hay documentación sobre cómo debería hacerse?

Actualizar

He subido todo el proyecto a GitHub https://github.com/respectTheCode/android-studio-library-example

Actualización 1

Basado en las sugerencias de Padma Kumar, esto es lo que he intentado.

  1. Crea un nuevo proyecto llamado MyApp
  2. Haga clic File > New Module, elija Android Libraryy nómbreloMyLib
  3. Hacer clic Build > Make Project

La compilación falla con este 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.

Luego agregué un packageatributo al manifiesto haciéndolo

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

Después de construir me sale este 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

Agregar dependencia no parece tener ningún impacto en el error. Continuando desde arriba

  1. Hacer clic File > Project Structure > Modules > MyApp-MyApp
  2. Cambiar a Dependenciespestaña
  3. Haga clic + > Module Dependencyy escojaMyLib
  4. Haga clic ApplyyOK
  5. Hacer clic Build > Make Project

Actualización 2

Basado en las sugerencias de Ethan, aquí es donde obtenemos

El subproyecto 2 build.gradleparece tener todas las partes correctas y la única diferencia es que la línea de complemento que se encuentra debajo es 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
    }
}

El proyecto raíz build.gradleestaba vacío, así que agregué dos proyectos como este

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

Ahora recibo este error al construir

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.

Actualización 3

Muchas gracias Ethan por resolver esto.

  1. Añadir compile project(':SubProjects:MyLib')a laMyLib/build.gradle
  2. Eliminar compile files('libs/android-support-v4.jar')de laMyLib/build.gradle
  3. Cierre el proyecto e importe el proyecto raíz desde gradle

Actualización 4

A partir de 0.1.2 ahora puede incluir en compile "com.android.support:support-v4:13.0.0"lugar de compile files('libs/android-support-v4.jar'). Dado que ahora proviene de mavin, puede incluir esto en múltiples proyectos sin problemas.

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')
}

Actualización 5

A partir de la 0.1.3 ahora hay un botón "Sincronizar proyecto" en la barra de herramientas. Puede hacer clic en eso en lugar de volver a importar su proyecto después de realizar cambios en los .gradlearchivos.

respectTheCode
fuente
Hice una solicitud de extracción para su proyecto github. Hubo 2 cambios simples. Elimina el contenido de tu /build.gradle. {Hice esto porque no definiste qué tipo de proyecto era, por lo que se quejaba de no saber qué hacer con él}, luego agregué la dependencia de: SubProject: MyLib a: SubProject: MyApp. Luego ejecuté ./gradlew: SubProject: MyApp: iD (iD se asigna a installDebug). También tuve que eliminar el duplicado libs / android-support-v4.jar. Como no es una dependencia 'real', no puede tenerla en dos lugares.
Ethan
Comenté sobre la solicitud de extracción. github.com/respectTheCode/android-studio-library-example/pull/1
respectTheCode
1
Vale la pena mencionar que si agrega compile 'com.google.android:support-v4:r6'a cada uno de sus proyectos y al complemento Maven (como en el ejemplo build.gradle a continuación) en lugar de la compile files('libs/android-support-v4.jar')gradle, se dará cuenta de que ambos proyectos incluyen lo mismo y solo lo incluirán una vez.
Ethan
@respectTheCode Envié una solicitud de extracción para limpiar un poco su proyecto github de muestra. ¡Gracias por compartir!
JohnnyLambada
Posible duplicado de Android studio, gradle y NDK
Cameron Lowell Palmer

Respuestas:

115

Nota : Esta respuesta es una respuesta pura de Gradle, la uso en IntelliJ regularmente, pero no sé cómo es la integración con Android Studio. Creo en saber lo que me está sucediendo, así que así es como uso Gradle y Android.

TL; DR Ejemplo completo: https://github.com/ethankhall/driving-time-tracker/

Descargo de responsabilidad : Este es un proyecto en el que estoy / estaba trabajando.

Gradle tiene una estructura definida (que puedes cambiar, el enlace en la parte inferior te dice cómo) que es muy similar a Maven si alguna vez la has usado.

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

Si solo tiene un proyecto, el archivo settings.gradle no es necesario. Sin embargo, si desea agregar más proyectos, lo necesitamos.

Ahora echemos un vistazo a ese archivo build.gradle. Vas a necesitar esto en él (para agregar las herramientas de Android)

build.gradle

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

Ahora tenemos que decirle a Gradle sobre algunas de las partes de Android. Es muy simple Una básica (que funciona en la mayoría de mis casos) se parece a la siguiente. Tengo un comentario en este bloque, me permitirá especificar el nombre y el código de la versión al generar el APK.

build.gradle

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

Algo que vamos a querer agregar, para ayudar a cualquiera que aún no haya visto la luz de Gradle, una forma de que puedan usar el proyecto sin instalarlo.

build.gradle

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

Así que ahora tenemos un proyecto para construir. Ahora vamos a agregar los otros. Los puse en un directorio, tal vez lo llamo deps, o subproyectos. Realmente no importa, pero necesitará saber dónde lo coloca. Para decirle a Gradle dónde están los proyectos, deberá agregarlos a settings.gradle.

Estructura de directorios:

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'

Lo último que debe asegurarse es el subProjects / reallyCoolProject1 / build.gradle tiene en apply plugin: "android-library"lugar de apply plugin: "android".

Al igual que todos los proyectos de Gradle (y Maven), ahora debemos informar al proyecto raíz sobre su dependencia. Esto también puede incluir las dependencias normales de Java que desee.

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')
}

Sé que esto parece muchos pasos, pero son bastante fáciles una vez que lo haces una o dos veces. De esta manera también le permitirá construir en un servidor CI suponiendo que tenga el SDK de Android instalado allí.

Nota al margen de NDK: si va a utilizar el NDK, necesitará algo como lo que se indica a continuación. El archivo build.gradle de ejemplo se puede encontrar aquí: 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')
}

Fuentes:

  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
fuente
1
Gracias @Ethan esto llena algunos de los espacios en blanco. A Android Studio solo le faltaba el proyecto raíz build.gradle. Actualizaré la pregunta con el error que recibo ahora.
respectTheCode
1
Intenté clonar su repositorio de seguimiento de tiempo de conducción e importar el proyecto, pero no lo compilé.
respectTheCode
Olvidé algo, hice una nueva solicitud
Ethan
1
Hola @ Ethan, parece que tienes experiencia con Gradle, ¿te importaría ayudar con mi problema también: stackoverflow.com/questions/17479076/…
TacB0sS
@ Ethan ¿Puedes ayudar con un problema de dependencia con Gradle para Android por favor?
JJD
6

Acabo de tener problemas muy similares con las construcciones de gradle / agregando la biblioteca .jar. Lo hice funcionar mediante una combinación de:

  1. Mover la carpeta libs hacia la raíz del proyecto (mismo directorio que 'src') y agregar la biblioteca a esta carpeta en el buscador (usando Mac OS X)
  2. En Android Studio, haga clic derecho en la carpeta para agregar como biblioteca
  3. Editando las dependencias en el archivo build.gradle, agregando compile fileTree(dir: 'libs', include: '*.jar')}

PERO lo que es más importante y molesto, solo unas horas después de que lo puse a funcionar, Android Studio acaba de lanzar 0.3.7, que afirma haber resuelto muchos problemas básicos como agregar bibliotecas .jar

http://tools.android.com/recent

Espero que esto ayude a la gente!

Joel Balmer
fuente
1
Este problema está hablando de las bibliotecas Andriod, no de las bibliotecas Java .jar.
respectTheCode
2
¡Cierto! Sin embargo, mi problema involucraba compilaciones de gradle y estudio de Android y esta publicación fue lo suficientemente similar como para ayudarme a llevarme a mi solución, solo pensé en difundir las buenas noticias en caso de que alguien más fuera llevado a esta pregunta y estuviera en la misma posición yo.
Joel Balmer
1

Aquí está mi solución para usuarios de Mac. Creo que también funciona para Windows:

Primero ve a la barra de herramientas de Android Studio

Build> Make Project (mientras están conectados, dejen que descarguen los archivos) y luego

Build> Compile Module "aquí se muestra el nombre de su aplicación" (todavía en línea, deje que los archivos se
descarguen y finalicen) y luego

Ejecute su aplicación que está hecha, iniciará su emulador y configúrelo, luego ejecútelo.

¡¡¡Eso es!!! Feliz codificación chicos !!!!!!!

Henula
fuente
0

Gradle Build Tools 2.2.0+ - Todo simplemente funciona

Esta es la forma correcta de hacerlo.

Al tratar de evitar la experimentación y, francamente, harto del NDK y todos sus hackers, estoy feliz de que salió 2.2.x de Gradle Build Tools y ahora simplemente funciona. La clave es la externalNativeBuildy señalando ndkBuildargumento de ruta a una Android.mko cambio ndkBuilda cmakey punto el argumento de ruta a un CMakeLists.txtscript de construcción.

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'
        //}
    }
}

Para obtener más detalles, consulte la página de Google sobre cómo agregar código nativo .

Después de que esto esté configurado correctamente, puede ./gradlew installDebugy listo. También deberá tener en cuenta que el NDK se está moviendo a clang ya que gcc ahora está en desuso en el NDK de Android.

Cameron Lowell Palmer
fuente