Per includere il tuo progetto di libreria nativa come dipendenza di build Gradle, devi fornire a Gradle il percorso al file di script CMake o ndk-build. Quando crei la tua app, Gradle esegue CMake o ndk-build e pacchettizza le librerie condivise con la tua app. Gradle utilizza anche lo script di build per sapere quali file trasferire nel tuo progetto Android Studio, in modo che tu possa accedervi dalla finestra Progetto. Se non disponi di uno script di build per le origini native, devi creare uno script di build CMake prima di procedere.
Ogni modulo nel tuo progetto Android può essere collegato a un solo file di script CMake o ndk-build. Ad esempio, se vuoi creare e pacchettizzare output da più progetti CMake, devi utilizzare un file CMakeLists.txt
come script di build CMake di primo livello (a cui dovrai poi collegare Gradle) e
aggiungere altri progetti CMake come dipendenze dello script di build. Allo stesso modo, se utilizzi ndk-build, puoi
includere altri makefile nel file di script
Android.mk
di primo livello.
Dopo aver collegato Gradle a un progetto nativo, Android Studio aggiorna il riquadro Progetto per mostrare i file di origine e le librerie native nel gruppo cpp, mentre gli script di build esterni nel gruppo File di build esterni.
Nota: quando apporti modifiche alla configurazione di Gradle, assicurati di applicare le modifiche facendo clic su Sincronizza progetto nella barra degli strumenti. Inoltre, quando apporti modifiche al file di script CMake o ndk-build dopo averlo già collegato a Gradle, devi sincronizzare Android Studio con le modifiche selezionando Crea > Aggiorna progetti C++ collegati dalla barra dei menu.
Utilizzare l'interfaccia utente di Android Studio
Puoi collegare Gradle a un progetto CMake o ndk-build esterno utilizzando l'interfaccia utente di Android Studio:
- Apri il riquadro Progetto sul lato sinistro dell'IDE e seleziona la visualizzazione Android.
- Fai clic con il pulsante 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 visualizzare una finestra di dialogo simile a quella mostrata nella Figura 4.
- Dal menu a discesa, seleziona CMake o
ndk-build.
- Se selezioni CMake, utilizza il campo accanto a
Percorso progetto per specificare il file di script
CMakeLists.txt
per il progetto CMake esterno. - Se selezioni ndk-build, utilizza il campo accanto a Percorso progetto per specificare il file di script
Android.mk
per il progetto ndk-build esterno. Android Studio include anche il fileApplication.mk
se si trova nella stessa directory del fileAndroid.mk
.
- Se selezioni CMake, utilizza il campo accanto a
Percorso progetto per specificare il file di script
- Fai clic su OK.
Configurare manualmente Gradle
Per configurare manualmente Gradle in modo che si colleghi alla tua libreria nativa, devi aggiungere
il blocco
externalNativeBuild
al file build.gradle
a livello di modulo
e configurarlo con il blocco
cmake
o
ndkBuild
:
Trendy
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 un progetto ndk-build esistente, utilizza il blocco
ndkBuild
anziché il blocco
cmake
e fornisci un percorso relativo al file Android.mk
. Gradle include anche il file Application.mk
se si trova nella stessa directory del file Android.mk
.
Specifica configurazioni facoltative
Puoi specificare argomenti e flag facoltativi per CMake o ndk-build
configurando un altro blocco
externalNativeBuild
all'interno del
blocco defaultConfig
del file
build.gradle
a livello di modulo. Analogamente ad altre proprietà nel blocco defaultConfig
, puoi eseguire l'override di queste proprietà per ogni versione di prodotto nella configurazione della build.
Ad esempio, se il tuo progetto CMake o ndk-build definisce più librerie native ed eseguibili, puoi utilizzare la proprietà
targets
per creare e pacchettizzare solo un sottoinsieme di questi
artefatti per una determinata versione di prodotto. Il seguente esempio di codice descrive alcune delle proprietà che puoi configurare:
Trendy
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 delle varianti di build, consulta
Configurare le varianti della build. Per
un elenco delle variabili configurabili per CMake con la
proprietà arguments
, consulta Utilizzo di variabili CMake.
Includi librerie native predefinite
Se vuoi che Gradle pacchettizzino librerie native predefinite che non sono utilizzate in nessuna
creazione nativa esterna, aggiungile alla directory src/main/jniLibs/ABI
del tuo modulo.
Le versioni del plug-in Android per Gradle precedenti alla 4.0 devono includere i target CMake
IMPORTED
nella directory jniLibs
affinché vengano inclusi nella tua
app. Se esegui la migrazione da una versione precedente del plug-in, potrebbe
riscontrare 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 usi il plug-in Android per Gradle 4.0, sposta tutte le librerie utilizzate da
IMPORTED
CMake target fuori dalla directory jniLibs
per evitare questo errore.
Specifica ABI
Per impostazione predefinita, Gradle crea la tua libreria nativa in file .so
separati per le Application Binary Interfaces (ABI) supportate da NDK e li pacchettizza tutti nella tua app. Se vuoi che Gradle crei e pacchettizzi solo alcune configurazioni ABI delle tue librerie native, puoi specificarle con il flag ndk.abiFilters
nel file build.gradle
a livello di modulo, come mostrato di seguito:
Trendy
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 blocco ndk
, come mostrato sopra, perché indica a Gradle di creare e pacchettizzare queste versioni delle tue librerie native. Tuttavia, se vuoi controllare cosa deve creare Gradle, indipendentemente da ciò che vuoi pacchettizzare nella tua app, configura un altro flag abiFilters
nel blocco
defaultConfig.externalNativeBuild.cmake
(o nel blocco
defaultConfig.externalNativeBuild.ndkBuild
). Gradle crea queste configurazioni ABI, ma pacchettizza solo quelle specificate nel blocco
defaultConfig.ndk
.
Ti consigliamo di pubblicare l'app utilizzando Android App Bundle per ridurre ulteriormente le dimensioni dell'app, poiché con il download verranno caricate solo le librerie native corrispondenti all'ABI del dispositivo di un utente.
Per la pubblicazione di app legacy tramite APK (creati prima di agosto 2021), valuta la possibilità di configurare più APK basati su ABI. Anziché creare un unico APK di grandi dimensioni con tutte le versioni delle librerie native, Gradle crea un APK separato per ogni ABI che vuoi supportare e pacchettizza solo i file necessari per ciascuna ABI. Se configuri più APK per ABI senza specificare il flag abiFilters
come mostrato nell'esempio di codice riportato sopra, Gradle crea tutte le versioni ABI supportate delle tue librerie native, ma pacchettizza solo quelle specificate nella configurazione con più APK. Per evitare di creare versioni indesiderate delle tue librerie native, fornisci lo stesso elenco di ABI sia per il flag abiFilters
sia per la configurazione di più APK per ABI.