Smart cast to “TextView” is impossible, because “textView” is a mutable property…

JavaからKotlinへ移行してAndroidアプリ書いている、私のような人にはタイトルのようなエラー結構出ると思うんですけど。

下記のようなシンプルなコードがあったとします。

    private var textView: TextView? = null

    //アプリが開始されると最初に処理されるメソッド
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.content_input_voice)

        textView = findViewById<View>(R.id.textView) as TextView

        textView.setText(getText(R.string.no_task_error)) //ここでエラー
}

これは、結論から言いますと、次の2パターンで治ります。

//パターン1 textViewはnull許可だってわかってるよ?とする
textView?.setText(getText(R.string.no_task_error)) 
//パターン2 textViewをvalにする
val textView:TextView = findViewById<View>(R.id.textView) as TextView
textView.setText(getText(R.string.no_task_error))

mutable は可変という意味です。

varという宣言していたり、Null許可している変数にアクセスしようとすると出ます。


Ubuntu18.04 LTS | HDDの増設

前回の続き。

内蔵HDDの追加作業をしました。

調べたらGUIで簡単にできるらしい。さっくりと実践。
(うっかりスクショ撮り忘れたので文字ばっかですがご了承ください)

参考: HDDをフォーマットする – Ubuntu 18.04 LTS編

  1. Windowsキーとか押して「disk」と入力し、出てきた「ディスク」を開く。
  2. セットアップを行いたいディスクを選択し、メニュー(≡)から「ディスクを初期化」を選択。
  3. ディスクの初期化
    何も入っていないドライブだったので下記のように選択して初期化。
      消去: 既存のデータを上書きしない(クイック)
      パーティション: 新しいシステムと(中略)互換(GPT)
  4. [➕]を押して未割り当て領域にパーティションを作成
    パーティション作成ダイアログでは、パーティションのサイズを最大にしました。
  5. ボリューム名などの設定は以下のようにして作成。
      ボリューム名: data
      消去: オフ
      タイプ: Linuxシステム専用の内蔵ディスク(Ext4)。
  6. [▶]を押してパーティションをマウント
  7. [⚙]を押してマウントオプションを編集
    Ubuntu起動時に自動でマウントされるよう設定する。
      ユーザーセッションのデフォルト: オフ
      ☑ システム起動時にマウントする
      ☑ ユーザーインターフェースに表示する
      マウントポイント: /media/onlineconsultant/data
      識別: UUID=~~~~~~~~~~
      ファイルシステムのタイプ: auto
    として [🆗]。認証を求められるのでパス入れて完了。
  8. 再起動して確認。

サイト通りの手順でできてしまった。

一応コマンドでもできるという話

まず現状確認

$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda1 during installation

UUID=d2916135-4486-43be-a209-b548c96bfe38 / ext4 errors=remount-ro 0 1
/swapfile none swap sw 0 0

ここで、以下のようにコマンド実行

sudo echo -e '/dev/sda1 /media/onlineconsultant/data auto defaults 0 0' >> /etc/fstab

みたいなことをしてもできます。(ちょっと /etc/fstab ファイルの中身は違うけど実質同じ(はず))

おわり。

参考

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ログインのテストしてちゃんと繋がったので、とりあえずこんな感じで作業終了。疲れた。

参考