调试Mapbox Android NDK库

时间:2016-06-05 23:56:47

标签: android c++ android-studio android-ndk mapbox

我正在尝试按照位于以下位置的Android Studio实验插件用户指南说明进行操作:

http://tools.android.com/tech-docs/new-build-system/gradle-experimental

修改位于以下位置的Mapbox GL Native库:

https://github.com/mapbox/mapbox-gl-native

具体来说,我修改了以下Android文件:

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/gradle/wrapper/gradle-wrapper.properties

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/build.gradle

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/MapboxGLAndroidSDK/build.gradle

https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/MapboxGLAndroidSDKTestApp/build.gradle

我的目标是修改库,以便我可以调试它。理想情况下,我可以使用Android Studio构建库并调试C / C ++代码。到目前为止,我可以构建它,但我无法调试它。一位在Mapbox工作的程序员告诉我他们也不知道如何调试Android代码,所以我怀疑这不是一个容易实现的目标。

我已经做了很多不同的尝试来应用Android Studio实验插件用户指南说明,但我没有在Gradle经验,我的最新尝试给我留下了以下错误消息,我不明白:

  

Gradle'android'项目刷新失败   错误:原因:org.gradle.api.internal.ExtensibleDynamicObject

是否有人知道如何修改这些文件以使其构建可调试的Android NDK库?造成上述错误的原因是什么?

我正在使用:

> Linux Mint 17.2 
> Android Studio 2.1.1 
> Build #AI-143.2821654, built on April 28, 2016 
> JRE: 1.8.0_65-b17 amd64 
> JVM: Java HotSpot(TM) 64-Bit Server VM by Oracle Corporation

以下是我目前修改过的4个文件。由于我是Gradle的新手,不要以为我已经正确地进行了任何修改。我只是尝试应用Android Studio实验插件用户指南说明,直到我成功构建。

由于

#// mapbox-gl-native/platform/android/gradle/wrapper/gradle-wrapper.properties

#Thu Apr 07 14:21:05 CDT 2016

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#//distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip
#//distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-all.zip
distributionSha256Sum=e77064981906cd0476ff1e0de3e6fef747bd18e140960f1915cca8ff6c33ab5c
// mapbox-gl-native/platform/android/MapboxGLAndroidSDKTestApp/build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        // classpath 'com.android.tools.build:gradle:2.1.0'
        //classpath 'com.android.tools.build:gradle-experimental:0.7.0'
        classpath 'com.android.tools.build:gradle-experimental:0.8.0-alpha2'
        classpath 'com.github.JakeWharton:sdk-manager-plugin:220bf7a88a7072df3ed16dc8466fb144f2817070'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url "http://oss.sonatype.org/content/repositories/snapshots/" }
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.12'
}
// mapbox-gl-native/platform/android/MapboxGLAndroidSDK/build.gradle

apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.model.library'
apply plugin: 'checkstyle'
apply plugin: 'maven'
apply plugin: 'signing'

allprojects {
    group project.GROUP
    version project.VERSION_NAME

    repositories {
        mavenCentral()
    }
}

repositories {
    mavenCentral()
}

ext {
    supportLibVersion = '23.4.0'
}

dependencies {
    compile "com.android.support:support-annotations:${supportLibVersion}"
    compile "com.android.support:support-v4:${supportLibVersion}"
    compile "com.android.support:design:${supportLibVersion}"
    compile 'com.squareup.okhttp3:okhttp:3.3.0'
    compile 'com.mapzen.android:lost:1.1.0'
}

model {
android {
    compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
    buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION

    defaultConfig {
        minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK)
        targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
    }

    sourceSets {
        main.res.srcDirs += 'src/main/res-public'
    }

    repositories {
        mavenCentral()
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    lintOptions {
        checkAllWarnings true
        warningsAsErrors true
    }

    buildTypes {
        debug {
            jniDebuggable true
            buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT_BASE", new StringBuilder().append("\"").append("MapboxEventsAndroid/").append(project.VERSION_NAME).append("\"").toString()
        }

        release {
            jniDebuggable false
            buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT_BASE", new StringBuilder().append("\"").append("MapboxEventsAndroid/").append(project.VERSION_NAME).append("\"").toString()
            consumerProguardFiles 'proguard-rules.pro'
        }
    }
}
}

configurations {
    all*.exclude group: 'commons-logging', module: 'commons-logging'
    all*.exclude group: 'commons-collections', module: 'commons-collections'
}

