Does DL4J support running on Android now?

I follow the instructions to configure on Android, but the following error will be reported:
04-13 19:49:33.646 9206 9247 E AndroidRuntime: at android.os.Binder.execTransactInternal(Binder.java:1290)
04-13 19:49:33.646 9206 9247 E AndroidRuntime: at android.os.Binder.execTransact(Binder.java:1249)
04-13 19:49:33.646 9206 9247 E AndroidRuntime: Caused by: java.lang.RuntimeException: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: http://nd4j.org/getstarted.html
04-13 19:49:33.646 9206 9247 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5131)
04-13 19:49:33.646 9206 9247 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4j.(Nd4j.java:226)
04-13 19:49:33.646 9206 9247 E AndroidRuntime: … 10 more
04-13 19:49:33.646 9206 9247 E AndroidRuntime: Caused by: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: http://nd4j.org/getstarted.html
04-13 19:49:33.646 9206 9247 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4jBackend.load(Nd4jBackend.java:218)
04-13 19:49:33.646 9206 9247 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5128)
04-13 19:49:33.646 9206 9247 E AndroidRuntime: … 11 more
my Gradle file:

plugins {
    id 'com.android.application'
}

android {
    namespace 'com.dd.ai'
    compileSdk 33

    defaultConfig {
        applicationId "com.dd.ai"
        minSdk 33
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
    buildFeatures {
        viewBinding true
    }

    packagingOptions {
        exclude 'META-INF/native-image/**/**.json'
        exclude 'META-INF/native-image/*.json'
        pickFirst 'nd4j-native.properties'
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.8.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.navigation:navigation-fragment:2.5.3'
    implementation 'androidx.navigation:navigation-ui:2.5.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    // Room start
    def room_version = "2.5.1"
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
    // Room end

    // Tensorflow lite dependencies
    implementation 'org.tensorflow:tensorflow-lite:2.8.0'
    implementation 'org.tensorflow:tensorflow-lite-select-tf-ops:2.8.0'
    // tf end
    def dl4jVersion = '1.0.0-beta6'
    def openblasVersion = '0.3.19-1.5.7'
    def opencvVersion = '4.5.5-1.5.7'
    def leptonicaVersion = '1.82.0-1.5.7'
    implementation(group: 'org.deeplearning4j', name: 'deeplearning4j-core', version: dl4jVersion) {
        exclude group: 'org.bytedeco', module: 'opencv-platform'
        exclude group: 'org.bytedeco', module: 'leptonica-platform'
        exclude group: 'org.bytedeco', module: 'hdf5-platform'
        exclude group: 'org.nd4j', module: 'nd4j-base64'
        exclude group: 'org.nd4j', module: 'nd4j-api'
    }

    implementation  group: 'org.nd4j', name: 'nd4j-native', version: dl4jVersion
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion, classifier: "android-arm"
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion, classifier: "android-arm64"
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion, classifier: "android-x86"
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion, classifier: "android-x86_64"
    implementation  group: 'org.bytedeco', name: 'opencv', version: opencvVersion
    implementation  group: 'org.bytedeco', name: 'opencv', version: opencvVersion, classifier: "android-arm"
    implementation  group: 'org.bytedeco', name: 'opencv', version: opencvVersion, classifier: "android-arm64"
    implementation  group: 'org.bytedeco', name: 'opencv', version: opencvVersion, classifier: "android-x86"
    implementation  group: 'org.bytedeco', name: 'opencv', version: opencvVersion, classifier: "android-x86_64"
    implementation  group: 'org.bytedeco', name: 'leptonica', version: leptonicaVersion
    implementation  group: 'org.bytedeco', name: 'leptonica', version: leptonicaVersion, classifier: "android-arm"
    implementation  group: 'org.bytedeco', name: 'leptonica', version: leptonicaVersion, classifier: "android-arm64"
    implementation  group: 'org.bytedeco', name: 'leptonica', version: leptonicaVersion, classifier: "android-x86"
    implementation  group: 'org.bytedeco', name: 'leptonica', version: leptonicaVersion, classifier: "android-x86_64"

    annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.4'


    // xgboost dependency
//    implementation group: 'ml.dmlc', name: 'xgboost4j_2.12', version: '1.7.4'
//    implementation group: 'ml.dmlc', name: 'xgboost4j_${scala.binary.version}', version: '1.7.5'
//    implementation group: 'ml.dmlc', name: 'xgboost4j-spark_${scala.binary.version}', version: '1.7.5'
    implementation group: 'io.github.metarank', name: 'lightgbm4j', version: '3.3.2-5'
}

@Laurin123 yes it does. You’re using a few year old version though. Please update to the latest version.

I’m guessing you found the google search quickstart sorry we need to update that.

You can find forums posts on the topic though.

@Laurin123 use this:

  def dl4jVersion = '1.0.0-M2.1'
    def openblasVersion = '0.3.21-1.5.8'
 implementation  group: 'org.deeplearning4j', name: 'deeplearning4j-nn', version: dl4jVersion
   implementation  group: 'org.nd4j', name: 'nd4j-native', version: dl4jVersion
    implementation  group: 'org.nd4j', name: 'nd4j-native', version:  dl4jVersion, classifier: "android-arm64"

    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion, classifier: "android-arm64"
This should do it for the updated versions. Please again keep in mind that the classifier such as (android-arm64,android-arm,…) might be needed depending on your use case.

For testing on an emulator you may also need android-x86 for your local testing but not for the deployed version.

I’m not familiar with all the details but you should look in to something like this: 다중 APK 빌드  |  Android 개발자  |  Android Developers

This would allow you to set something up where you can split dependencies by platfom and reduce the overall size of the apk for each platform.

I modified it according to the way you changed it, but still reported an error:
04-13 20:29:14.205 17006 17047 E AndroidRuntime: at android.os.Binder.execTransact(Binder.java:1249)
04-13 20:29:14.205 17006 17047 E AndroidRuntime: Caused by: java.lang.RuntimeException: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: https://deeplearning4j.konduit.ai/nd4j/backend
04-13 20:29:14.205 17006 17047 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5066)
04-13 20:29:14.205 17006 17047 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4j.(Nd4j.java:284)
04-13 20:29:14.205 17006 17047 E AndroidRuntime: … 10 more
04-13 20:29:14.205 17006 17047 E AndroidRuntime: Caused by: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: https://deeplearning4j.konduit.ai/nd4j/backend
04-13 20:29:14.205 17006 17047 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4jBackend.load(Nd4jBackend.java:211)
04-13 20:29:14.205 17006 17047 E AndroidRuntime: at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5062)
04-13 20:29:14.205 17006 17047 E AndroidRuntime: … 11 more

