Class ‘Task’ is not abstract and does not implement abstract member public abstract fun writeToParcel(p0: Parcel!, p1: Int): Unit defined in android.os.Parcelable

AndroidのParcelのことでつまづています。

Parcelという仕組みは、例えばIntentからIntentへ何か値を渡すときに、String(文字列)とかInt(整数)とかだと簡単に渡せるんですが、自分で作った自作クラスのオブジェクトを渡すための仕組みです。(かなりはしょっていますが)

Parcelについて(Android公式 英語)

で、Javaでやってた時はかなりごちゃごちゃ書かないと、 自分で作った独自クラス にParcelというのを実装できませんでした。

Kotlinでも、少し古いのを読むと、の独自クラスに実装するのに、やはりかなりわかりにくい処理を書かねばいけませんでした。

しかし、なんと!!

Android StudioのKotlinのプラグインの1.3.60 以降では、下記のように

@Parcelize
class Task(val _id: String, val _name: String):Parcelab

これだけでOKになりました!

@Parcelize

アノテーションと、Parcelableを継承するだけで完結!

になったらしいです。

A study of the Parcelize feature from Kotlin Android Extensions
https://medium.com/@BladeCoder/a-study-of-the-parcelize-feature-from-kotlin-android-extensions-59a5adcd5909

しゅごいー

と思って早速実装したところ、タイトル通り、ビルドできませんでした。

下記のStack Overflowさんにも、1.3.60以降はこのエラー出ないヨ!って書いてあるんですけどね…。

https://stackoverflow.com/questions/56018761/class-x-is-not-abstract-and-does-not-implement-fun-writetoparcel-defined-in-an

仕方なく

androidExtensions {
experimental = true
}

をアプリケーションのbuild.gradleに書いたらビルドできるようになりました。

build.gradleの全部をサンプルで載せておきます。

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "hogehoge.myapplication"
        minSdkVersion 14
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'

        androidTest.java.srcDirs += 'src/androidTest/kotlin'
    }
}

