Collegare Gradle alla libreria nativa

Per includere il progetto della libreria nativa come dipendenza build Gradle, devi disporre per fornire a Gradle il percorso del file di script CMake o ndk-build. Quando crei la tua app, Gradle esegue CMake o ndk-build e i pacchetti librerie con la tua app. Gradle usa anche lo script di build per sapere quali file per eseguire il pull del tuo progetto Android Studio, in modo da potervi accedere dal Finestra Progetto. Se non hai uno script di build per il tuo devi creare un nuovo Crea lo script di build prima di proseguire.

Ogni modulo nel tuo progetto Android può collegarsi a un solo CMake o ndk-build del file di script. Ad esempio, se vuoi creare e pacchettizzare output più progetti CMake, devi usare un solo file CMakeLists.txt come script di build CMake di primo livello (da collegare poi a Gradle) e aggiungi altri progetti CMake come le dipendenze dello script di build. Analogamente, se utilizzi ndk-build, può includere altri Makefile nella cartella di primo livello Android.mk.

Una volta collegato Gradle a un progetto nativo, Android Studio aggiorna Riquadro Progetto in cui vengono mostrati i file di origine e le librerie native nel gruppo cpp e i tuoi script di build esterni nel Gruppo File di build esterni.

Nota:quando apporti modifiche alla configurazione di Gradle, assicurati di applica le modifiche facendo clic su Sincronizza progetto nella barra degli strumenti. Inoltre, quando apporti modifiche a CMake o ndk-build di script dopo averlo collegato a Gradle, devi sincronizzare Android Studio con le tue modifiche selezionando Crea > Aggiorna C++ collegato Progetti dalla barra dei menu.

Puoi collegare Gradle a un progetto CMake o ndk-build esterno utilizzando Interfaccia utente di Android Studio:

  1. Apri il riquadro Progetto dal lato sinistro dell'IDE e per selezionare la visualizzazione Android.
  2. Fai clic con il tasto destro del mouse sul modulo che vuoi collegare alla tua libreria nativa, Ad esempio, il modulo app e seleziona Collega progetto C++ con Gradle dal menu. Dovresti vedere una finestra di dialogo simile alla quella mostrata nella figura 4.
  3. Dal menu a discesa, seleziona CMake o ndk-build.
    1. Se selezioni CMake, utilizza il campo accanto a Percorso progetto per specificare lo script CMakeLists.txt per il tuo progetto CMake esterno.
    2. Se selezioni ndk-build, utilizza il campo accanto a Percorso progetto per specificare il file di script Android.mk per del tuo progetto ndk-build esterno. Android Studio include anche Application.mk file se si trova nella stessa directory del Android.mk file.

    Figura 4. Collegamento di un progetto C++ esterno utilizzando Finestra di dialogo di Android Studio.

  4. Fai clic su OK.

Configura manualmente Gradle

Per configurare manualmente Gradle in modo che si colleghi alla tua libreria nativa, devi aggiungere externalNativeBuild a livello di modulo build.gradle e configuralo con il cmake o Blocco ndkBuild:

Alla moda

android {
  ...
  defaultConfig {...}
  buildTypes {...}

  // Encapsulates your external native build configurations.
  externalNativeBuild {

    // Encapsulates your CMake build configurations.
    cmake {

      // Provides a relative path to your CMake build script.
      path "CMakeLists.txt"
    }
  }
}

Kotlin

android {
  ...
  defaultConfig {...}
  buildTypes {...}

  // Encapsulates your external native build configurations.
  externalNativeBuild {

    // Encapsulates your CMake build configurations.
    cmake {

      // Provides a relative path to your CMake build script.
      path = file("CMakeLists.txt")
    }
  }
}

Nota:se vuoi collegare Gradle a una build ndk-build esistente progetto, utilizza la ndkBuild al posto del blocco cmake e fornisci un percorso relativo al tuo file Android.mk. Inoltre, Gradle include il file Application.mk, se presente si trova nella stessa directory del file Android.mk.

