Using libpd in Android Studio
Asked Answered
N

5

6

So I've got the git repo from https://github.com/libpd/pd-for-android and created a new blank project in Android Studio for my "AmazingSynthesizer".

I used the "Import Module" wizard to import PdCore and AndroidMidi. Then, right clicked on "app" to view my "Module Settings". Under dependencies I've added PdCore as a module dependency. Also, I added AndroidMidi as a module dependency for "PdCore".

So far, that seemed right to my. My app's build.gradle includes the libraries and I can import PdDispatcher in my MainActivity. The problem is, that it still seems to miss the native libraries (I think!).

The very basic example code from the official libpd book (Making Musical Apps by Peter Brinkmann)

PdAudio.initAudio(sampleRate, 0, 2, 8, true);

fails miserably

java.lang.UnsatisfiedLinkError: Couldn't load pd from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.app.amazingsynthesizer-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.app.amazingsynthesizer-1, /vendor/lib, /system/lib]]]: findLibrary returned null
        at java.lang.Runtime.loadLibrary(Runtime.java:358)
        at java.lang.System.loadLibrary(System.java:526)
        at org.puredata.core.PdBase.<clinit>(PdBase.java:55)
        at org.puredata.android.io.PdAudio.startAudio(PdAudio.java:86)
        at com.app.amazingsynthesizer.MainActivity.onResume(MainActivity.java:62)
        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1192)
        at android.app.Activity.performResume(Activity.java:5310)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2764)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2803)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2238)
        at android.app.ActivityThread.access$800(ActivityThread.java:135)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5001)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
        at dalvik.system.NativeStart.main(Native Method)
Nunuance answered 25/8, 2014 at 18:0 Comment(0)
M
7

[Updated 1/17/2016]

Now that the pd-for-android library artifact has been published to jCenter, the simplest solution got even simpler: no clones, no imports; just edit your project's build.gradle file and add a compile dependency on org.puredata.android:pd-core:1.0.0.

See pd-for-android's updated README for help.

Original accepted answer:

The simplest way to get up and running is to copy the prebuilt .so files to:

AmazingSynthesizer/src/main/jniLibs

You'll need libpd.so and libpdnativeopensl.so for the architectures that you are targeting, for example:

AmazingSynthesizer/src/main/jniLibs/armeabi/libpd.so AmazingSynthesizer/src/main/jniLibs/armeabi/libpdnativeopensl.so

Mcmullen answered 4/1, 2015 at 21:58 Comment(0)
N
7

[Updated on 03.07.2016]

Along with the new circumstances given by the pd-for-android project update, I updated my blog posts as well. Take a look here:

Blog post: http://www.journal.deviantdev.com/pure-data-for-android-jcenter-gradle-dependecy/

Sample Project: http://www.journal.deviantdev.com/sample-libpd-android-studio/


[Original Answer]

Basically this question is answered in different ways, but I want to add another answer for sharing my thoughts. I documented and updated different ways of how to run libpd with android studio. I will summarize the essential steps:

  1. Get Android Studio
  2. Download pd-for-android from GitHub
  3. Create a new project in Android Studio
  4. Import AndroidMidi as Module into Android Studio
  5. Import PDCore as Module into Android Studio
  6. Add a dependency for AndroidMidi to PDCore
  7. Add a dependency for PDCore to your App

Now you have two possible ways to get it working. You can build pd-for-android with the NDK and add the dependencies or you can add jniLibs.srcDirs = ['src', 'libs']" to the PdCore build.gradle. Normally you will choose the second way except you have to compile some externals not coming with pd-for-android by default.

Here you can find some posts, providing more details and a sample project for Android Studio:

Good luck!

Neaten answered 28/3, 2015 at 17:1 Comment(2)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.Bigamist
That sounds reasonable and I already added the essential parts for providing a valid answer. Thanks for your advice!Neaten
M
3

I had the same problem and to fix it I had to tell the android gradle plugin where the jni files (.so) are:

android {

// omitted ...

  sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src', 'jni/libpd/java']
        resources.srcDirs = ['src', 'jni/libpd/java']
        aidl.srcDirs = ['src', 'jni/libpd/java']
        renderscript.srcDirs = ['src', 'jni/libpd/java']

        // ** this is what was missing **
        jniLibs.srcDirs = ['src', 'libs']

        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }
  }
}

You can check out the complete build.gradle file in a fork I made of the original libpd-for-android repository. I'm using there a newer version of the Android gradle plugin and it works great with Android Studio:

https://github.com/tkirshboim/pd-for-android/

-- Update from 30.06.2015 --

My pd-for-android fork was extended by @github/joebowbeer so that the gradle support is improved and you can create an .aar file using gradle and the Android NDK. So it's no longer necessary to copy the the pd-for-android code + binaries when creating a new Android project that uses pure data. The pull request for this updated fork should be merged soon to the master branch. Until then you can clone this fork from here:

https://github.com/joebowbeer/pd-for-android/tree/gradle_mods

I don't have enough reputation yet to comment on the answer by @sdaau to this question, it is however incorrect that Android Studio will not support NDK. NDK is supported in Android Studio from version 1.3 onwards. You can download it from here.

Mathison answered 31/1, 2015 at 18:50 Comment(0)
F
2

I've had the same problem. To make it short you have to instruct gradle to include *.so files as dependency in your project (it doesn't happen automatically)

I was able to solve my problem looking at this answer: https://stackoverflow.com/a/17974618 I hope it helps.

