android - 调试 Mapbox Android NDK 库

标签 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' project refresh failed Error:Cause: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
}
}

最佳答案

您的 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 用于 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 开始调试。

关于android - 调试 Mapbox Android NDK 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37647941/

相关文章:

android-studio - Android Studio: “Update & Restart”不起作用

android - Android:使用OpenCV对齐图像

android - 如何在 AndEngine 中使用斜体或粗体创建自定义字体?

c++ - #import 指令创建的 COM 包装器类用 unsigned short 替换 wchar_t

c++ - 如果不先声明函数,我可以交换变量的值吗?

安卓房间数据库。以表名作为参数创建和删除表

android - 这是什么错误?

android - MPAndroidChart:删除点 lineChart 之间的填充

c++ - 库达 : mix c++ and cuda code

android-studio - 模拟器没有出现在android studio