androidExtensions {
    experimental = true
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:28.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Kotlin のコードをバイトコードにしてからJavaにデコンパイルする

Android Studio内(現時点で3.4.1)で 実に簡単にできます。(´ω`)

①対象のKotlinのファイルを開いておく

②Tools→Kotlin→Show Kotlin Bytecode

で、右のベイン(私の環境では)に、バイトコードが出ます。

おおー。

で、上にある「Decompile」というボタンを押します。

そうすると、左側のソースコードのところに、例えば

「Task.kt」

というファイルを変換した時は

「Task.decompiled.java」

というファイルができます。

途中、バイトコードにしてくれるのはIntelliJのやさしさなんですかね?

「ちゃんとやってますよー」

みたいな。

なんでこんなことやってみたかというと、下記のMediumの記事を見て、とても勉強になったからです。(オール英語でかなりつらい)

良記事なので、また違うところで紹介できるといいなと思います。

https://medium.com/@BladeCoder/a-study-of-the-parcelize-feature-from-kotlin-android-extensions-59a5adcd5909



Ubuntu 18.04 LTSにDockerを入れて機械学習環境を構築

前回の続き。

Ubuntuが無事(?)に入ったところで、いよいよDocker入れてTensorFlow入れて機械学習をゴリゴリやりたいところですが、その前にはやっぱり準備が必要です。

参考: Docker  |  TensorFlow

やったこと

もたもたとアプデ確認
Dockerのインストール
TensorFlowのDockerイメージを取得?
Dockerイメージを適用して環境構築?
動作確認?

もたもた

諸事情で前回作業から間が空きまくってしまったので、アップデートの確認とか色々します。

パッケージ一覧取得
$ sudo apt update
パッケージの更新
$ sudo apt dist-upgrade
不要になったパッケージの削除
$ sudo apt autoremove

Ubuntuのバージョン管理ツールも入れます。(多分最初から入っているけど念の為)
$ sudo apt install update-manager-core

Ubuntuのアップグレードチェック
$ do-release-upgrade -c
おっと、Ubuntuの最新版は19.10でしたが、LTSはまだなかったみたいです。
There is no development version of an LTS available. To upgrade to the latest non-LTS develoment release set Prompt=normal in /etc/update-manager/release-upgrades.

画面の解像度?表示倍率?がおかしかったのでNVIDIAのドライバを再インストール

古いドライバ削除
$ sudo apt --purge remove nvidia-*
パッケージ情報更新
$ sudo apt update
推奨ドライバ確認
$ ubuntu-drivers devices
 (略) nvidia-driver-435 がrecommended
あれ?公式のドライバ検索だと440なんだけど……??

ウーンPPA。
$ sudo add-apt-repository ppa:graphics-drivers/ppa
パッケージ情報更新
$ sudo apt update
推奨ドライバを再度確認
$ ubuntu-drivers devices
 (略)  nvidia-driver-440 がrecommended
公式のドライバ検索と同じ結果になった。

インストール
$ sudo apt install nvidia-driver-440
再起動
$ sudo reboot
……解像度なおったわ!!!

nvidiaの情報チェック
$ nvidia-smi
 (略) 問題なさげ

これでやっとまともにUbuntuのセットアップ作業ができる……
参考: Ubuntu Linux 18.04にGPUドライバをインストールする|setoyama60jp|note

Dockerインストール

アプデチェックはこの辺にして、Dockerを入れます。どっか~んっ!

参考: Get Docker Engine – Community for Ubuntu | Docker Documentation

パッケージ一覧を更新
$ sudo apt update

HTTPSでdocker repositoryを利用するためのパッケージを導入

$ sudo apt install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common

Dockerの公式のGPG Keyを追加
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

repositoryを追加

$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"

パッケージ一覧を再度更新
$ sudo apt update

Dockerのインストール
$ sudo apt install docker-ce

インストールできたらDockerのバージョン確認
$ docker version

Client: Docker Engine - Community
Version: 19.03.4
API version: 1.40
Go version: go1.12.10
Git commit: 9013bf583a
Built: Fri Oct 18 15:54:09 2019
OS/Arch: linux/amd64
Experimental: false
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/version: dial unix /var/run/docker.sock: connect: permission denied

Linux で GPU サポートを有効にするため、nvidia-dockerをインストール

# Add the package repositories
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

# Install package and restart docker
$ sudo apt update && sudo apt install -y nvidia-container-toolkit
$ sudo systemctl restart docker

TensorFlowセットアップ

TensorFlow の Docker イメージをダウンロード

latest stable release versionのイメージを取得
$ docker pull tensorflow/tensorflow

参考: Docker | TensorFlow

TensorFlow Docker コンテナを起動確認

$ sudo docker run --rm -it -p 8888:8888 tensorflow/tensorflow:latest-py3

~~~~(略)~~~~
Status: Downloaded newer image for tensorflow/tensorflow:latest-py3

________                               _______________
___  __/__________________________________  ____/__  /________      __
__  /  _   \  __ \_  ___/  __ \_  ___/  /   __  /_  __ \_ | /| / /
_  /   /  __/  / / /(__  )/ /_/ /  /   _  __/    / / // /_ |/ |/ /
/_/    \___/// ///____/ \____///    //      /_/  \____/____/|__/

WARNING: You are running this container as root, which can cause new files in
mounted volumes to be created as the root user on your host machine.
To avoid this, run the container by specifying your user's userid:
$ docker run -u $(id -u):$(id -g) args...

なんかでた。

外部からAIサーバとして使うために固定IPアドレスを指定

参考: Ubuntu 18.04 LTSで固定IPアドレスの設定 – Qiita

参考: Ubuntu18.04 LTSでネットワークの設定方法 – ちゃんおぎのメモ置き場

元の

# Let NetworkManager manage all devices on this system
network:
version: 2
renderer: NetworkManager

変更後

# Let NetworkManager manage all devices on this system
network:
version: 2
renderer: NetworkManager

ethernets:
enp3s0:
dhcp4: n
addresses: [192.168.x.xxx/24]
gateway4: 192.168.x.1
nameservers:
addresses: [192.168.x.1]
dhcp6: n

PuTTYでSSHログインのテストしてちゃんと繋がったので、とりあえずこんな感じで作業終了。疲れた。

参考

Android Studio3 Logcatの字が小さい

高解像度のディスプレイで使っていると、ある時からAndroidStudioのLogcatが表示されるところの字が非常に小さくなって見づらくなりました。

「まるで、ゴミのようだ!!」

というわけで、設定を変更します。

File→Editor→Color Scheme→Console Font

で変更できます。

File→Editor

にもFontがありますが、これはソースコードなどの表示ですね。

Kotlin tailrec とは(超簡単解説)

Kotlin(コトリン)の勉強を始めたばっかりです。6年ぐらいJavaをやってて、まぁ、今度のAndroidアプリはKotlinでやってみるか、ということで始めました。

本を読んでいて、次のようなサンプルコードに出会いました。

    tailrec private fun gcd(a: Int, b: Int): Int =
        if (b == 0) a
        else gcd(b, a % b)

tailrecとはなんぞや!!

Kotlin公式サイトで見ます。残念ながら現時点では英語しかないらしい…。

https://kotlinlang.org/docs/reference/functions.html#tail-recursive-functions

簡単に、意訳しますね!

tailrecの修飾子がついた関数は、条件を満たせば、再帰関数をスタックオーバーフローの心配なく使える。

条件は

・その関数自体の呼び出しが、関数の最後である
・try catchブロックの中ではない

だそうです。

以上が、超簡単なtailrecの話でした。以下は、もうちょっと詳しく補足です。
—————————————————-

そもそも、tailrecの日本語が「末尾再帰」なのか「末尾再帰最適化」なのか、よくわかりませんが、再帰関数の、返り値が末尾で再帰する場合、Kotlinの場合はJVMがいい感じに処理してくれるということです。

何がいい感じなのかというと、再帰関数というのはスタックオーバーフローを起こしやすいのです。

自分自身を参照して、ぐるぐる回るので、なかなかストップ条件にいたらない場合、そうなりがちですね。

しかし、 末尾再帰最適化 では、それを普通のwhileループみたいに内部で書き換えてくれるので、スタックオーバーフローの心配がなくなるのです。

すごいー。

「じゃあ、最初からwhileとかで書けばいいじゃん」

という人もいると思います。

♪違う違う~ そうじゃ、そうじゃなーいー

再帰関数はあまりJavaとかでは出てこないですけども、使えると便利なシーンがあります。同じことを何度か繰り返す場合ですね。

その時に、

「ああー この入力値がもしかしてバカでかかったらスタックオーバーフローで止まってしまうのでは…」

と心配をしなくていいのは、素晴らしいことなんです。