简体   繁体   中英

How to create new module (android library) into libgdx apllication? (if it is possible)

I created libgdx application with android module (kotlin - libktx) - I use: https://github.com/tommyettinger/gdx-liftoff

I tried to add new module (Android Library) in Android Studio, but it do not work: Cannot add extension with name 'kotlin', as there is an extension already registered with that name.

I tried to modify build.gradle of created module, but it do not help. Just the error was changing. I would like to ask if you know: is it possible to add Android Library Module to libgdx application? And how?

If I add new module (Java or Kotlin Library), it works. But I would like to create module with android dependencies. If it is possible. Thank you.

UPDATE:

Here are my gradle files and description of changes what I tried to do. If anyone can help.

I am trying to do this with the fresh libgdx project. I made a copy of folder "android" and rename it to "androTest".

I changed in project (in root folder): settings.gradle

include 'core', 'lwjgl3', 'android', 'androTest'

In root folder in file build.gradle I made a copy of part with subproject configuration of android and the final file is:

buildscript {
    repositories {
        mavenCentral()
        maven { url 'https://s01.oss.sonatype.org' }
        mavenLocal()
        google()
        gradlePluginPortal()
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
        maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:$androidPluginVersion"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"

        // This follows advice from https://blog.gradle.org/log4j-vulnerability
        constraints {
            classpath("org.apache.logging.log4j:log4j-core") {
                version {
                    strictly("[2.18, 3[")
                    prefer("2.18.0")
                }
                because("CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities")
            }
        }
    }
}

allprojects {
    apply plugin: 'eclipse'
    apply plugin: 'idea'
}

configure(subprojects - project(':android')) {
    apply plugin: 'java-library'
    apply plugin: 'kotlin'
    sourceCompatibility = 1.8
    compileJava {
        options.incremental = true
    }
    dependencies {
        // This follows advice from https://blog.gradle.org/log4j-vulnerability
        constraints {
            implementation("org.apache.logging.log4j:log4j-core") {
                version {
                    strictly("[2.18, 3[")
                    prefer("2.18.0")
                }
                because("CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities")
            }
        }
    }
}

configure(subprojects - project(':androTest')) {
    apply plugin: 'java-library'
    apply plugin: 'kotlin'
    sourceCompatibility = 1.8
    compileJava {
        options.incremental = true
    }
    dependencies {
        // This follows advice from https://blog.gradle.org/log4j-vulnerability
        constraints {
            implementation("org.apache.logging.log4j:log4j-core") {
                version {
                    strictly("[2.18, 3[")
                    prefer("2.18.0")
                }
                because("CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities")
            }
        }
    }
}

subprojects {
    version = '1.0.0'
    ext.appName = 'TestLibGDXProject'
    repositories {
        mavenCentral()
        maven { url 'https://s01.oss.sonatype.org' }
        mavenLocal()
        gradlePluginPortal()
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
        maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
        maven { url 'https://jitpack.io' }
    }
}

eclipse.project.name = 'TestLibGDXProject' + '-parent'

File build.gradle from new folder "androTest" is the same as build.gradle in original "android" folder except of last line. In "androTest" I changed only last line. There is file from "androTest" folder:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 30
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src/main/java', 'src/main/kotlin']
            aidl.srcDirs = ['src/main/java', 'src/main/kotlin']
            renderscript.srcDirs = ['src/main/java', 'src/main/kotlin']
            res.srcDirs = ['res']
            assets.srcDirs = ['../assets']
            jniLibs.srcDirs = ['libs']
        }
    }
    packagingOptions {
        // Preventing from license violations (more or less):
        pickFirst 'META-INF/LICENSE.txt'
        pickFirst 'META-INF/LICENSE'
        pickFirst 'META-INF/license.txt'
        pickFirst 'META-INF/LGPL2.1'
        pickFirst 'META-INF/NOTICE.txt'
        pickFirst 'META-INF/NOTICE'
        pickFirst 'META-INF/notice.txt'
        // Excluding unnecessary meta-data:
        exclude 'META-INF/robovm/ios/robovm.xml'
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/dependencies.txt'
    }
    defaultConfig {
        applicationId 'com.testgdx.testlibgdxproject'
        minSdkVersion 19
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
    compileOptions {
        sourceCompatibility "1.8"
        targetCompatibility "1.8"
        coreLibraryDesugaringEnabled true
    }
    kotlinOptions.jvmTarget = "1.8"
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

repositories {
    // needed for AAPT2, may be needed for other tools
    google()
}

configurations { natives }

dependencies {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
    implementation "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
    implementation project(':core')

    natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a"
    natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
    natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
    natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64"

    // This follows advice from https://blog.gradle.org/log4j-vulnerability
    constraints {
        implementation("org.apache.logging.log4j:log4j-core") {
            version {
                strictly("[2.18, 3[")
                prefer("2.18.0")
            }
            because("CVE-2021-44228, CVE-2021-45046, CVE-2021-45105: Log4j vulnerable to remote code execution and other critical security vulnerabilities")
        }
    }
}

// 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() {
    doFirst {
        file("libs/armeabi-v7a/").mkdirs()
        file("libs/arm64-v8a/").mkdirs()
        file("libs/x86_64/").mkdirs()
        file("libs/x86/").mkdirs()

        configurations.getByName("natives").copy().files.each { jar ->
            def outputDir = null
            if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
            if(jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a")
            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"
                }
            }
        }
    }
}
tasks.matching { it.name.contains("merge") && it.name.contains("JniLibFolders") }.configureEach { packageTask ->
    packageTask.dependsOn 'copyAndroidNatives'
}

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_SDK_ROOT"
        }
    } else {
        path = "$System.env.ANDROID_SDK_ROOT"
    }

    def adb = path + "/platform-tools/adb"
    commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.testgdx.testlibgdxproject/com.testgdx.testlibgdxproject.android.AndroidLauncher'
}

eclipse.project.name = appName + "-androTest"

If I try to build it I can see error:

A problem occurred evaluating project ':android'.
> Failed to apply plugin 'kotlin-android'.
   > Cannot add extension with name 'kotlin', as there is an extension already registered with that name.

if I remove the problem line from build.gradle file (apply plugin: 'kotlin-android') I can see new error:

* What went wrong:
A problem occurred evaluating project ':android'.
> Could not get unknown property 'kotlinOptions' for extension 'android' of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension.

I remove the line from build.gradle file (kotlinOptions.jvmTarget = "1.8") and I can see error:

A problem occurred configuring project ':android'.
> com.android.build.gradle.internal.BadPluginException: The 'java' plugin has been applied, but it is not compatible with the Android plugins.

All errors are from original "android" module.

Liftoff's partial author here. It looks like the issue has to do with configure(subprojects - project(':android')) { in the root build.gradle file, which includes all projects except for the android project, and still includes the newly-added androTest project. You probably want configure(subprojects - project(':android') - project(':androTest')) { instead, which makes androTest use the same configuration (or lack of it) that the android project uses. You'll also want to remove the entire configure(subprojects - project(':androTest')) { block, which is entirely broken because it will try to configure android with the same config the last block excluded android from.

I haven't pushed a release in a little while, but one should be coming up soon. I noticed how ugly the dependency constraints are here, and they aren't needed in the current Gradle version, so the next GDX-Liftoff release will remove the constraints (and you can remove them now yourself if you want).

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM