1

I've successfully compiled the SoundTouch library and copied the resulting files into my project's libs folder.

library

within each one of this folders there is a libsoundtouch.so file.

in my project's jni folder I have the following files:

  • Android.mk
  • Application.mk
  • soundtouch-jni.cpp

my Android.mk looks like this:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# *** Remember: Change -O0 into -O2 in add-applications.mk ***

LOCAL_MODULE    := soundtouch
LOCAL_SRC_FILES := soundtouch-jni.cpp ../../SoundTouch/AAFilter.cpp  ../../SoundTouch/FIFOSampleBuffer.cpp \
                ../../SoundTouch/FIRFilter.cpp ../../SoundTouch/cpu_detect_x86.cpp \
                ../../SoundTouch/sse_optimized.cpp ../../SoundStretch/WavFile.cpp \
                ../../SoundTouch/RateTransposer.cpp ../../SoundTouch/SoundTouch.cpp \
                ../../SoundTouch/InterpolateCubic.cpp ../../SoundTouch/InterpolateLinear.cpp \
                ../../SoundTouch/InterpolateShannon.cpp ../../SoundTouch/TDStretch.cpp \
                ../../SoundTouch/BPMDetect.cpp ../../SoundTouch/PeakFinder.cpp 

# for native audio
LOCAL_SHARED_LIBRARIES += -lgcc 
# --whole-archive -lgcc 
# for logging
LOCAL_LDLIBS    += -llog
# for native asset manager
#LOCAL_LDLIBS    += -landroid

# Custom Flags: 
# -fvisibility=hidden : don't export all symbols
LOCAL_CFLAGS += -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections

# OpenMP mode : enable these flags to enable using OpenMP for parallel computation 
#LOCAL_CFLAGS += -fopenmp
#LOCAL_LDFLAGS += -fopenmp


# Use ARM instruction set instead of Thumb for improved calculation performance in ARM CPUs 
LOCAL_ARM_MODE := arm

include $(BUILD_SHARED_LIBRARY)

and this is my module build.gradle file:

apply plugin: 'com.android.application'