EDIT: I forgot: I also had to compile the PdCore project with ndk-build. If you get an error regarding files in the folder opensl_stream, make sure you got them correctly since they are a link to another git repo (i just copied them manually to my folder... not the best solution but it worked)

Cheers

Fahlband answered 7/9, 2014 at 21:18 Comment(1)
Hi Enrico, and thanks for this answer. Can u give me some more advice what i need to do? Maybe you can share your build.gradle file with the *.so file dependencies?Neaten
T
0

Thanks to the answer by @kirsh300, I got to a newer git repo of libpd for Android, but still the build process wasn't trivial for me. Since this is likely to remain complicated (see Android Studio "Current NDK support is deprecated"), below is a bash script of what I had to do, in order to get the libpd for Android to build on my old Linux box.

First problem is that my installation is in non-standard directories. Then, I've used the SDK from an old(er) Android Studio Bundle for Linux, 135.1078000 (from 20140321); this one by default goes max to API 19; and doesn't install other APIs by default. However, the current revision of libpd refers to both API 17, and API 21. API 17 I installed manually by calling the command $ANDROID_HOME/tools/android, which is the Android SDK Manager - while API 21 I downgraded to 19 by patching files in the script below. So, my Android SDK manager shows for installed:

sdk.png

Second problem is that with this SDK, there comes a gradlew which is version 1.10 - while the current version of gradlew checked in the libpd repo is 2.4 (upon first call, it will attempt to download the correct gradle version). The thing to remember is, not to call the gradlew from the SDK - because that one doesn't understand, say, android.ndkDirectory ("Could not find property 'ndkDirectory' on com.android.build.gradle.LibraryExtension_Decorated@3e3c83"), or variant.outputs.each ("Could not find property 'outputs' on com.android.build.gradle.internal.api.LibraryVariantImpl_Decorated@97447e") constructs in build.gradle scripts - thus gradlew 2.4 from the repo should be used (hence the relative path in the script).

Here is the script:

#!/usr/bin/env bash

# wget http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-linux.tgz
# wget http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86.bin
# unpack downloads - and modify these to your actual absolute paths (also for JAVA_HOME below):
ADTSDK=/path/to/adt-bundle-linux-x86-20140321/sdk
ADNDK=/path/to/android-ndk-r10e
# these seem to not really matter? nvm, keep:
export ANDROID_HOME=$ADTSDK
export ANDROID_NDK_HOME=$ADNDK

set -x

# only run if the subdirectory pd-for-android not created yet:
if [ ! -d "pd-for-android" ]; then
  #git clone https://github.com/libpd/pd-for-android.git # no, OLD!
  git clone https://github.com/tkirshboim/pd-for-android.git
  cd pd-for-android
  # checkout specific version to make sure this test works when the repo changes:
  git checkout -f c5ea734c5aac7f2d37141e287bd0102706d54e55
  # create root/top-level local.properties, esp. for sdk.dir:
  echo "ndk.dir=$ADNDK" > local.properties 
  echo "sdk.dir=$ADTSDK" >> local.properties
  # downgrade API version:
  sed -i 's_compileSdkVersion 21_compileSdkVersion 19 //21_' PdTest/build.gradle
  sed -i 's_buildToolsVersion "21.1.2"_buildToolsVersion "19.1" //"21.1.2"_' PdTest/build.gradle
  sed -i "s_targetSdkVersion 21_targetSdkVersion 19 //21_" PdTest/build.gradle
  sed -i 's_compileSdkVersion 21_compileSdkVersion 19 //21_' CircleOfFifths/build.gradle
  sed -i 's_buildToolsVersion "21.1.2"_buildToolsVersion "19.1" //"21.1.2"_' CircleOfFifths/build.gradle
  sed -i "s_targetSdkVersion 21_targetSdkVersion 19 //21_" CircleOfFifths/build.gradle
  sed -i 's_compileSdkVersion 21_compileSdkVersion 19 //21_' ScenePlayer/build.gradle
  sed -i 's_buildToolsVersion "21.1.2"_buildToolsVersion "19.1" //"21.1.2"_' ScenePlayer/build.gradle
  sed -i "s_targetSdkVersion 21_targetSdkVersion 19 //21_" ScenePlayer/build.gradle
  sed -i 's_compileSdkVersion 21_compileSdkVersion 19 //21_' Voice-O-Rama/build.gradle
  sed -i 's_buildToolsVersion "21.1.2"_buildToolsVersion "19.1" //"21.1.2"_' Voice-O-Rama/build.gradle
  sed -i "s_targetSdkVersion 21_targetSdkVersion 19 //21_" Voice-O-Rama/build.gradle
  cd PdCore
  sed -i 's_compileSdkVersion 21_compileSdkVersion 19 //21_' build.gradle
  sed -i "s_buildToolsVersion '21.1.2'_buildToolsVersion '19.1' //'21.1.2'_" build.gradle # The SDK Build Tools revision (19.0.3) is too low for project ':PdCore'. Minimum required is 19.1.0 - install via Android SDK manager
  sed -i "s_targetSdkVersion 21_targetSdkVersion 19 //21_" build.gradle
  # check if tasks pass:
  ../gradlew tasks || { echo 'tasks failed' ; exit 1; } # pulls gradle-2.4-all.zip;
  # build:
  # must specify JAVA_HOME here, else "FAILURE: Build failed ... Could not find tools.jar"
  JAVA_HOME=/path/to/jdk1.6.0_45 ../gradlew assembleRelease 
  cd ../..
fi
Tweet answered 24/7, 2015 at 17:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.