model {
android.libraryVariants.all { variant ->
    def name = variant.name
    task "javadoc$name"(type: Javadoc) {
        description = "Generates javadoc for build $name"
        failOnError = false
        destinationDir = new File(destinationDir, variant.baseName)
        source = files(variant.javaCompile.source)
        classpath = files(variant.javaCompile.classpath.files) + files(android.bootClasspath)
        exclude '**/R.java', '**/BuildConfig.java', 'com/almeros/**'
        options.windowTitle("Mapbox Android SDK $VERSION_NAME Reference")
        options.docTitle("Mapbox Android SDK $VERSION_NAME")
        options.header("Mapbox Android SDK $VERSION_NAME Reference")
        options.bottom("© 2015–2016 Mapbox. All rights reserved.")
        options.links("http://docs.oracle.com/javase/7/docs/api/")
        options.linksOffline("http://d.android.com/reference/", "$System.env.ANDROID_HOME/docs/reference")
        options.overview("src/main/java/overview.html")
        options.group("Mapbox Android SDK", "com.mapbox.*")
        options.group("Third Party Libraries", "com.almeros.*")
        // TODO exclude generated R, BuildConfig, com.almeros.*
    }
}
}

checkstyle {
    configFile project.file('../checks.xml')
    showViolations true
}

/*
task cleanJNIBuilds {
    def jniLibsDir = new File("MapboxGLAndroidSDK/src/main/jniLibs")
    delete jniLibsDir.absolutePath
}
*/

model
{
android.libraryVariants.all { variant ->
    def name = variant.buildType.name
    def checkstyle = project.tasks.create "checkstyle${name.capitalize()}", Checkstyle
    checkstyle.dependsOn variant.javaCompile
    checkstyle.source variant.javaCompile.source
    checkstyle.classpath = project.fileTree(variant.javaCompile.destinationDir)
    checkstyle.exclude('**/BuildConfig.java')
    checkstyle.exclude('**/R.java')
    checkstyle.exclude('**/com/almeros/android/multitouch/**')
    project.tasks.getByName("check").dependsOn checkstyle
}

// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/jar.gradle
android.libraryVariants.all { variant ->
    def jarTask = project.tasks.create(name: "jar${variant.name.capitalize()}", type: Jar) {
        from variant.javaCompile.destinationDir
        exclude "**/R.class"
        exclude "**/BuildConfig.class"
    }
    jarTask.dependsOn variant.javaCompile
    artifacts.add('archives', jarTask);
}
}

// From https://raw.github.com/mcxiaoke/gradle-mvn-push/master/gradle-mvn-push.gradle
def isReleaseBuild() {
    return VERSION_NAME.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
    return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL :
            "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}

def getSnapshotRepositoryUrl() {
    return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL :
            "https://oss.sonatype.org/content/repositories/snapshots/"
}

def getRepositoryUsername() {
    return hasProperty('USERNAME') ? USERNAME :
            (hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "")
}

def getRepositoryPassword() {
    return hasProperty('PASSWORD') ? PASSWORD :
            (hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "")
}


task apklib(type: Zip) {
    appendix = extension = 'apklib'

    from 'AndroidManifest.xml'
    into('res') {
        from 'res'
    }
    into('src') {
        from 'src'
    }
}

artifacts {
    archives apklib
}

afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

                pom.groupId = GROUP
                pom.artifactId = POM_ARTIFACT_ID
                pom.version = VERSION_NAME

                repository(url: getReleaseRepositoryUrl()) {
                    authentication(userName: getRepositoryUsername(),
                            password: getRepositoryPassword())
                }
                snapshotRepository(url: getSnapshotRepositoryUrl()) {
                    authentication(userName: getRepositoryUsername(),
                            password: getRepositoryPassword())
                }

/*
                // Leaving out as artifact was incorrectly named when found
                addFilter('aar') { artifact, file ->
                    artifact.name == archivesBaseName
                }
                addFilter('apklib') { artifact, file ->
                    artifact.name == archivesBaseName + '-apklib'
                }
*/

                pom.project {
                    name POM_NAME
                    packaging POM_PACKAGING
                    description POM_DESCRIPTION
                    url POM_URL

                    scm {
                        url POM_SCM_URL
                        connection POM_SCM_CONNECTION
                        developerConnection POM_SCM_DEV_CONNECTION
                    }

                    licenses {
                        license {
                            name POM_LICENCE_NAME
                            url POM_LICENCE_URL
                            distribution POM_LICENCE_DIST
                        }
                    }

                    developers {
                        developer {
                            id POM_DEVELOPER_ID
                            name POM_DEVELOPER_NAME
                        }
                    }
                }
            }
        }
    }

    signing {
        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
        sign configurations.archives
    }

    model {
    task androidJavadocs(type: Javadoc) {
        source = android.sourceSets.main.java.sourceFiles
        classpath = files(android.bootClasspath)
    }
    }

    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
        classifier = 'javadoc'
        from androidJavadocs.destinationDir
    }

    model {
    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.sourceFiles
    }
    }

    artifacts {
        archives androidSourcesJar
        archives androidJavadocsJar
    }
}