android {
    signingConfigs {
        dev_key {
            keyAlias '#########'
            keyPassword '########'
            storeFile file('/Users/daniele/Desktop/Chords/########')
            storePassword '#######'
        }
    }
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "com.dancam.chords"
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 16
        versionName "2.1"
        signingConfig ##########
        multiDexEnabled true
    }
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }

    dataBinding {
        enabled = true
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

I import a native function:

public final class SoundTouch {
    public native final static String getVersionString();

// Load the native library upon startup
static
{
    System.loadLibrary("soundtouch");
}
}

This is my soundtouch-jni.cpp file:

#include <jni.h>
#include <android/log.h>
#include <stdexcept>
#include <string>

using namespace std;

#include "../../../include/SoundTouch.h"
#include "../source/SoundStretch/WavFile.h"

#define LOGV(...)   __android_log_print((int)ANDROID_LOG_INFO, "SOUNDTOUCH", __VA_ARGS__)
//#define LOGV(...)


// String for keeping possible c++ exception error messages. Notice that this isn't
// thread-safe but it's expected that exceptions are special situations that won't
// occur in several threads in parallel.
static string _errMsg = "";


#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#define BUFF_SIZE 4096


using namespace soundtouch;


// Set error message to return
static void _setErrmsg(const char *msg)
{
    _errMsg = msg;
}


#ifdef _OPENMP

#include <pthread.h>
extern pthread_key_t gomp_tls_key;
static void * _p_gomp_tls = NULL;

/// Function to initialize threading for OpenMP.
///
/// This is a workaround for bug in Android NDK v10 regarding OpenMP: OpenMP works only if
/// called from the Android App main thread because in the main thread the gomp_tls storage is
/// properly set, however, Android does not properly initialize gomp_tls storage for other threads.
/// Thus if OpenMP routines are invoked from some other thread than the main thread,
/// the OpenMP routine will crash the application due to NULL pointer access on uninitialized storage.
///
/// This workaround stores the gomp_tls storage from main thread, and copies to other threads.
/// In order this to work, the Application main thread needws to call at least "getVersionString"
/// routine.
static int _init_threading(bool warn)
{
    void *ptr = pthread_getspecific(gomp_tls_key);
    LOGV("JNI thread-specific TLS storage %ld", (long)ptr);
    if (ptr == NULL)
    {
        LOGV("JNI set missing TLS storage to %ld", (long)_p_gomp_tls);
        pthread_setspecific(gomp_tls_key, _p_gomp_tls);
    }
    else
    {
        LOGV("JNI store this TLS storage");
        _p_gomp_tls = ptr;
    }
    // Where critical, show warning if storage still not properly initialized
    if ((warn) && (_p_gomp_tls == NULL))
    {
        _setErrmsg("Error - OpenMP threading not properly initialized: Call SoundTouch.getVersionString() from the App main thread!");
        return -1;
    }
    return 0;
}

#else
static int _init_threading(bool warn)
{
    // do nothing if not OpenMP build
    return 0;
}
#endif


// Processes the sound file
static void _processFile(SoundTouch *pSoundTouch, const char *inFileName, const char *outFileName)
{
    int nSamples;
    int nChannels;
    int buffSizeSamples;
    SAMPLETYPE sampleBuffer[BUFF_SIZE];

    // open input file
    WavInFile inFile(inFileName);
    int sampleRate = inFile.getSampleRate();
    int bits = inFile.getNumBits();
    nChannels = inFile.getNumChannels();

    // create output file
    WavOutFile outFile(outFileName, sampleRate, bits, nChannels);

    pSoundTouch->setSampleRate(sampleRate);
    pSoundTouch->setChannels(nChannels);

    assert(nChannels > 0);
    buffSizeSamples = BUFF_SIZE / nChannels;

    // Process samples read from the input file
    while (inFile.eof() == 0)
    {
        int num;

        // Read a chunk of samples from the input file
        num = inFile.read(sampleBuffer, BUFF_SIZE);
        nSamples = num / nChannels;

        // Feed the samples into SoundTouch processor
        pSoundTouch->putSamples(sampleBuffer, nSamples);

        // Read ready samples from SoundTouch processor & write them output file.
        // NOTES:
        // - 'receiveSamples' doesn't necessarily return any samples at all
        //   during some rounds!
        // - On the other hand, during some round 'receiveSamples' may have more
        //   ready samples than would fit into 'sampleBuffer', and for this reason
        //   the 'receiveSamples' call is iterated for as many times as it
        //   outputs samples.
        do
        {
            nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
            outFile.write(sampleBuffer, nSamples * nChannels);
        } while (nSamples != 0);
    }

    // Now the input file is processed, yet 'flush' few last samples that are
    // hiding in the SoundTouch's internal processing pipeline.
    pSoundTouch->flush();
    do
    {
        nSamples = pSoundTouch->receiveSamples(sampleBuffer, buffSizeSamples);
        outFile.write(sampleBuffer, nSamples * nChannels);
    } while (nSamples != 0);
}



extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionString(JNIEnv *env, jobject thiz)
{
    const char *verStr;

    LOGV("JNI call SoundTouch.getVersionString");

    // Call example SoundTouch routine
    verStr = SoundTouch::getVersionString();

    /// gomp_tls storage bug workaround - see comments in _init_threading() function!
    _init_threading(false);

    int threads = 0;
    #pragma omp parallel
    {
        #pragma omp atomic
        threads ++;
    }
    LOGV("JNI thread count %d", threads);

    // return version as string
    return env->NewStringUTF(verStr);
}



extern "C" DLL_PUBLIC jlong Java_net_surina_soundtouch_SoundTouch_newInstance(JNIEnv *env, jobject thiz)
{
    return (jlong)(new SoundTouch());
}


extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_deleteInstance(JNIEnv *env, jobject thiz, jlong handle)
{
    SoundTouch *ptr = (SoundTouch*)handle;
    delete ptr;
}


extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setTempo(JNIEnv *env, jobject thiz, jlong handle, jfloat tempo)
{
    SoundTouch *ptr = (SoundTouch*)handle;
    ptr->setTempo(tempo);
}


extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setPitchSemiTones(JNIEnv *env, jobject thiz, jlong handle, jfloat pitch)
{
    SoundTouch *ptr = (SoundTouch*)handle;
    ptr->setPitchSemiTones(pitch);
}


extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setSpeed(JNIEnv *env, jobject thiz, jlong handle, jfloat speed)
{
    SoundTouch *ptr = (SoundTouch*)handle;
    ptr->setRate(speed);
}


extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getErrorString(JNIEnv *env, jobject thiz)
{
    jstring result = env->NewStringUTF(_errMsg.c_str());
    _errMsg.clear();

    return result;
}


extern "C" DLL_PUBLIC int Java_net_surina_soundtouch_SoundTouch_processFile(JNIEnv *env, jobject thiz, jlong handle, jstring jinputFile, jstring joutputFile)
{
    SoundTouch *ptr = (SoundTouch*)handle;

    const char *inputFile = env->GetStringUTFChars(jinputFile, 0);
    const char *outputFile = env->GetStringUTFChars(joutputFile, 0);

    LOGV("JNI process file %s", inputFile);

    /// gomp_tls storage bug workaround - see comments in _init_threading() function!
    if (_init_threading(true)) return -1;

    try
    {
        _processFile(ptr, inputFile, outputFile);
    }
    catch (const runtime_error &e)
    {
        const char *err = e.what();
        // An exception occurred during processing, return the error message
        LOGV("JNI exception in SoundTouch::processFile: %s", err);
        _setErrmsg(err);
        return -1;
    }


    env->ReleaseStringUTFChars(jinputFile, inputFile);
    env->ReleaseStringUTFChars(joutputFile, outputFile);

    return 0;
}

EDIT:

After doing what Alex Cohn suggested, I ended up with the following errors:

Build command failed.

Error while executing process /Users/daniele/Library/Android/sdk/ndk-bundle/ndk-build with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Android.mk NDK_APPLICATION_MK=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=0 APP_PLATFORM=android-21 NDK_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj NDK_LIBS_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib/armeabi-v7a/*
rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib/armeabi-v7a/gdbserver
rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib/armeabi-v7a/gdb.setup
mkdir -p /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/soundtouch
echo [armeabi-v7a] "Compile++ arm  ": "soundtouch <= soundtouch-jni.cpp"
/Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ -MMD -MP -MF /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o.d -gcc-toolchain /Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 -fpic -ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -fno-integrated-as -g -target armv7-none-linux-androideabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-exceptions -fno-rtti -marm -O2 -DNDEBUG  -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl/stlport/stlport -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl//gabi++/include -I/Users/daniele/Developer/AndroidProjects/Chords2/app/jni -DANDROID -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections -Wa,--noexecstack -Wformat -Werror=format-security  -frtti   -fexceptions  -isystem /Users/daniele/Library/Android/sdk/ndk-mbundake: *** No rule to make target `/Users/daniele/Delveeloper/platforms/android-/AndroidProjects/Chords2/app/jni/../../SoundTouch/AAFilter.cpp', needed by `/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermedi2ates/ndkBuild/1/arch-arm/usr/include -c release/obj/local/armeabi-v7a/objs/soun /Users/dtdaniele/Douch/__/__/SoeveloundTouch/AAFpilter.o'.  Stop.
er/AndroidProjects/Chords2/app/jni/soundtouch-jni.cpp -o /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o 

Build command failed.

Error while executing process /Users/daniele/Library/Android/sdk/ndk-bundle/ndk-build with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Android.mk NDK_APPLICATION_MK=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=1 APP_PLATFORM=android-21 NDK_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj NDK_LIBS_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/*
rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdbserver
rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup
mkdir -p /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a
echo [armeabi-v7a] "Gdbserver      ": "[arm-linux-androideabi] /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdbserver"
install -p /Users/daniele/Library/Android/sdk/ndk-bundle/prebuilt/android-arm/gdbserver/gdbserver /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdbserver
echo [armeabi-v7a] "Gdbsetup       ": "/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup"
echo "set solib-search-path /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a" > /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup
echo "directory /Users/daniele/Library/Android/sdk/ndk-bundle/platforms/android-21/arch-arm/usr/include /Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl/stlport/stlport /Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl//gabi++/include /Users/daniele/Developer/AndroidProjects/Chords2/app/jni" >> /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup
mkdir -p /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs/soundtouch
echo [armeabi-v7a] "Compile++ arm  ": "soundtouch <= soundtouch-jni.cpp"
/Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ -MMD -MP -MF /Users/daniele/Developer/Androidmake: *** No rule to make target `/Users/daniele/Developer/AndroidProjects/Chords2/app/jniPro/../../SojeundTouch/AAFilter.cpp'c, ts/nCheeded by `o/Usrdsers/daniele/Develo2/apper/AndroidpProjects/Chords2/app/build/intermediates/ndkBuild//bdebug/obj/local/uiarmeabi-v7a/objs/soundtouch/__/__/SoundldTouch/AAFilter.o'.  Stop.
/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o.d -gcc-toolchain /Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 -fpic -ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -fno-integrated-as -g -target armv7-none-linux-androideabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-exceptions -fno-rtti -marm -O2 -DNDEBUG  -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl/stlport/stlport -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl//gabi++/include -I/Users/daniele/Developer/AndroidProjects/Chords2/app/jni -DANDROID -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections -Wa,--noexecstack -Wformat -Werror=format-security  -frtti   -fexceptions  -isystem /Users/daniele/Library/Android/sdk/ndk-bundle/platforms/android-21/arch-arm/usr/include -c  /Users/daniele/Developer/AndroidProjects/Chords2/app/jni/soundtouch-jni.cpp -o /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o

Please notice: I compiled the Soundtouch Library using ndk-build on Ubuntu Linux, then copied it over to macOS where I normally work

Any clue on how to fix this?

Daniele
  • 4,163
  • 7
  • 44
  • 95
  • Can you include the header file that exports the native C function please. And the error log (logcat) around the error (it has extra messages that will help diagnose the problem) – Richard Critten Sep 05 '17 at 17:15
  • @RichardCritten you mean the soundtouuch-jni.cpp? – Daniele Sep 05 '17 at 17:17
  • I want to see the full C declaration of `getVersionString` – Richard Critten Sep 05 '17 at 17:18
  • I don't know exactly where to find the function getVersionString. Anyway all functions are giving the error – Daniele Sep 05 '17 at 17:24
  • Most like the compiler/linker have exported the symbols in libsoundtouch with mangled names. Use nm to see what the names of the functions exported by the module actually are. Notoriously frustrating aspect of JNI. You can probably have non-mangled names exported by using extern "C" {} – JJF Sep 05 '17 at 17:31
  • @JJF I'll try to rebuild it – Daniele Sep 05 '17 at 17:36
  • I think you've got more work to do. From what I can tell that library you're trying to use does not support the C calling convention (which is what JNI requires) so you're going to have to write a bridge in C that the JVM calls which in turn calls the CPP code. See https://github.com/bytedeco/javacpp to see what you're up against. – JJF Sep 05 '17 at 17:41
  • @JJF would you please have a look at the source code? there is an android example there that's working. Maybe you can get some more info from there. I compiled and built it following the guide in the README. Here is the source code link: http://www.surina.net/soundtouch/sourcecode.html – Daniele Sep 05 '17 at 17:55
  • 2
    What package is your SoundTouch class in? That sample would require SoundTouch class to be in net.surina.soundtouch package. The package name is part of the JNI function name. – JJF Sep 05 '17 at 18:17
  • 1
    And that soundtouch-jni.cpp does provide unmangled names for you to use. e.g. extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionString(JNIEnv *env, jobject thiz); Note the package name included in the function name. – JJF Sep 05 '17 at 18:23
  • @JFF I see it's true I got al unmangled function names. Is it because of an error during compile? – Daniele Sep 06 '17 at 09:11
  • @JFF I added my soundtouuch-jni.cpp in the question for you to have a look – Daniele Sep 06 '17 at 09:21
  • Woould the one who downvoted mind to explain why? – Daniele Sep 06 '17 at 14:17
  • There are tons of answers that address the 'Cannot resolve corresponding JNI function' error message. Please consider this one as well: https://stackoverflow.com/a/44225181/192373. TL;NR: Android Studio will not look into your **.so** files for the native methods, it can find them only if you use the integrated externalNativeBuild. – Alex Cohn Sep 06 '17 at 19:58
  • 1
    @AlexCohn I see, so that error should be an Android Studio related thing and should be all ok once I run the apk? Should I just ignore it? Please tell me more about this `externalNativeBuild` stuff, How do I implement it? Will it allow Android Studio to resolve those jni functions? – Daniele Sep 07 '17 at 06:18
  • 1
    @AlexCohn As you suggested here: https://stackoverflow.com/a/44225181/6427630 I used the `@SuppressWarnings()` to build the apk but when I try to run it I get `java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.dancam.chords-1/base.apk"],nativeLibraryDirectories=[/data/app/com.dancam.chords-1/lib/x86, /system/lib, /vendor/lib]]] couldn't find "libsoundtouch.so"` on the `System.loadLibrary("soundtouch")` line. Any Idea why this happens? The .so fileas are inside my `app/jniLibs` folder – Daniele Sep 07 '17 at 07:15
  • Yes, I believe that switching to `externalNativeBuild` is the best way fix your problems. – Alex Cohn Sep 07 '17 at 09:17
  • Per your screenshot, the .so files are in `app/libs` folder. You can configure gradle to pick them up from there, but it is much healthier to enable the integrated build. – Alex Cohn Sep 07 '17 at 09:31
  • Your question is very confusing. Your logs suggest a Mac, but the screenshot is from Linux. The logs look like they come from more than one command interlaced. And the `-B -n` arguments are very strange. How did you obtain these logs? – Alex Cohn Sep 08 '17 at 21:39
  • @AlexCohn you are right sorry for not saying that. I actually compiled the library on Ubuntu Linux, and then copied on my Mac where I normally work – Daniele Sep 09 '17 at 07:49

2 Answers2

2

You should setup your gradle project to build the C++ library.

Please add to your build.gradle the following line (inside the android {} block):

externalNativeBuild.ndkBuild.path = 'jni/Android.mk'

(assuming paths ~/AndroidStudioProjects/Chords2/app/build.gradle and ~/AndroidStudioProjects/Chords2/app/jni/Android.mk).

To reduce compilation time and APK size, you can filter out the ABIs that you don't use, at least while debugging:

ndk { abiFilters 'armeabi-v7a' }

This line goes inside the defaultConfig {} block.

At any rate, after the APK is ready, you can use Build/Analyze APK from Android Studio's menu and check that all .so files are packed into it.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Thanks, will try this out in a moment – Daniele Sep 07 '17 at 10:25
  • Please have a look at the edited question. I'm facing those issues after doing what you told me. Do you know how to address them? – Daniele Sep 07 '17 at 10:40
  • **first rule:** never use spaces in path when you deal with Android NDK (and SDK). – Alex Cohn Sep 07 '17 at 11:37
  • Thanks, changing that directory name, brought me a bit further. At least now starts removing the `armeabi-v7a` stuff. Still hanging up somewhere though. Please check the updated question, with the new log – Daniele Sep 07 '17 at 14:31
  • Try to remove the **build** directory and rebuild everything. – Alex Cohn Sep 07 '17 at 15:01
  • I tried to understand what error messages you pasted, but they make no sense. I don't know where `-B -n` come for the integrated **ndk-build** command. – Alex Cohn Sep 07 '17 at 18:14
  • I'm trying to update the NDK to the latest version. If this does not fix it, I'll probably start a bounty, I don't really know what to do anymore. I also checked a bunch of guides on how to import `.so` libraries and it seamed pretty easy. Don't know why I'm getting all this errors – Daniele Sep 08 '17 at 09:55
  • After updating the NDK to `r15c` I got another, new error log for you to check out :) – Daniele Sep 08 '17 at 10:39
2

I see you have problems building libsoundtouch.so in Android Studio. This happens, e.g. when the build scripts of a third-part library require special environment. E.g. the only supported way to build webrtc for Android is on 64-bit Linux.

In this case, you can use the prebuilt libraries. Put them in a jniLibs folder under your project (jniLibs/armeabi-v7a/libsoundtouch.so etc.), or set a custom folder for jniLibs in build.gradle (in android {} block):

sourceSets.main.jniLibs.srcDir 'libs'

You should not use externalNativeBuild.ndkBuild.path together with this.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 1
    Thanks again Alex, but what are the prebuilt libraries? The ones I'm using are the ones I built on 64-bit Linux – Daniele Sep 09 '17 at 11:36
  • Yes, the ones you copied from the Linux build machine – Alex Cohn Sep 09 '17 at 12:45
  • The gradle build finally succeded, thanks for that. I'm havingproblems when calling the library related methods though. Please check out the edited question – Daniele Sep 10 '17 at 14:05
  • Please open a separate question, it's free on this site. These questions are intended to help others, too. By changing the story again and again, you make it very hard to follow. – Alex Cohn Sep 10 '17 at 15:13