Specifica le configurazioni facoltative

Puoi specificare argomenti e flag facoltativi per CMake o ndk-build configurando un altro externalNativeBuild all'interno della defaultConfig blocco a livello di modulo build.gradle. Simile ad altre strutture in blocco defaultConfig, puoi eseguire l'override di queste proprietà per nella configurazione della build.

Ad esempio, se il tuo progetto CMake o ndk-build definisce più modelli ed eseguibili, puoi utilizzare lo targets per creare e pacchettizzare solo un sottoinsieme di queste elementi per una determinata varietà di prodotto. Il seguente esempio di codice descrive alcune delle proprietà che puoi configurare:

Alla moda

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {

      // For ndk-build, instead use the ndkBuild block.
      cmake {

        // Passes optional arguments to CMake.
        arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"

        // Sets a flag to enable format macro constants for the C compiler.
        cFlags "-D__STDC_FORMAT_MACROS"

        // Sets optional flags for the C++ compiler.
        cppFlags "-fexceptions", "-frtti"
      }
    }
  }

  buildTypes {...}

  productFlavors {
    ...
    demo {
      ...
      externalNativeBuild {
        cmake {
          ...
          // Specifies which native libraries or executables to build and package
          // for this product flavor. The following tells Gradle to build only the
          // "native-lib-demo" and "my-executible-demo" outputs from the linked
          // CMake project. If you don't configure this property, Gradle builds all
          // executables and shared object libraries that you define in your CMake
          // (or ndk-build) project. However, by default, Gradle packages only the
          // shared libraries in your app.
          targets "native-lib-demo",
                  // You need to specify this executable and its sources in your CMakeLists.txt
                  // using the add_executable() command. However, building executables from your
                  // native sources is optional, and building native libraries to package into
                  // your app satisfies most project requirements.
                  "my-executible-demo"
        }
      }
    }

    paid {
      ...
      externalNativeBuild {
        cmake {
          ...
          targets "native-lib-paid",
                  "my-executible-paid"
        }
      }
    }
  }

  // Use this block to link Gradle to your CMake or ndk-build script.
  externalNativeBuild {
    cmake {...}
    // or ndkBuild {...}
  }
}

Kotlin

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {

      // For ndk-build, instead use the ndkBuild block.
      cmake {

        // Passes optional arguments to CMake.
        arguments += listOf("-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang")

        // Sets a flag to enable format macro constants for the C compiler.
        cFlags += listOf("-D__STDC_FORMAT_MACROS")

        // Sets optional flags for the C++ compiler.
        cppFlags += listOf("-fexceptions", "-frtti")
      }
    }
  }

  buildTypes {...}

  productFlavors {
    ...
    create("demo") {
      ...
      externalNativeBuild {
        cmake {
          ...
          // Specifies which native libraries or executables to build and package
          // for this product flavor. The following tells Gradle to build only the
          // "native-lib-demo" and "my-executible-demo" outputs from the linked
          // CMake project. If you don't configure this property, Gradle builds all
          // executables and shared object libraries that you define in your CMake
          // (or ndk-build) project. However, by default, Gradle packages only the
          // shared libraries in your app.
          targets += listOf("native-lib-demo",
                  // You need to specify this executable and its sources in your CMakeLists.txt
                  // using the add_executable() command. However, building executables from your
                  // native sources is optional, and building native libraries to package into
                  // your app satisfies most project requirements.
                  "my-executible-demo")
        }
      }
    }

    create("paid") {
      ...
      externalNativeBuild {
        cmake {
          ...
          targets += listOf("native-lib-paid",
                  "my-executible-paid")
        }
      }
    }
  }

  // Use this block to link Gradle to your CMake or ndk-build script.
  externalNativeBuild {
    cmake {...}
    // or ndkBuild {...}
  }
}