task makeClean(type: Exec) {
    workingDir '../../'
    commandLine 'make', 'clean'
}

task makeAndroid(type: Exec) {
    workingDir '../../'
    commandLine 'make', 'android'
}

task makeAndroidAll(type: Exec) {
    workingDir '../../'
    commandLine 'make', 'apackage'
}
// mapbox-gl-native/platform/android/MapboxGLAndroidSDKTestApp/build.gradle

apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.model.application'
apply plugin: 'checkstyle'

task accessToken {
    def tokenFile = new File("MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml")
    if (!tokenFile.exists()) {
        String tokenFileContents = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                "<resources>\n" +
                "    <string name=\"mapbox_access_token\">" + "$System.env.MAPBOX_ACCESS_TOKEN" + "</string>\n" +
                "</resources>"

        if (tokenFileContents == null) {
            throw new InvalidUserDataException("You must set the MAPBOX_ACCESS_TOKEN environment variable.")
        }
        tokenFile.write(tokenFileContents)
    }
}

gradle.projectsEvaluated {
    // preBuild.dependsOn('accessToken')
}

ext {
    supportLibVersion = '23.4.0'
}

model {
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.mapbox.mapboxsdk.testapp"
        minSdkVersion.apiLevel 15
        targetSdkVersion.apiLevel 23
        versionCode 9
        versionName "4.1.0"

        // Specify AndroidJUnitRunner as the default test instrumentation runner
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'LICENSE.txt'
    }

    lintOptions {
        checkAllWarnings true
        warningsAsErrors true
        disable 'IconDensities'
        disable 'InvalidPackage'
    }

    testOptions {
        unitTests.returnDefaultValues = true
    }

    buildTypes {
        debug {
            // run code coverage reports
            testCoverageEnabled = true
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
}

dependencies {
    compile(project(':MapboxGLAndroidSDK')) {
        transitive = true
    }

    // Support libraries
    compile "com.android.support:support-annotations:${supportLibVersion}"
    compile "com.android.support:support-v4:${supportLibVersion}"
    compile "com.android.support:appcompat-v7:${supportLibVersion}"
    compile "com.android.support:design:${supportLibVersion}"
    compile "com.android.support:recyclerview-v7:${supportLibVersion}"

    // Leak Canary
    //debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
    //releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'

    // Directions SDK
    compile('com.mapbox.mapboxsdk:mapbox-android-directions:1.0.0@aar') {
        transitive = true
    }

    // Geocoder SDK
    compile('com.mapbox.mapboxsdk:mapbox-android-geocoder:1.0.0@aar') {
        transitive = true
    }

    // Testing dependencies
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:1.10.19'
    androidTestCompile "com.android.support:support-annotations:${supportLibVersion}"
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    androidTestCompile 'com.android.support.test:rules:0.4.1'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.5.4'
}

checkstyle {
    configFile project.file('../checks.xml')
    showViolations true
}

model {
android.applicationVariants.all { variant ->
    def name = variant.buildType.name
    def checkstyle = project.tasks.create "checkstyle${name.capitalize()}", Checkstyle
    checkstyle.dependsOn variant.javaCompile
    checkstyle.source variant.javaCompile.source
    checkstyle.classpath = project.fileTree(variant.javaCompile.destinationDir)
    checkstyle.exclude('**/BuildConfig.java')
    checkstyle.exclude('**/R.java')
    project.tasks.getByName("check").dependsOn checkstyle
}
}

1 个答案:

答案 0 :(得分:1)

您的gradle方法实质上是将Android SDK Makefile重写或移植到gradle。要解决您在Linux上所做的事情,您可能需要修改现有的Makefile。

原因是Mapbox Android SDK build process使用make android来构建目标libmapbox-gl.so。您拥有的Gradle项目包含.so文件和您常用的Java代码。

make android拨打mapbox-gl-native/Makefile

并生成mapbox-gl-native/build/android-arm-v7/Makefile,您可能需要研究如何修改以生成调试信息,正如Chris Stratton在上述评论中提到的那样。

当您开始修改C ++时,您需要修改settings.gradle以使用修改后的.so for Android。

include ':MapboxGLAndroidSDK'
project(':MapboxGLAndroidSDK').projectDir = new File(rootProject.projectDir, '<relative-path-to>/../mapbox-gl-native/platform/android/MapboxGLAndroidSDK')
include ':app'

需要考虑的另一件事 - 你能为Linux构建一个可调试的版本吗?

我们已经使用Xcode调试器为Mapbox SDK成功调试了C ++,因为我们也构建了一个iOS应用程序。我知道这不符合您的确切需求,但我提到它,以防您实验室或组织中的任何其他人在OS X上访问Xcode并可以使用make iproj开始调试。