It literally worked for this guy: Quickstart using GPS trajectories file from UCI

@Laurin123 could you post your full build.gradle?

This is my full build.gradle:

plugins {
    id 'com.android.application'
}

android {
    namespace 'com.dd.aiautobrt'
    compileSdk 33

    defaultConfig {
        applicationId "com.dd.aiautobrt"
        minSdk 33
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
    buildFeatures {
        viewBinding true
    }

    packagingOptions {
        exclude 'META-INF/native-image/**/**.json'
        exclude 'META-INF/native-image/*.json'
        pickFirst 'nd4j-native.properties'
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.8.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.navigation:navigation-fragment:2.5.3'
    implementation 'androidx.navigation:navigation-ui:2.5.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    // Room start
    def room_version = "2.5.1"
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
    // Room end

    // Tensorflow lite dependencies
    implementation 'org.tensorflow:tensorflow-lite:2.8.0'
    implementation 'org.tensorflow:tensorflow-lite-select-tf-ops:2.8.0'
    // tf end
    def dl4jVersion = '1.0.0-M2.1'
    def openblasVersion = '0.3.21-1.5.8'
    implementation  group: 'org.nd4j', name: 'nd4j-native', version: dl4jVersion
    implementation  group: 'org.nd4j', name: 'nd4j-native', version: dl4jVersion, classifier: "android-arm64"
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion
    implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion, classifier: "android-arm64"
    implementation  group: 'org.deeplearning4j', name: 'deeplearning4j-nn', version: dl4jVersion
}

@Laurin123 could you post the full stack trace? Your build.gradle looks correct. I’d be interested in knowing what your difference is vs @adonnini . @adonnini could you please let us know what your android version is?

Thanks!

Are these what you need? Need additional information?

04-14 11:05:56.706  7613  7635 I dd.aiautobrt: This is sticky GC, maxfree is 33554432 minfree is 2097152
04-14 11:05:56.718  7613  7644 W System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
04-14 11:05:56.718  7613  7644 W System.err: SLF4J: Defaulting to no-operation (NOP) logger implementation
04-14 11:05:56.718  7613  7644 W System.err: SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
04-14 11:05:56.730  7613  7644 E JavaBinder: *** Uncaught remote exception!  (Exceptions are not yet supported across processes.)
04-14 11:05:56.730  7613  7644 E JavaBinder: java.lang.ExceptionInInitializerError
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at org.nd4j.linalg.factory.Nd4j.create(Nd4j.java:3444)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at com.dd.aiautobrt.algo.BayesRegression.calculateW(BayesRegression.java:75)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at com.dd.aiautobrt.algo.BayesRegression.learn(BayesRegression.java:109)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at com.dd.aiautobrt.algomodel.ModelController.train(ModelController.java:149)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at com.dd.aiautobrt.algomodel.ModelController.startTrain(ModelController.java:118)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at com.dd.aiautobrt.BasedController.onEventChanged(BasedController.java:42)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at com.dd.aiautobrt.services.AiAutobackModelService$ModelServiceWrapper.onEventChanged(AiAutobackModelService.java:45)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at com.dd.aiautobrt.IAibackService$Stub.onTransact(IAibackService.java:98)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at android.os.Binder.execTransactInternal(Binder.java:1290)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at android.os.Binder.execTransact(Binder.java:1249)
04-14 11:05:56.730  7613  7644 E JavaBinder: Caused by: java.lang.RuntimeException: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: https://deeplearning4j.konduit.ai/nd4j/backend
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5066)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at org.nd4j.linalg.factory.Nd4j.<clinit>(Nd4j.java:284)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	... 10 more
04-14 11:05:56.730  7613  7644 E JavaBinder: Caused by: org.nd4j.linalg.factory.Nd4jBackend$NoAvailableBackendException: Please ensure that you have an nd4j backend on your classpath. Please see: https://deeplearning4j.konduit.ai/nd4j/backend
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at org.nd4j.linalg.factory.Nd4jBackend.load(Nd4jBackend.java:211)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5062)
04-14 11:05:56.730  7613  7644 E JavaBinder: 	... 11 more

