くうと徒然なるままに

モバイルアプリを作りながらバックエンドも作っています。

Gradle Custom Task with kotlin を実行するときに 引数を渡したり実行結果を読み取る。

Gradle Task に引数を渡す

Gradle Task を実行するときに引数を渡したいときがあると思います。
build.gradle内で完結している場合には、以下のように lateinit var な変数を定義すれば値を渡すことができます。

lateinit var userName: String

さて、build.gradle.kts 内に留まらず、terminal等から呼び出すときにはどうすればいいでしょうか。

まぁ、結果から言うと以下のように設定すればいけます。 プロパティを定義してそこにオプションであることを明示してあげるといける。

@Suppress("UnstableApiUsage")
    @set:Option(option = "userAge", description = "this is stand for user age")
    @get:Input
    lateinit var age: String

Gradle Task の実行結果を読み取る

同じプログラム内から呼び出してるときはシュッとできますが、ここで書くのは外部から呼び出すときです。

具体的には、terminal から Gradle Custom task を呼び出すときに値を返したい的な。

結論からいくと プログラム内から標準出力して表示してシェル芸なりなんなりしてよしなに処理すればいける。

プログラム全体像

SampllteTask.kt

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.options.Option

open class SampleTask : DefaultTask() {

    lateinit var userName: String

    @Suppress("UnstableApiUsage")
    @set:Option(option = "userAge", description = "this is stand for user age")
    @get:Input
    lateinit var age: String

    @TaskAction
    fun print() {
        print("Hello ${userName} your ${age} yeard-old")
    }
}

build.gradle

task sample(type: SampleTask) {
    userName = "kuu"
}

出力例

./gradlew sample --userAge="21"  -q
Hello kuu your 21 yeard-old⏎                  

AirPods を購入して2年ぐらいが経過したのでバッテリーの容量を計測してみた。

AirPods というAppleより販売されている完全無線型イヤホンを利用しています。

Apple AirPods with Charging Case (最新モデル)

Apple AirPods with Charging Case (最新モデル)

発売当初は「耳からうどん」とか言われてましたが、現在はほとんどの人が使っているのでないでしょうか?

さて、長年使用してきて困ってきたことがあります。それは、バッテリーがヘタってきたことです。体感的に以前よりバッテリーが持たなくなってきている気がしています。

今回は、 AirPods のバッテリーの容量を実際に使用してどのくらいヘタってきたのかを計測していきたいと思います。
日頃の利用頻度は、作業するときのBGMをかける用途で使っています。

計測方法

15分ごとにエクセルに記入していき計算したりグラフ化したりしました。

f:id:kuxumarin:20190729064729p:plain

f:id:kuxumarin:20190729064801p:plain

超ざっくりとした計測なので精度はあれです。

AirPods 本体(うどん)

本体のバッテリーの容量がヘタってくると頻繁にケースに入れてチャージしなければいけません。

音楽を聞くとき

公式の使用では5時間連続使用することができるはずです。

2時間半で40%まで減りました。

ということで計算すると4時間ちょいでバッテリーがなくなることになります。減っていますね。

Skypeでミーティングをするとき

ちょうどSkypeでミーティングする用事が入っていたためそちらでも検証してみました。

通話での連続使用時間は2時間となっています。しかし、実際に使ってみると1時間程度でバッテリーが残り10%になってしまいました。

AirPods ケース

総使用時間は6時間で64%消費したので、1時間にざっくり10%利用することになります。

ということで10時間程度で本体のバッテリーが切れることになります。ちょっと多めに計算しても19時間程度は利用できてほしいのですが、10時間までしか使えないのは消耗が激しい気がしてます。

で、どうしたいの?

AirPodsのバッテリーは消耗してあまり使えなくなりました。しかし、私は先日 WF1000-xm3 を買ったのでそちらを利用して行こうと考えています。

kuxumarin.hatenablog.com

無線ノイキャンイヤホンWF1000-XM3を使い倒してみた@大学、新幹線、オフィス、京都観光

ソニーから最近発売開始され人気を集めている無線ノイキャンイヤホン WF1000-XM3 を使い倒してみたので感想記事を書いていきます。

ソニー SONY ワイヤレスノイズキャンセリングイヤホン WF-1000XM3 : 完全ワイヤレス/Bluetooth/ハイレゾ相当 最大6時間連続再生 2019年モデル プラチナシルバー WF-1000XM3 S

WF1000-XM3 とは?

強力なノイズキャンセリングを搭載したAirPodsのような無線イヤホンです。
Amazon などで購入でき、色は黒と白から選ぶことができます。

特徴

ノイズキャンセリング

ソニーからはノイズキャンセリング機能が秀逸なため以前より話題になっている WH-1000XM3 というものが出ています。
写真のやつです。

ソニー SONY ワイヤレスノイズキャンセリングヘッドホン WH-1000XM3 B : LDAC/Bluetooth/ハイレゾ 最大30時間連続再生 密閉型 マイク付 2018年モデル ブラック

こちらのノイズキャンセリング機能を移植したものです。実際に使ってみると ほぼ同等なノイズキャンセリング効果 を発揮してくれているようです。

音がいいらしい

ハイレゾとかAACとかよくわかりませんが、音がいいらしいです。詳しくないですが、iPhone 付属のイヤホンやAirPodsより音質いいかなーってぐらいです。

耳に触れる部分がゴム製なため耳の隙間がなくなるのでいい感じに使えます。

ソニー製😇

ソニー信者はソニーの製品を買わないといけないのです。

購入モチベーション

WH-1000XM3 では暑い時期になってきた。

WH-1000XM3 はヘッドホンです。耳全体を覆うため暑いです。

イヤホンなら軽減されるかなーと思い購入。

