みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

AndroidStudioでTensorflowデモを動かす。

はじめに

TensorflowのAndroidのデモを動かそうとしたところ、 いろいろハマった上にまとまった情報がなかったのでメモっておく。

ソースの取得

まず--recurse-submodules忘れた。これは完全に自分のミス。

$ git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git

修正点

手で修正したファイルは次のとおり。

  • tensorflow/examples/android/AndroidManifest.xml
  • tensorflow/examples/android/build.gradle

AndroidManifest.xml

基本的にはAndroidStudioが色々やってくれるのでそれに従う。

diff --git a/tensorflow/examples/android/AndroidManifest.xml b/tensorflow/examples/android/AndroidManifest.xml
index 5c47ce6b67..bea3683102 100644
--- a/tensorflow/examples/android/AndroidManifest.xml
+++ b/tensorflow/examples/android/AndroidManifest.xml
@@ -16,23 +16,29 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="org.tensorflow.demo">
-
     <uses-permission android:name="android.permission.CAMERA" />
-    <uses-feature android:name="android.hardware.camera" />
-    <uses-feature android:name="android.hardware.camera.autofocus" />
+    <uses-feature android:name="android.hardware.camera"/>
+    <uses-feature android:name="android.hardware.camera.autofocus"/>
+    <uses-feature android:name="android.software.leanback"/>
+    <uses-feature android:name="android.hardware.touchscreen"/>
+
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
 
     <uses-sdk
         android:minSdkVersion="21"
-        android:targetSdkVersion="23" />
+        android:targetSdkVersion="27" />
 
-    <application android:allowBackup="true"
+    <application
+        android:hardwareAccelerated="true"
+        android:allowBackup="true"
         android:debuggable="true"
         android:label="@string/app_name"
         android:icon="@drawable/ic_launcher"
-        android:theme="@style/MaterialTheme">
+        android:theme="@style/MaterialTheme"
+        tools:ignore="GoogleAppIndexingWarning,HardcodedDebugMode,MissingTvBanner">
 
         <activity android:name="org.tensorflow.demo.ClassifierActivity"
             android:screenOrientation="portrait"

一番ハマったのはandroid:hardwareAccelerated="true"

手持ちのスマートフォンのカメラがしょぼく、CameraAPI2が使用できなかったためレガシーにフォールバックするのだが、 これがハードウェアアクセラレーションを有効化していないと、画面が真っ黒になってしまうという問題がある。

TextureViewでonSurfaceTextureAvailableが呼ばれないことに気づいたのでわかった。

build.gradle

diff --git a/tensorflow/examples/android/build.gradle b/tensorflow/examples/android/build.gradle
index 0767726aa9..20c4e4df9b 100644
--- a/tensorflow/examples/android/build.gradle
+++ b/tensorflow/examples/android/build.gradle
@@ -24,23 +24,25 @@ getProject().setBuildDir('gradleBuild')
 
 buildscript {
     repositories {
+        google()
         jcenter()
     }
 
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.0.1'
+        classpath 'com.android.tools.build:gradle:3.3.1'
         classpath 'org.apache.httpcomponents:httpclient:4.5.4'
     }
 }
 
 allprojects {
     repositories {
+        google()
         jcenter()
     }
 }
 
 // set to 'bazel', 'cmake', 'makefile', 'none'
-def nativeBuildSystem = 'bazel'
+def nativeBuildSystem = 'none'
 
 // Controls output directory in APK and CPU type for Bazel builds.
 // NOTE: Does not affect the Makefile build target API (yet), which currently
@@ -76,14 +78,14 @@ project.ext.TMP_DIR   = project.buildDir.toString() + '/downloads'
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 23
-    buildToolsVersion '26.0.2'
+    compileSdkVersion 27
+
 
     if (nativeBuildSystem == 'cmake') {
         defaultConfig {
             applicationId = 'org.tensorflow.demo'
             minSdkVersion 21
-            targetSdkVersion 23
+            targetSdkVersion 27
             ndk {
                 abiFilters "${cpuType}"
             }
@@ -189,6 +191,6 @@ apply from: "download-models.gradle"
 
 dependencies {
     if (nativeBuildSystem == 'cmake' || nativeBuildSystem == 'none') {
-        compile 'org.tensorflow:tensorflow-android:+'
+        implementation 'org.tensorflow:tensorflow-android:+'
     }
 }

ポイントとなる修正点は次のとおり。

  1. リポジトリへのgoogleの追加(2ヶ所)
  2. def nativeBuildSystem = 'none'
  3. implementation 'org.tensorflow:tensorflow-android:+'

これらの修正を行わないとビルドが通らなかった。

APKのインストールに失敗してアプリが開始できない

アプリやデバッグを開始しようとすると次のメッセージがでてアプリが開始できない。 APKのインストールで失敗するようだった。

java.io.IOException: 接続が相手からリセットされました
Error while Installing APK

たぶん、ここDisable Instant Runが効いたと思う。

Disable Instant Run (Android Document)

To disable Instant Run:

1. Open the Settings or Preferences dialog. (For Mac, Android Studio -> Preferences)
2. Navigate to Build, Execution, Deployment > Instant Run.
3. Uncheck the box next to Enable Instant Run.

ただ、この操作をしてもしばらくうまく行かなくて、.gradle.ideaを削除して、AndroidStudioを再起動したらうまくいった記憶がある。(既に曖昧)