AndroidStudio ndkBuild: How to include flavor jni folders? - android-studio

I am upgrading my project from experimentalNdk to ndkBuild
I have copied one of the previously generated Android.mk from build/intermediates/ndk/green/debug/Android.mk to my main jni folder.
I kept most of it but the following three includes, as they are flavor/buildType specific: (assuming productFlavor is "green")
LOCAL_C_INCLUDES += C:\path\to\project\modulename\src\green\jni
LOCAL_C_INCLUDES += C:\path\to\project\modulename\src\debug\jni
LOCAL_C_INCLUDES += C:\path\to\project\modulename\src\greenDebug\jni
I managed to add two of those lines via gradle:
externalNativeBuild {
ndkBuild {
path "$projectDir/src/main/jni/Android.mk"
}
}
productFlavors {
green {
externalNativeBuild {
ndkBuild {
arguments "LOCAL_C_INCLUDES+=$projectDir\src\green\jni"
}
}
}
... Other flavors ...
}
buildTypes {
debug {
externalNativeBuild {
ndkBuild {
arguments "LOCAL_C_INCLUDES+=$projectDir\src\debug\jni"
}
}
}
... Other build types ...
}
But where can I add the third line, that combines both?
LOCAL_C_INCLUDES+=$projectDir\src\greenDebug\jni

Related

Autocompletion not working in Android Studio Arctic Fox inside buildSrc