WH-1000XM3 は大きい

旅行とかに行くときにWH-1000XM3 を持ち歩くとかさばって辛いです。

小型化したかった。

実際使ってみてどうなの?

大学

大学の中を歩いてるときに静かに歩くことができます。

イヤホン自体の大きさが小さいため目立たずに使えて良さげです。

講義中は外しましょう(つけ心地いいのでつい忘れてしまう

東海道新幹線

とある事情により毎週東京と名古屋を往復しています。そのためかなりの頻度で新幹線を使っています。

大体3時間ぐらい電車に乗っているのですが、ノイズキャンセリング付きのものを使う前はかなり体力を消費していました。しかし、使うようになってからは体力がほとんど減ることなく乗車することができます。

新幹線のノイズって割とMPだけでなくHPも奪っていくんですね。

車内販売する時どうなの?

イヤホンを耳から外さないと辛いです。イヤホンにも一応外音取り込み機能がついてますが、正直外した方が楽...
シンカンセンスゴクカタイアイス 美味しい☺️

WH1000-XM3 と比べてどうなの?新幹線で寝る時辛い問題とか

ヘッドホンタイプの場合新幹線で寝るときにい引っかかってしまい辛いです。しかし、このイヤホンを使えばその問題が解決されます。

眠い時はぐっすり寝てます。₍₍ (ง ˘ω˘ )ว ⁾⁾ スヤッ スヤッ

オフィス

私は学生ですが、現在関東地方にあるIT企業で Software engineer のインターンシップをしています。
そのため、オフィス環境で使っている時の感想を書きます。

オフィス環境の前提条件

  • オープンスペース, 空いてる空間活用してフリーアドレスみたいにしてる人もいる
  • 席の近くにカフェがある
  • 電話がかかってくることはない

メルカリオフィスがUpdateされたよ!Part2 #メルカリな日々 | mercan (メルカン)

iPhone の音楽アプリで一番小さい音量で音楽を流すだけで大抵の騒音はカットできます。

使ってる風景

Sync の時以外は基本的にずっとつけてます。1on1 の時を除くとほとんど入ってないので割と多い時間で付けてます。

前の席はクーラー的に割と涼しかったのでヘッドホンの方を使ってましたが、最近は出番減り気味です。(暑がり

カフェで買う時

カフェで買うときには人間とコミュケーションを取らないといけないので話すのですが、こちらも新幹線の車内販売と同じようにイヤホンを外してます。

京都観光

旅行に行くときに充電もつ?

試しに1泊二日で京都へ旅行してきました。(それ以外にも目的はあるけど

朝充電が完了してから行きましたが、二日目に帰ってきてからも使えました。

トイレ行く時とかにイヤホンをケースに入れて充電してました。実用上は十分な印象。

観光とノイズキャンセリングイヤホン

ずっとつけていたわけではないのですが、愛知から京都への新幹線での移動時間やお寺等での鑑賞時に使いました。音が聞こえてた方がいいような場所では外しましたが、観光地で静かに鑑賞したい派の私としてはノイズキャンセリングが騒音だけにいい感じに聞いててよかったです。

音楽無しでノイズキャンセリングだけしてると騒音カットしつつ会話できていい感じ。

f:id:kuxumarin:20190718034213j:plain

欠点は?

防水ではない

防水ではないので雨が降ってくると辛い....

次のバージョンでは頑張ってほしい

最低音量でもある程度大きい

微妙に音楽かけたい時ってあるじゃん。そういうときに辛い。

ここから買ってくれると筆者が喜びます

iPad に入っているアプリを棚卸してみる。

iPad に入っているアプリを書き出してみる。

特によく使うやつ

写真系

動画見る系

たまによく使う

特によく使う

定番アプリ

写真系

Lightroom で編集してクラウドにバックアップしてます。

動画見る系

BGMがあると集中できるので

たまによく使う

本は最近あまり買ってないのでなぁ。

Circle CI の Config ファイルの検証をローカルで実行する。

Circle CI の .circleci/config.yaml をローカルで検証したくないですか?

Step 1. Install Circle Ci CLI

Circle CI にはローカルで実行できるようにCLI Tool が存在します。
また、Homebrew から導入できるようになっているので以下のコマンドを叩くだけで入れることができます。

brew install circleci

Step 2. Execute Validate Command

Circle CI のバリデーションを行うコマンドを実行することができます。

circleci config validate

検証に成功した時の出力

Config file at .circleci/config.yml is valid.

RecyclerView.ListAdapter でアイテム挿入後に何かしたい!非同期辛い!

RecyclerView を使って何かする時に ListAdapter を使ってますか? DIFFUtil を使うときに合わせて使うことが多いかなと思います。

問題点

submitList しても非同期で挿入されるため、 SubmitList() した直後にRecyclerView(Adapter) に対してあれこれすると古いリストに対して操作してしまう。

どのようなケースで問題になるのでしょうか?
具体的には以下にsubmitList した後に処理をするケースで問題になります。

// adpater は ListAdapter の実装クラス
adapter.submitList(emptyList())
// RecyclerView に適当な処理を加える
binding.RecyclerView.scrollToPosition(100)

Why?

SubmitList は内部で DIFFUtil を使い差分を計算する処理をバックグラウンドExecuter でしているからです。

そのため、submitList が発火した後に非同期的に差分計算をし、挿入したりしてます。

必ず挿入した後のリストに対して操作しなければいけない場合は?

コールバックを設定すれば大丈夫そうです。
ただ、もっとスッキリできる方法あるかも....

        adapter.registerAdapterDataObserver(object: RecyclerView.AdapterDataObserver(){
            override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
                super.onItemRangeChanged(positionStart, itemCount)
                // 変更されたのがコールバックされる
            }
        })