Android Studio 14 原生开发 + CrystaX NDK

2024-04-22

我正在尝试将一个巨大的跨平台 C++11 (iOS+Android) 应用程序项目迁移到 Android Studio 14。我使用 CrystaX NDK 进行 boost 和 C++14。他们网站的博客上有官方 Android Studio + CrystaX 教程here https://www.crystax.net/en/blog/3但它已经过时了。

我已经下载了官方的 hello-jni 示例,该示例旨在与 Android Studio 1.4 一起使用,并尝试对其进行调整以与 CrystaX NDK 一起使用。这些是我的 Gradle 2.5 设置:

项目构建.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
       jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle-experimental:0.2.0'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

模块构建.gradle

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.1"

        defaultConfig.with {
            applicationId = "com.tableair.app"
            minSdkVersion.apiLevel = 4
            targetSdkVersion.apiLevel = 23
        }
    }

    compileOptions.with {
        sourceCompatibility=JavaVersion.VERSION_1_7
        targetCompatibility=JavaVersion.VERSION_1_7
    }

    /*
     * native build settings
     */
    android.ndk {
        moduleName = "tableair-framework"
        cppFlags += "-std=c++11"
        cppFlags += "-Werror"
        ldLibs = ["android", "log", "GLESv2", "crystax"]
        stl = "gnustl_static"
        /*
         * Other ndk flags configurable here are
         * cppFlags += "-fno-rtti"
         * cppFlags += "-fno-exceptions"
         * ldLibs    = ["android", "log"]
         * stl       = "system"
         */
    }
    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles  += file('proguard-rules.txt')
        }
    }
    android.productFlavors {
        // for detailed abiFilter descriptions, refer to "Supported ABIs" @
        // https://developer.android.com/ndk/guides/abis.html#sa
        create("arm") {
            ndk.abiFilters += "armeabi"
        }
        create("arm7") {
            ndk.abiFilters += "armeabi-v7a"
        }
        create("arm8") {
            ndk.abiFilters += "arm64-v8a"
        }
        create("x86") {
            ndk.abiFilters += "x86"
        }
        create("x86-64") {
            ndk.abiFilters += "x86_64"
        }
        create("mips") {
            ndk.abiFilters += "mips"
        }
        create("mips-64") {
            ndk.abiFilters += "mips64"
        }
        // To include all cpu architectures, leaves abiFilters empty
        create("all")
    }
}

本地属性

ndk.dir=/Users/vilius/Software/Android/crystax-ndk-10.2.1
sdk.dir=/Users/vilius/Library/Android/sdk

当我尝试运行该应用程序时。我收到此错误:

....
:app:generateAllDebugAndroidTestSources UP-TO-DATE
:app:copyArm64-v8aDebugAllTableair-frameworkSharedLibraryGdbServer UP-TO-DATE
:app:createArm64-v8aDebugAllTableair-frameworkSharedLibraryGdbsetup
:app:compileArm64-v8aDebugAllTableair-frameworkSharedLibraryTableair-frameworkMainC UP-TO-DATE
:app:linkArm64-v8aDebugAllTableair-frameworkSharedLibrary
/Users/vilius/Software/Android/crystax-ndk-10.2.1/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/bin/ld:     cannot find -lcrystax
/Users/vilius/Software/Android/crystax-ndk-10.2.1/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/bin/ld:     cannot find -lcrystax
Error:error: ld returned 1 exit status
Error:Execution failed for task ':app:linkArm64-v8aDebugAllTableair-frameworkSharedLibrary'.
> A build operation failed.
      Linker failed while linking libtableair-framework.so.
  See the complete log at: file:///Users/vilius/TableAir/Mobile/app/android-studio-project/app/build/tmp/linkArm64-v8aDebugAllTableair-frameworkSharedLibrary/output.txt    

.../output.txt 显示与消息窗口中完全相同的信息。

有人对这个问题有想法吗?


是的,例如here https://www.crystax.net/en/blog/3有点过时了,因此我们计划很快发布新文章,其中更新了如何将 CrystaX NDK 与新的实验性 Gradle 插件结合使用的描述。在此期间,您可以关注example https://github.com/crystax/android-samples-android-studio我已经推送到github了。该示例中最有趣的部分是应用程序的 build.gradle,因此为了方便起见,我将其复制到此处:

import org.gradle.internal.os.OperatingSystem;

apply plugin: 'com.android.model.application'