Per scoprire di più sulla configurazione delle versioni di prodotto e sulla creazione delle varianti, vai a Configura le varianti della build. Per un elenco di variabili che puoi configurare per CMake arguments, consulta Utilizzare le variabili CMake.

Includi librerie native predefinite

Se vuoi che Gradle pacchettizzi librerie native predefinite che non vengono utilizzate in nessuna build nativa esterna, aggiungili a src/main/jniLibs/ABI del tuo modulo.

Sono necessarie versioni del plug-in Android Gradle precedenti alla 4.0, incluso CMake IMPORTED target nella directory jniLibs da includere nel tuo dell'app. Se stai eseguendo la migrazione da una versione precedente del plug-in, puoi: si verifica un errore come il seguente:

* What went wrong:
Execution failed for task ':app:mergeDebugNativeLibs'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > More than one file was found with OS independent path 'lib/x86/libprebuilt.so'

Se utilizzi il plug-in Android Gradle 4.0, sposta le librerie utilizzate IMPORTED Crea destinazioni all'esterno della directory jniLibs per evitare questo errore.

Specifica le ABI

Per impostazione predefinita, Gradle crea la tua raccolta nativa in .so per le interfacce Application Binary Interfaces (ABI) supportate da NDK e pacchettizzarle tutte nella tua app. Se vuoi Gradle per creare e pacchettizzare solo determinate configurazioni ABI del tuo asset nativo librerie, puoi specificarle con ndk.abiFilters nel file build.gradle a livello di modulo, come mostrato di seguito:

Alla moda

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {...}
      // or ndkBuild {...}
    }

    // Similar to other properties in the defaultConfig block,
    // you can configure the ndk block for each product flavor
    // in your build configuration.
    ndk {
      // Specifies the ABI configurations of your native
      // libraries Gradle should build and package with your app.
      abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
                   'arm64-v8a'
    }
  }
  buildTypes {...}
  externalNativeBuild {...}
}

Kotlin

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {...}
      // or ndkBuild {...}
    }

    // Similar to other properties in the defaultConfig block,
    // you can configure the ndk block for each product flavor
    // in your build configuration.
    ndk {
      // Specifies the ABI configurations of your native
      // libraries Gradle should build and package with your app.
      abiFilters += listOf("x86", "x86_64", "armeabi", "armeabi-v7a",
                   "arm64-v8a")
    }
  }
  buildTypes {...}
  externalNativeBuild {...}
}

Nella maggior parte dei casi, devi solo specificare abiFilters nel ndk, come mostrato sopra, perché indica a Gradle di creare e pacchettizzare le versioni delle tue librerie native. Tuttavia, se vuoi controllare ciò che Gradle dovrebbe creare, indipendentemente da ciò che vuoi nella tua app, configura un altro flag abiFilters nella defaultConfig.externalNativeBuild.cmake (o defaultConfig.externalNativeBuild.ndkBuild). Gradle crea queste configurazioni ABI, ma pacchettizza solo quelle specificate Blocco defaultConfig.ndk.

Ti consigliamo di pubblicare utilizzando Android App Bundle per ridurre ulteriormente le dell'app, poiché solo le librerie native corrispondenti all'ABI del dispositivo verrà consegnato con il download.

Per la pubblicazione di app precedenti tramite APK (create prima di agosto 2021), prendi in considerazione l'utilizzo di configurazione diversi APK basati su ABI, anziché creare un unico APK di grandi dimensioni con delle tue librerie native, Gradle crea un APK separato per ogni ABI che vuoi supportare e pacchettizza solo i file di cui ogni ABI ha bisogno. Se configurare più APK per ABI senza specificare Flag abiFilters come mostrato nell'esempio di codice in alto, build di Gradle tutte le versioni ABI supportate delle tue librerie native, ma pacchettizza solo quelle che hai specificato nella configurazione di più APK. Per evitare di creare versioni le librerie native che non vuoi, fornisci lo stesso elenco di ABI per sia il flag abiFilters sia l'APK multiplo per ABI configurazione.