I'm trying to use TensorFlow in an Android mobile app to infer on a model. First, I have already built and tested a TensorFlow graph; it is saved as a protobuf file. Next, I have the toolchain setup and I have built and run the Inception Android demo. My next step is to create a fresh Android project in Android Studio (with C++ enabled) following the Android tutorial. I've created the JNI Hello World app, it compiles and runs on a Nexus. But when I tried to import 'org.tensorflow', I can't get Android Studio (AS) to recognize it. So, my primary question is: how to bring TensorFlow into my Demo app.
For example, I created a simple class to start with:
package com.foobar.tfdemo;
import org.tensorflow.contrib.android.TensorFlowInferenceInterface;
public class TensorFlowClassifier implements Classifier {
// do something
}
But Android Studio cannot resolve org.tensorflow.
Possible options:
1) Modify build.gradle to compile TF into the project (using Bazel)
2) Externally compile a TF library (.so) and import it, or
3) Use CMakeList.txt to import a TF library
In detail:
Option 1) Modify build.gradle.
I used the Inception build.gradle as a model and copied over most of it. The same import org.tensorflow still doesnt resolve, even though there are no other errors. Here is the build.gradle file:
apply plugin: 'com.android.application'
def bazel_location = '/usr/local/bin/bazel'
def cpuType = 'armeabi-v7a'
def nativeDir = 'libs/' + cpuType
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.algoint.tfdemo"
minSdkVersion 23
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
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'
})
compile 'com.android.support:appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
}
task buildNative(type:Exec) {
workingDir '../../..'
commandLine bazel_location, 'build', '-c', 'opt', \
'tensorflow/examples/android:tensorflow_native_libs', \
'--crosstool_top=//external:android/crosstool', \
'--cpu=' + cpuType, \
'--host_crosstool_top=@bazel_tools//tools/cpp:toolchain'
}
task copyNativeLibs(type: Copy) {
from('../../../bazel-bin/tensorflow/examples/android') { include '**/*.so' }
into nativeDir
duplicatesStrategy = 'include'
}
copyNativeLibs.dependsOn buildNative
assemble.dependsOn copyNativeLibs
tasks.whenTaskAdded { task ->
if (task.name == 'assembleDebug') {
task.dependsOn 'copyNativelibs'
}
}
Option 2: Bring in a tensorflow library (.so) file.
I've spent a lot of time on this. I've generated libtensorflow_demo.so using Bazel at the command line:
bazel build //tensorflow/examples/android:tensorflow_native_libs --crosstool_top=//external:android/crosstool --cpu=$CPU --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
and placed it in both ~project/libs and ~project/src/app/src/main/jniLibs. But nothing I do seems to help.
Option 3: Use CMakeList.txt to compile tensorflow.
I haven't spent much time on this. I don't think CMakeList.txt will be able to invoke Bazel or import an .so file. I think it needs a .a file instead.
So, how have others gone about incorporating Tensorflow into Android projects?
Best regards.