final APP_ABIS = ["armeabi", "armeabi-v7a", "x86"]
final BOOST_SHARED_LIBS = ["boost_serialization"]

model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.1"

        defaultConfig.with {
            applicationId = "net.crystax.testboost2"
            minSdkVersion.apiLevel = 15
            targetSdkVersion.apiLevel = compileSdkVersion.asType(Integer)
            versionCode = 1
            versionName = "1.0"
        }

    }

    compileOptions.with {
        sourceCompatibility = JavaVersion.VERSION_1_7
        targetCompatibility = JavaVersion.VERSION_1_7
    }

    android.ndk {
        moduleName = "test-boost2"
        cppFlags += "-std=c++11"
        cppFlags += "-fexceptions"
        cppFlags += "-frtti"
        cppFlags += "-Werror"
        cppFlags += "-I" + getBoostIncDir()
        ldLibs.addAll BOOST_SHARED_LIBS
        ldLibs += "log"
        stl = "gnustl_shared"
    }

    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles += file('proguard-rules.pro')
        }
    }

    android.productFlavors {
        APP_ABIS.each { abi ->
            create(getFlavorName(abi)) {
                ndk.with {
                    abiFilters += abi
                    getPrebuiltLibPaths(abi).each { path ->
                        ldFlags += "-L" + path
                    }
                }
            }
        }
    }

}

tasks.all {
    task ->
        if (task.name.startsWith('link')) {
            task.dependsOn copyNativeLibs, stripNativeLibs
        }
}

task copyNativeLibs {
    ["debug", "release"].each { buildType ->
        APP_ABIS.each { abi ->
            def libs = [:]
            BOOST_SHARED_LIBS.each { name ->
                libs[name] = "${getBoostLibDir(abi)}/lib${name}.so"
            }
            libs.crystax = getLibCrystax(abi)

            libs.each { name, file ->
                dependsOn tasks.create(name: "copy-native-library-${name}-${abi}-${buildType}", type: Copy) {
                    from file
                    into getTargetLibDir(abi, buildType)
                }
            }
        }
    }
}