@Laurin123 hmm…there’s got to be a root cause here. Are you sure you aren’t using an old apk or anything like that?

Beyond that…could you please set a system property: org.bytedeco.javacpp.logger.debug=true

I wonder if you’re running in to some sort of a hidden native library issue that causes this exception to be thrown.

Hi,

Below you will find the part of my gradle build related to deplearning4j. As you will see, there are significant differences. As Adam said, I would suggesto to start with to try the gradle build fragment below.

Thanks,

Alex

            def dl4jVersion = '1.0.0-M2.1'
            def openblasVersion = '0.3.21-1.5.8'

            implementation  group: 'org.deeplearning4j', name: 'deeplearning4j-nn', version: dl4jVersion
            implementation  group: 'org.nd4j', name: 'nd4j-native', version: dl4jVersion
            implementation  group: 'org.nd4j', name: 'nd4j-native', version:  dl4jVersion, classifier: "android-arm64"

            implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion
            implementation  group: 'org.bytedeco', name: 'openblas', version: openblasVersion, classifier: "android-arm64"

Sorry my answer above was superfluous.

You use dl4j to train and run your network on Android, right?

As a test, it might be useful if you could run the code that fails on Android on the desktop.

I would be helpful if you could share the section of code where the error occurs.

@Laurin123 I guess maybe you’ve moved on. It’d be nice to know why your setup might not be working when Alex’s was.