I am writing a custom plugin inside buildSrc using Android Studio Arctic Fox installed by brew. After some tests, there is a problem with the autocompletion of imports. It works inside app/build.gradle.kts that I can do import com.android.build.api.dsl.*, but inside buildSrc this raised Unresolved reference on android namespace.
The root build.gradle.kts:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
extra["kotlin_version"] = "1.4.32"
classpath("com.android.tools.build:gradle:7.0.2")
classpath(kotlin("gradle-plugin", version = "1.4.32"))
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
build.gradle.kts under buildSrc:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.4.31"
`kotlin-dsl`
}
repositories {
google()
mavenCentral()
}
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "11"
apiVersion = "1.4"
}
}
dependencies {
implementation("com.android.tools.build:gradle:7.0.2")
implementation("com.android.tools.build:gradle-api:7.0.2")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32")
implementation(kotlin("stdlib"))
gradleApi()
}
build.gradle.kts under app:
import com.example.pythonLibs
plugins {
id("com.android.application")
kotlin("android")
id("com.example.plugin")
}
android {
compileSdk = 30
ndkVersion = "23.0.7599858"
sourceSets {
getByName("main") {
pythonLibs {
srcDir("src/main/pythonLibs")
}
}
}
defaultConfig {
applicationId = "com.example.embedpythontest"
minSdk = 23
targetSdk = 30
versionCode = 1
versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// consumerProguardFiles = [file("consumer-rules.pro")]
externalNativeBuild {
cmake {
//arguments("-DANDROID_STL=c++_shared")
//cppFlags("")
}
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.21.3"
}
}
compileOptions {
sourceCompatibility(JavaVersion.VERSION_11)
targetCompatibility(JavaVersion.VERSION_11)
}
kotlinOptions {
jvmTarget = "11"
apiVersion = "1.4"
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation("androidx.appcompat:appcompat:1.3.1")
implementation("com.google.android.material:material:1.4.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.1")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.3")
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
}
in all files under buildSrc/src/main/kotlin/**, when doing import com.android.build.api.dsl.*, a problem shown but build project is ok. But if I do import inside buildSrc/build.gradle.kts, it won't be compiled. But the same thing could be done inside app/build.gradle.kts.
Why Android Studio cannot find the class?
This problem is caused by not being familiar with the dependencies in Gradle. After changing the dependncy block to:
dependencies {
implementation("com.android.tools.build:gradle-api:7.0.2")
implementation(kotlin("stdlib"))
gradleApi()
}
which copied from here that would solve the problem.

Android Studio Wikitude Native SDK Issue

So im trying to first build a basic app using android studio and Wikitudes Native SDK to make an AR app. After following the setup instructions ive ran into an error I cant seem to solve but have an idea of why/where its happening. Does anyone know what could be causing these errors?
This image here shows the errors I am getting and what looks to be an issue with a few of the imports
Here is also a copy of my build.gradle file (Module: app), and my build.gradle file (Module: NativeSDKExamples), respectively:
apply plugin: 'com.android.application'
android {
compileSdkVersion commonCompileSdkVersion
buildToolsVersion commonBuildToolsVersion
defaultConfig {
applicationId "com.uhg.ent.mobile.lifesciences.amplify"
minSdkVersion commonMinSdkVersion
targetSdkVersion commonTargetSdkVersion
versionCode 1
versionName "7.2.1"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
debuggable true
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = "app-" + variant.buildType.name + ".apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
flavorDimensions "arch"
productFlavors {
arm7 {
dimension "arch"
}
arm8 {
dimension "arch"
}
x86 {
dimension "arch"
}
allarchs {
dimension "arch"
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile (name: 'wikitude-native-sdk', ext:'aar')
arm7Compile project(path: ':plugins', configuration: 'arm7Release')
arm8Compile project(path: ':plugins', configuration: 'arm8Release')
x86Compile project(path: ':plugins', configuration: 'x86Release')
allarchsCompile project(path: ':plugins', configuration: 'allarchsRelease')
compile "com.android.support:appcompat-v7:$commonSupportLibVersion"
compile "com.android.support:design:$commonSupportLibVersion"
compile "com.android.support:support-v4:$commonSupportLibVersion"
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.google.android:flexbox:0.2.5'
}
repositories {
mavenCentral()
flatDir {
dirs 'libs'
}
}
AND
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
maven {
url 'https://maven.google.com'
}
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
subprojects {
ext.commonCompileSdkVersion = 26
ext.commonBuildToolsVersion = "26.0.0"
ext.commonMinSdkVersion = 19
ext.commonTargetSdkVersion = 26
ext.commonSupportLibVersion = "26.0.0"
}
allprojects {
repositories {
jcenter()
maven {
url 'https://maven.google.com'
}
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
}

Cannot properly compile play services for libgdx

So I've been trying to add google play services for my game.
First thing I did was add the dependency to the gradle file. This is how it looks now:
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'com.google.gms:google-services:3.0.0'
}
}
allprojects {
apply plugin: "eclipse"
apply plugin: "idea"
version = '1.0'
ext {
appName = "My First Game"
gdxVersion = '1.9.3'
roboVMVersion = '2.1.0'
box2DLightsVersion = '1.4'
ashleyVersion = '1.7.0'
aiVersion = '1.8.0'
googlePlayVersion = '9.4.0'
}
repositories {
mavenLocal()
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url "https://oss.sonatype.org/content/repositories/releases/" }
}
}
project(":android") {
apply plugin: "android"
configurations { natives }
dependencies {
compile project(":core")
compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-arm64-v8a"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86_64"
compile "com.badlogicgames.box2dlights:box2dlights:$box2DLightsVersion"
compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion"
compile "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion"
compile "com.google.android.gms:play-services:$googlePlayVersion"
}
}
project(":core") {
apply plugin: "java"
dependencies {
compile "com.badlogicgames.gdx:gdx:$gdxVersion"
compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
compile "com.badlogicgames.box2dlights:box2dlights:$box2DLightsVersion"
compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion"
}
}
tasks.eclipse.doLast {
delete ".project"
}
Here is a picture of the packages I have installed
However I still can't use the library and if I try to make for example an AdView (which I should now be able to) it goes red and can't be identified, however I can Alt+Enter to
Add library 'play-services-ads-lite-9.4.0' to classpath
If I add that, it adds the following line to the module (not project) gradle file:
compile 'com.google.android.gms:play-services-ads-lite:9.4.0'
and I get this gradle error.
If I go to:
/home/user/Android/Sdk/extras/google/m2repository/com/google/android
I can see the folders play-services, play-services-ads, etc, so I know they are there!
Thank you for taking the time to look into my problem. All help is appreciated!
EDIT: It has come to my attention that you might need the code: apply plugin: 'com.google.gms.google-services'.
I'm not sure where this should be however it says i need a file google-services.json. Not sure you should need this? Here is where i place the above line of code:
project(":android") {
apply plugin: "android"
configurations { natives }
dependencies {
compile project(":core")
compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"
compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-arm64-v8a"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86"
natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86_64"
compile "com.badlogicgames.box2dlights:box2dlights:$box2DLightsVersion"
compile "com.badlogicgames.gdx:gdx-controllers:$gdxVersion"
compile "com.badlogicgames.gdx:gdx-controllers-android:$gdxVersion"
compile "com.google.android.gms:play-services:$googlePlayVersion"
}
apply plugin: 'com.google.gms.google-services'
}
EDIT2: if I try to put the dependency as well as the "apply plugin" in this file instead of the project gradle I get the same result in the fork of an error message saying that google-services.json is missing. This is my module android gradle:
android {
buildToolsVersion "23.0.2"
compileSdkVersion 23
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
instrumentTest.setRoot('tests')
}
defaultConfig {
applicationId "com.oscarboking.myfirstgame"
minSdkVersion 9
targetSdkVersion 23
}
}
// called every time gradle gets executed, takes the native dependencies of
// the natives configuration, and extracts them to the proper libs/ folders
// so they get packed with the APK.
task copyAndroidNatives() {
file("libs/armeabi/").mkdirs();
file("libs/armeabi-v7a/").mkdirs();
file("libs/arm64-v8a/").mkdirs();
file("libs/x86_64/").mkdirs();
file("libs/x86/").mkdirs();
configurations.natives.files.each { jar ->
def outputDir = null
if (jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a")
if (jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
if (jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
if (jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64")
if (jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
if (outputDir != null) {
copy {
from zipTree(jar)
into outputDir
include "*.so"
}
}
}
}
task run(type: Exec) {
def path
def localProperties = project.file("../local.properties")
if (localProperties.exists()) {
Properties properties = new Properties()
localProperties.withInputStream { instr ->
properties.load(instr)
}
def sdkDir = properties.getProperty('sdk.dir')
if (sdkDir) {
path = sdkDir
} else {
path = "$System.env.ANDROID_HOME"
}
} else {
path = "$System.env.ANDROID_HOME"
}
def adb = path + "/platform-tools/adb"
commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.oscarboking.myfirstgame/AndroidLauncher'
}
// sets up the Android Eclipse project, using the old Ant based build.
eclipse {
// need to specify Java source sets explicitly, SpringSource Gradle Eclipse plugin
// ignores any nodes added in classpath.file.withXml
sourceSets {
main {
java.srcDirs "src", 'gen'
}
}
jdt {
sourceCompatibility = 1.6
targetCompatibility = 1.6
}
classpath {
plusConfigurations += [project.configurations.compile]
containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
}
project {
name = appName + "-android"
natures 'com.android.ide.eclipse.adt.AndroidNature'
buildCommands.clear();
buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
buildCommand "org.eclipse.jdt.core.javabuilder"
buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
}
}
// sets up the Android Idea project, using the old Ant based build.
idea {
module {
sourceDirs += file("src");
scopes = [COMPILE: [plus: [project.configurations.compile]]]
iml {
withXml {
def node = it.asNode()
def builder = NodeBuilder.newInstance();
builder.current = node;
builder.component(name: "FacetManager") {
facet(type: "android", name: "Android") {
configuration {
option(name: "UPDATE_PROPERTY_FILES", value: "true")
}
}
}
}
}
}
}
dependencies {
compile "com.google.android.gms:play-services:9.4.0"
}
apply plugin: 'com.google.gms.google-services'
If I try to use anything in the library I can alt+enter to the dependency however it tries to add it to the core module gradle file.
I'm using classpath 'com.google.gms:google-services:2.0.0' in my project gradle and compile 'com.google.android.gms:play-services-analytics:8.4.0'
compile 'com.google.android.gms:play-services-appinvite:8.4.0'
compile 'com.google.android.gms:play-services-games:8.4.0' in my android module gradle.
I'm also using google analytics, so the first one or two imports may be unnecessary.
Maybe you have to clean the project/remove the .gradle folder.

How to configure srcDir for components with Android Experimental Gradle Module

I currently have a series of components with java, aidl, assets, resources, jni, and manifests and proguard files to support the components.
I would like to deliver AAR files with a number of different combinations of these components.
I would like to be able to debug the code in each component when assembled (which I think means making a project that includes all the components source files, as AAR explosion doesn't do release/debug variants.)
I want to use the experimental gradle plug in for the NDK part.
My first hack looks like:
model {
android {
// ... stuff
sources {
main {
def mySourceSet = ["../../sourceTree/client",
"../../sourceTree/instrumentation",
"../../sourceTree/engine"]
java {
source {
srcDirs = mySourceSet } } }
aidl {
source {
srcDirs = mySourceSet } } }
resources {
source {
srcDirs = mySourceSet } } }
assets {
source {
srcDirs = mySourceSet } } }
manifest {
source {
srcDirs = mySourceSet } } }
jniLibs {
source {
srcDirs = mySourceSet } } }
jni {
source {
srcDirs = mySourceSet } } }
}
}
}
}
The java classes get combined as I would like.
The aidl files get combined as I would like.
Everything else is not quite there (manifests aren't merged, resources/assets pick up java classes, and still using old .so from previous build system.)
Going into the different rules, it looks like mySourceSet is going to need repetition to do the right thing for the non java/aidl files to get the format right to pick things up (or exclude them.) I've been trying (with little success) to see what I can do with += notation and if I can move those to a gradle settings/config fragment in the sourceTree, include it, and have it modify the srcDirs.
I'd like something like one of these to work:
model { android { sources { main { aidl { source { srcDirs += "../../sourceTree/instrumentation" } } } } } }
model.android.sources.main.aidl.source << { srcDirs += "../../sourceTree/instrumentation" }
model.android << { sources { main { aidl { source { srcDirs += "../../sourceTree/instrumentation" } } } } }
but they fail with various "you can't do that" errors.
Is there a way to set the srcDirs outside the android { model {}} block?
Any hints on how to make the assets/resources/manifest merge correctly given a list of top level directories it should look through?

How to generate on the fly Java source code to build with Gradle in Android Studio?

As part of an Android app that uses the NDK, I need to export some constants from the C/C++ world into Java. For obvious reasons, I'd rather have this automated. I'm using Android Studio with the NDK support.
How can I generate some .java file on the fly from a shell script that would be ran by Gradle whenever the app builds? Ideally this .java file would go in an build intermediaries directory somewhere and wouldn't have to be in the app source directory.
As an example, the shell script would generate this Java source:
public enum Type {
FOO,
BAR
}
from this C++ source:
enum class Type {
FOO,
BAR
}
For reference here's a simplified version of the Gradle file I'm starting from in Android Studio:
apply plugin: 'com.android.model.application'
model {
compileOptions.with {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "..."
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
}
defaultConfig.multiDexEnabled = true
}
android.ndk {
platformVersion = "18"
moduleName = "jni"
...
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
ndk.with {
CFlags.add("-Werror")
cppFlags.add("-Werror")
}
}
}
android.productFlavors {
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
}
}
repositories {
...
}
dependencies {
...
}
apply plugin: 'com.google.gms.google-services'
You could just write the generated file to the $buildDir/generatedJava then add that directory as a source folder. Then make the task javaCompile depend on your task that generates the source. Something like this could be used inside a build.gradle
def outputJavaFile = new File("$buildDir.absolutePath/generatedJava", 'MyEnum.java')
task generateSources(type: Exec) {
def source = $/
package com.example;
public enum Something {
One,
Two
}
/$
if (!outputJavaFile.parentFile.exists()) {
outputJavaFile.parentFile.mkdirs()
}
outputJavaFile.withWriter {
it << source
}
}
compileJava.dependsOn outputJavaFile
sourceSets {
main {
java {
srcDirs 'src/main/java', outputJavaFile.absolutePath
}
}
}
// if the goal is to generate the source from a script then just call the script
// inside the Exec closure
task shellScriptToGenerateSources(type: Exec) {
commandLine 'myShellScript.sh'
}
// then make compileJava depend on the task that runs the script
compileJava.dependsOn shellScriptToGenerateSources
Edit: To apply the same logic to your updated build.gradle file might look something like this
apply plugin: 'com.android.model.application'
// define an output folder for our generated .java files
def GENERATED_JAVA_OUTPUT = "$buildDir/generatedJava"
// if the goal is to generate the source from a script then just call the script
// inside the Exec closure
task shellScriptToGenerateSources(type: Exec) {
commandLine 'myShellScript.sh'
}
// then make compileJava depend on the task that runs the script
compileJava.dependsOn shellScriptToGenerateSources
model {
compileOptions.with {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "..."
minSdkVersion.apiLevel = 18
targetSdkVersion.apiLevel = 23
}
defaultConfig.multiDexEnabled = true
}
android.ndk {
platformVersion = "18"
moduleName = "jni"
...
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
ndk.with {
CFlags.add("-Werror")
cppFlags.add("-Werror")
}
}
}
android.productFlavors {
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
}
// let android know that our java sources shoudl also consider the generated java for the compiler
android.sourceSet {
main {
java {
srcDir(GENERATED_JAVA_OUTPUT)
}
}
}
}
repositories {
...
}
dependencies {
...
}
apply plugin: 'com.google.gms.google-services'

Resources