task stripNativeLibs(dependsOn: copyNativeLibs) {
    ["debug", "release"].each { buildType ->
        APP_ABIS.each { abi ->
            def libs = []
            libs.addAll(BOOST_SHARED_LIBS)
            libs += "crystax"

            libs.each { name ->
                dependsOn tasks.create(name: "strip-native-library-${name}-${abi}-${buildType}", type: Exec) {
                    commandLine getStripExecutable(abi), "--strip-unneeded", "${getTargetLibDir(abi, buildType)}/lib${name}.so"
                }
            }

        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.android.support:design:23.0.1'
}

def getNdkDir() {
    if (System.env.ANDROID_NDK_ROOT != null)
        return System.env.ANDROID_NDK_ROOT

    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())
    def ndkdir = properties.getProperty('ndk.dir', null)
    if (ndkdir == null)
        throw new GradleException("""\
                NDK location not found.
                Define location with ndk.dir in the local.properties file
                or with an ANDROID_NDK_ROOT environment variable.""")

    return ndkdir
}

def getCrystaxNdkDir() {
    def ndkDir = getNdkDir()
    if (!(new File(ndkDir, "sources/crystax").exists()))
        throw new GradleException("""\
            '${ndkDir}' is not a CrystaX NDK.
            Edit ndk.dir in local.properties or set ANDROID_NDK_ROOT
            environment variable pointing to CrystaX NDK""")

    return ndkDir
}

def getFlavorName(abi) {
    switch (abi) {
        case "armeabi":
            return "arm";
        case "armeabi-v7a":
            return "arm7"
        case "arm64-v8a":
            return "arm64"
        default:
            return abi.replaceAll('-', '_')
    }
}

def getToolchainName(abi) {
    switch (abi) {
        case ~/^armeabi.*/:
            return "arm-linux-androideabi"
        case ~/^arm64.*/:
            return "aarch64-linux-android"
        case "mips":
            return "mipsel-linux-android"
        case "mips64":
            return "mips64el-linux-android"
        case ["x86", "x86_64"]:
            return abi
        default:
            throw new GradleException("Unsupported ABI: '${abi}'")
    }
}

def getToolchainPrefix(abi) {
    switch (abi) {
        case ~/^armeabi.*/:
            return "arm-linux-androideabi"
        case ~/^arm64.*/:
            return "aarch64-linux-android"
        case "mips":
            return "mipsel-linux-android"
        case "mips64":
            return "mips64el-linux-android"
        case "x86":
            return "i686-linux-android"
        case "x86_64":
            return "x86_64-linux-android"
        default:
            throw new GradleException("Unsupported ABI: '${abi}'")
    }
}

def getHostOS() {
    if (OperatingSystem.current().isLinux())
        return "linux"
    if (OperatingSystem.current().isMacOsX())
        return "darwin"
    if (OperatingSystem.current().isWindows())
        return "windows"
    throw new GradleException("Unsupported host OS")
}

def getHostArch() {
    def arch = System.getProperty("os.arch")
    switch (arch) {
        case ["x86_64", "amd64"]:
            return "x86_64"
        case ~/^i[3456]86/:
        case "x86":
            return "x86"
        default:
            throw new GradleException("Can't detect host's CPU architecture: '${arch}'")
    }
}

def getHostTag() {
    def tag = getHostOS()
    def arch = getHostArch()
    if (tag != "windows" || arch != "x86")
        tag += "-${arch}"
    return tag
}

def getStripExecutable(abi) {
    def ndk = getCrystaxNdkDir()
    def toolchainName = getToolchainName(abi)
    def toolchainPrefix = getToolchainPrefix(abi)
    def hostTag = getHostTag()
    def strip = "${ndk}/toolchains/${toolchainName}-4.9/prebuilt/${hostTag}/bin/${toolchainPrefix}-strip"
    if (OperatingSystem.current().isWindows())
        strip = strip.replaceAll('/', '\\\\') + '.exe'
    return strip
}

def getPrebuiltLibPaths(abi) {
    def paths = []
    paths += getBoostLibDir(abi)
    paths += getLibCrystaxDir(abi)
    return paths
}

def getTargetLibDir(abi, buildType) {
    return "${buildDir}/intermediates/binaries/${buildType}/${getFlavorName(abi)}/lib/${abi}"
}

def getLibCrystaxDir(abi) {
    return "${getCrystaxNdkDir()}/sources/crystax/libs/${abi}"
}

def getLibCrystax(abi) {
    return "${getLibCrystaxDir(abi)}/libcrystax.so"
}

def getBoostDir() {
    return "${getCrystaxNdkDir()}/sources/boost/1.58.0"
}

def getBoostIncDir() {
    return "${getBoostDir()}/include"
}

def getBoostLibDir(abi) {
    return "${getBoostDir()}/libs/${abi}"
}

我已经使用 Android Studio 1.4 和 gradle 实验插件 0.2.0 对其进行了测试。

其实定制copyNativeLibs仅将共享库包含到 apk 中所需的任务;如果您链接静态库,copyNativeLibs根本不需要。

UPDATE:我已经添加stripNativeLibs任务只是因为我意识到 APK 包含了带有调试信息的未剥离库,使其大小太大而没有任何实际需要。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Studio 14 原生开发 + CrystaX NDK 的相关文章

  • 在 Android Studio 中,为什么我必须在模拟器中单击“运行应用程序”两次才能启动应用程序?

    在 Android Studio 中 当我按播放按钮在 Android 模拟器上安装并运行应用程序时 大约 5 10 秒后 我在屏幕底部收到一条消息 显示 安装成功 但应用程序实际上并未运行在模拟器上 我必须再次按下播放按钮 这是非常令人沮
  • CardView 圆角获得意想不到的白色

    When using rounded corner in CardView shows a white border in rounded area which is mostly visible in dark environment F
  • 无法获取log.d或输出Robolectrict + gradle

    有没有人能够将 System out 或 Log d 跟踪从 robolectric 测试输出到 gradle 控制台 我在用Robolectric Gradle 测试插件 https github com robolectric robo
  • std::unique_ptr 是否需要知道 T 的完整定义?

    我的标题中有一些代码 如下所示 include
  • android xamarin 中的 reCaptcha

    我想在 Xamarin android 应用程序中实现验证码 我抓住了这个在 Android 中集成 googles reCaptcha 验证 https www c sharpcorner com article how to integ
  • 为什么不继承 std::allocator

    我创建了自己的分配器 如下所示 template
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Android 模拟器插件无法初始化后端 EGL 显示

    我在 Cloudbees 上设置了 Jenkins 作业 并且可以在那里成功签出并编译我的 Android 项目 现在我想在 android 模拟器中运行一些 JUnit 测试并添加 Android 模拟器插件 我将 显示模拟器窗口 选项设
  • 如何使用 Cordova 获取当前安装的应用程序的版本?

    我已经找到了应用程序可用性插件 https github com ohh2ahh AppAvailability它主要检查用户是否在其设备上安装了某个应用程序 是否有可能获得应用程序的当前版本 开发者名称 重要 以及所有可能的信息 一般来说
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 在gradle插件中获取应用程序变体的包名称

    我正在构建一个 gradle 插件 为每个应用程序变体添加一个新任务 此新任务需要应用程序变体的包名称 这是我当前的代码 它停止使用最新版本的 android gradle 插件 private String getPackageName
  • 如何使用 IF 检查 TextView 可见性

    我有一个 onCheckedChangeListener 来根据选择的单选按钮显示文本视图 我有 1 个疑问和 1 个难题 想知道是否有人可以帮助我 问题 您能否将单选组默认检查值设置为 否 单选按钮 以便一开始就不会检查任何内容 问题 如
  • 如何使用InputConnectionWrapper?

    我有一个EditText 现在我想获取用户对此所做的所有更改EditText并在手动将它们插入之前使用它们EditText 我不希望用户直接更改中的文本EditText 这只能由我的代码完成 例如通过使用replace or setText
  • 在 android DatePickerDialog 中将语言设置为法语

    有什么办法可以让日期显示在DatePickerDialog用法语 我已经搜索过这个但没有找到结果 这是我的代码 Calendar c Calendar getInstance picker new DatePickerDialog Paym
  • Android Studio - Windows 7 上的 Android SDK 问题

    我对 Google i o 2013 上发布的最新开发工具 Android Studio 有疑问 我已经成功安装了该程序并且能够正常启动 我可以导入现有项目并对其进行编辑 但是 当我尝试单击 SDK 管理器图标或 AVD 管理器图标时 或者
  • 我的设备突然没有显示在“Android 设备选择器”中

    我正在使用我的三星 Galaxy3 设备来测试过去两个月的应用程序 它运行良好 但从今天早上开始 当我将设备连接到系统时 它突然没有显示在 Android 设备选择器 窗口中 我检查过 USB 调试模式仅在我的设备中处于选中状态 谁能猜出问
  • 如何根据 gradle 风格设置变量

    我想传递一个变量test我为每种风格设置了不同的值作为 NDK 的定义 但出于某种原因 他总是忽略了最后味道的价值 这是 build gradle apply plugin com android library def test andr
  • Android 套接字和 asynctask

    我即将开始制作一个应该充当 tcp 聊天客户端的应用程序 我一直在阅读和阅读 我得出的结论是最好 如果不需要 将我的套接字和异步任务中的阅读器 问题是我不确定从哪里开始 因为我是 Android 新手 这至少对我来说是一项艰巨的任务 但据我
  • 如何确定对手机号码的呼叫是本地呼叫还是 STD 或 ISD

    我正在为 Android 开发某种应用程序 但不知道如何获取被叫号码是本地或 STD 的号码的数据 即手机号码检查器等应用程序从哪里获取数据 注意 我说的是手机号码 而不是固定电话 固定电话号码 你得到的数字是字符串类型 因此 您可以获取号
  • 将 Intent 包装在 LabeledIntent 中以用于显示目的

    要求 我的应用程序中有一个 共享 按钮 我需要通过 Facebook 分享 我需要选择是否安装原生 Facebook 应用程序 我们的决定是 如果未安装该应用程序 则将用户发送到 facebook com 进行分享 当前状态 我可以检测何时

随机推荐

  • 在数据库中存储条件逻辑表达式/规则

    如何使用 RDBMS 存储逻辑表达式 我标记对象并希望能够基于这些标记构建事实陈述 这些可能被视为虚拟标签 Tags new for sale used offer Rule second hand goods new or used an
  • 限制 TinyMCE 编辑器中的键盘快捷键

    试图找到在 TinyMCE 编辑器的 jQuery 版本中禁用单个键盘快捷键的位置 目前允许的快捷方式列表是 ctrl z Undo ctrl y Redo ctrl b Bold ctrl i Italic ctrl u Underlin
  • 如何将 Visual Studio 中的结构打包为包含 uint32_t 的 24 位?

    我正在尝试将现有应用程序从 32 位 ARM 微控制器移植到桌面平台 例如 Microsoft Windows GCC 在 ARM 上使用 我能够使用 32 位 MinGW 编译器在 Windows 上成功编译该应用程序 但是我使用 Mic
  • 如何让内部控件不覆盖主控件的事件?

    我有一个UserControl其中包含一些内部控件 像这样的东西 现在当我在我的项目中使用它时 我想要every如果单击 我的控件点会引发相同的单击事件 就像其他控件一样 但问题是 我的处理程序在另一个项目中 仅当我单击背景上的某个位置 而
  • AWS:找不到 iam 的实例元数据

    我正在尝试在我的 ec2 实例上设置 elasticsearch s3 快照 它失败并出现以下错误 nested NotSerializableExceptionWrapper sdk client exception The reques
  • 如何同时远程连接到多个 Glassfish 4+ 实例?

    我正在寻找一种从基于 Swing 的独立客户端 JDK7 SE 同时连接到 Glassfish 4 JDK7 EE 的多个实例的方法 我通过以下方式成功连接到单个实例 这就是初始上下文的构造 private void connect Str
  • 我可以检查安装的 Indy 版本吗?

    我需要使用最新的 Indy 组件库版本 我可以通过某些源代码命令或任何其他技巧来获取库版本 以确保我使用正确的库 我知道我正在使用indy 160 bpl 这是我的 Delphi XE2 将鼠标移动到组件栏上时所说的内容 我从中获取的最新
  • Spring事务中是否需要异常处理?

    我对事务的异常处理有疑问 为了清楚地说明我的问题 我想展示我的配置
  • fn 和 fn* 有什么区别?

    在 Clojure 中 fn 和 fn 有什么区别 当我在语法中引用使用 宏创建的函数时 我看到 fn 例如 在 REPL 中 user gt inc fn p1 342 343 auto clojure core inc p1 342 3
  • JavaFX 滚动表更新性能随着时间的推移而降低

    我有一个 TableView 显示最后 N 个项目 顶部的新项目 从底部删除项目等 似乎发生的情况是 CPU 负载随着时间的推移而增加 导致同一台计算机上的其他 X 应用程序变得缓慢 平台详细信息 Redhat 6 7 32 位 Java
  • 不同长度的时间序列数据的聚类

    我有不同系列长度的时间序列数据 我想根据 DTW 距离进行聚类 但找不到与之相关的 ant 库 sklearn给出直接错误 而 tslearn kmeans 给出错误答案 我的问题是如果我用零填充它就可以解决 但我不确定这在聚类时填充时间序
  • `git svn rebase` 与 `git rebase trunk`

    我正在开发一个使用 subversion 作为存储库的项目 因为我需要进行一些还无法发送到 svn 服务器的更改 所以我开始使用git svn这样我就可以进行本地签到 我的设置如下所示 分支机构 trunk 跟踪 svn trunk mas
  • Java 8 升级后无法获取数据库连接

    我最近将一个应用程序从 java 1 7 升级到 1 8 其余库版本保持不变 升级后我收到以下错误 DEBUG 2015 11 12 09 55 12 BasicResourcePool An exception occurred whil
  • Cassandra - 有没有办法限制异步查询的数量?

    我想知道是否有办法限制 cassandra java 驱动程序同时执行的查询数量 目前 我执行了很多查询 如下所示 PreparedStatement stmt session prepare SELECT FROM users WHERE
  • log4j2 在自定义 Appender 中将 printObject 设置为 true

    HERE https logging apache org log4j 2 x manual extending html它说 如果 toString 方法 附加程序应将 printObject 指定为 true 呈现传递给 Appende
  • OpenLayers 中的复合(complex)功能

    我在玩了一下 OpenLayers 想知道是否有一种方法可以创建自定义 功能 我想要完成的是一个具有多个部分的功能 或者是否有一种方法可以将多个功能 绑定 在一起 我想要实现的目标是 我想在地图上的某个位置显示各种数量的数据 并且我想将其包
  • Chrome 扩展:提交后修改 facebook-chat 中的消息文本

    我正在尝试创建一个 Chrome 扩展程序 当用户在聊天框中按 Enter 键时 该扩展程序会修改提交的消息 文本区域的 HTML 代码
  • Rails 测试(MiniTest)中分配方法的目的是什么?

    用于自动生成的测试 test should create item do login user assert difference Item count do post create item creator item creator ti
  • 如何在for_each方法中使用自己类的函数?

    假设我有这个类 继承自 std Vector 这只是一个例子 include
  • Android Studio 14 原生开发 + CrystaX NDK

    我正在尝试将一个巨大的跨平台 C 11 iOS Android 应用程序项目迁移到 Android Studio 14 我使用 CrystaX NDK 进行 boost 和 C 14 他们网站的博客上有官方 Android Studio C