will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

良いルーターを使うのはもはやライフハックつだ!!! TP-LINK AC3150 レビュー

Amazon Cyber Mondayあざす!!!

[asin:B01LYTYIKF:detail]

買ってしまった!良いルーター!それは TP-LINK Archer 3150!

TP-LINK? 聞いたこと無い?

私自身も日本ではバッファローエレコムNECが有名すぎて、TP-LINKを知らなかったんですがTP-LINKは世界シェア43%の企業。

最速のワイヤレス規格である802.11adのルータを世界初でお披露目するほどです。

ガジェット好きの先輩の家に行ったらTP-LINK Archer C9が置いてあって、繋いで見たところ接続の安定性・速度に感動したのがきっかけ。

そして、現在使っているBuffalo WZR-600DHPも2012年発売の機種なので古くなってきたし、TP-LINKのルータに買い換えよう!と
2週間程しらべたり、チャンスを伺っていました。

"日本で発売される最上位機種"のArcher5400が12月中に発売予定なので、こちらを買うつもりでいたが、
AmazonのCyber MondayでArcher3150がセールになっていて15,800円に値下がりしてたので買ってしまった!!!ヨドバシでは22,000円程なので、ポイントを考えても安かったです。

現在でも20,000円前後なのでAmazonで買うのがおすすめかな?ポイントが付くヨドバシでもいいかも(๑•̀ㅂ•́)و✧

上記で"日本で発売される最上位機種"と書いたのは
日本で公式に発売される予定がたっていないであろうTP-LINK AD7200Amazonで販売されているから。

AD7200は"世界初の802.11ad対応のルータ"で、Amazonでは最安で4万円程ですが、元値は$350前後のようです。発売されてから1年たつのに割高。 Amazon, Rakuten, 公式サイトをみても品薄な感じです。 公式販売されないということは、技適が通っていないかもしれません。

Archer 3150で満足できない!というかたは素直に12月中発売のArcher 5400を待ちましょう。

話を戻しまして、、、金曜日に注文して、本日土曜日に到着したので早速開封・セットアップしレビューしていきます!

開封の儀・セットアップ

はい、箱ドーーン

f:id:matsuokah:20161210214020j:plain

でかい。開封の儀を執り行います。

f:id:matsuokah:20161210214846j:plain

同梱物は本体、アンテナ x 4, 電源コード, 電源アダプタ

f:id:matsuokah:20161210214152j:plain

ポートが
背面にはWAN x 1, LAN x 4
側面にはUSB2.0 x 1, USB3.0 x 1

f:id:matsuokah:20161210213801j:plain

Mac Book Air 11inchを横に並べると大きさがより分かる。

あとは接続設定しておしまい

PCでセットアップした場合Wi-Fiに接続しセットアップの手順に従って入力していけば3分くらいで終わりました。

personal-studio9.com

上記のブログではWebのセットアップ手順が載っています。MacBookPro Touchbar 13inchとの大きさの比較も載ってます。考える事同じ笑
そもそも、MacBookAirの11inchと同じくらいの大きさってことになるMacBookProのTouchbarの13inchは相当コンパクトだな・・・!!!

が、今回はせっかくなのでアプリから設定しなおしてみる。

play.google.com

今回はAndroidのアプリです

1. ルーターを選択

f:id:matsuokah:20161210224640p:plain

2. 設定項目 > インターネット

f:id:matsuokah:20161210224633p:plain

3. 各欄の入力

f:id:matsuokah:20161210224638p:plain

これで終わりです。

基本スペック

Archer 3150の製品情報仕様より抜粋して転載しています。

ワイヤレス規格規格

IEEE 802.11ac/n/a 5GHz
IEEE 802.11b/g/n 2.4GHz

セキュリティ

64/128-bit WEP、WPA/WPA2、WPA-PSK/WPA-PSK2 暗号化方式

特徴

1. MU-MIMO

マルチユーザー、マルチインプット、マルチアウトプットの略で

簡単にいうと、複数機種を同時接続してもサクサク!ということです。

しかし、受信側もMU-MIMOに対応していないと有効になりません。

私の普段使いであるスマホのXperiaZ5とNexus9はMIMO対応で、MU-MIMOではないようです。(製品ページのスペックを読んだり、ググったりしたが見つからなかったので。)

私が自宅で使っている2012 midのMac Book Pro Retina802.11acにすら対応していない。買い替えどきかな。

2. デュアルコアコプロセッサx2搭載

ルーターデュアルコアってきいたことなかったんですが、ハイエンドルーターでは当たり前のようです。

NAS接続したり複数の端末を同時に動画を見てもヌルサクなのはこのおかげかも?

欠点としては若干の発熱があることです。ファンはうるさくないのですが表面がほんのり温かくなります。

ネットワークテストしてみる

5GHzのネットワークに繋いでテストしてみます。

スピードテスト1 単体でテストしてみる

使用アプリ
Speed Test

使用デバイス Nexus9(MIMO対応) DL: 67.49Mbps
UL: 93.80Mbps

スピードテスト2 複数台で同時にテストしてみる

使用デバイス

Nexus9(左)の結果
DL: 25.91Mbps
UL: 64.04Mbps

XperiaZ5(MIMO対応)(右)
DL: 24.73Mbps
UL: 32.43Mbps

さすがにWANがボトルネックですね!各値を足すと単体でテストしたときとほぼ同じ数字になります。

スピードテストYoutubeのシークを同時にしてみる

※音が出ます

使用デバイス
Nexus9(左)
XperiaZ5(右)

シークが早い気がする。多分。

RSSI値を調べる

ルーターがを置いているリビングと廊下を隔ててたところにある寝室でテストしてみました。
dB値が大きい(-なので値が低い)方が電波強度は強いです。

MBPのWi-FiOption + Clickで調べられます。
また、このテストはルーターの置き場所や遮蔽物の有無によって結果が変わって来ることが注意点です。

5GHz

f:id:matsuokah:20161211000056p:plain

リビング: -39dBm
寝室:-65dBm

2.4GHz

f:id:matsuokah:20161211000128p:plain

リビング: -40dBm
寝室:-53dBm

ということで、2.4GHzの方がさすがに隔てた部屋でも強いですね!

前のルータだと2.4GHzのみで寝室に移動すると電波強度が80dBm程度でした。(スクショ撮り忘れた)
また主観ではありますが、接続自体も不安定だったので改善されています。寝室では、頻繁にWi-Fiの検索中になっていた。

まとめ

ということでTP-LINKのWi-FiルータArcher 3150を紹介しましたが
快適なWi-Fiはもはやライフハックなのでは?と感じる体験レポートでした。ぜひご検討あれ!

[asin:B01LYTYIKF:detail]

InputMethodService(キーボード)開発の勘所となりそうな項目

この記事はAndroid Advent Calendar 2016 - Qiitaの11日目の記事です。

昨日は@yuyakaidoさんのData Binding Tipsでした。 明日は@rei-mさんのDagger2とMockitoでUIテストはじめる話です。

11日目はAndroid StudioでKotlinのプロジェクトが新規で作られるソースを
そろそろKotlinを選べるになってほしいmatsuokahが担当いたします。

InputMethodServiceに触れていて、キーボードのクセを掴まねば!ということで、勘所となりそうな項目を書いてみます。

InputMethodService(以下、ほぼ同義のIME)とは

いわゆるキーボードの継承元となるServiceです。
Simeji、Google日本語入力POBoxATOKが日本では有名ですね。

IMEはググっても、ヒット数が少ないのでマイナーな分野ですね。

IMEアプリの作り方はハンズオン記事を見ればわかります。
サンプルもあります。

ざっくりキーボードの作り方

  1. InputMethodServiceを継承したクラスを作成
  2. Android Manifestにサービスの定義を行う
  3. カスタムしていく

本当にざっくりですがこんな感じです。
ハンズオン記事ではMainActivityに<category android:name="android.intent.category.LAUNCHER"/>を記載していないですが、
設定アプリとしてActivityを使うはずなので消さなくて良いでしょう。

何のメソッドをオーバーライドすべきか?

を見て、リストしてみました。

Intentionally emptyとコメントが書かれているメソッド

  • onBindInput
  • onUnbindInput
  • onInitializeInterface
  • onStartInput・・・初期化
  • onStartInputView
  • onStartCandidatesView
  • onWindowShown
  • onWindowHidden
  • onDisplayCompletions
  • onViewClicked
  • onUpdateCursor
  • onUpdateCursorAnchorInfo

デフォルトでnullを返却しているメソッド

  • onCreateInputView・・・ここでビューを作成する
  • onCreateCandidatesView

デフォルトでfalseを返却している

  • onTrackballEvent
  • onGenericMotionEvent

フルスクリーンモード

  • onEvaluateFullscreenMode・・・画面を回転させた時に、フルスクリーンモードにするか否か

ということで、基本的にはここらへんのメソッドをオーバーライドしてIMEをカスタムしていくことになります。
リストにはライフサイクルに関わるメソッドも含まれています。

また、

ライフサイクル

f:id:matsuokah:20161211020251p:plain

Android Developers - creating-input-methodより転載

というような単純なライフサイクルとなっています。
しかし、思わぬ所でイベントが発火されるケースが幾つかあります。

操作して、ライフサイクルでログを追っていきましょう。

f:id:matsuokah:20161211021719g:plain

これが最もシンプルなIMEの操作だと思います。実際のログは以下のとおりです

## MyImeへ切り替えを開始
D/ImeService: onCreate
D/ImeService: onCreateInputMethodInterface
D/ImeService: onCreateInputMethodSessionInterface
D/ImeService: onInitializeInterface
D/ImeService: onBindInput
D/ImeService: onStartInput, restarting : false
D/ImeService: onCreateInputView
D/ImeService: onCreateCandidatesView
D/ImeService: onStartInputView, restarting : false
D/ImeService: onWindowShown
## IMEの表示が完了

## 別のIMEへの切り替えを開始
D/ImeService: onFinishInputView, finishingInput :   true
D/ImeService: onFinishInput
D/ImeService: onStartInput, restarting : false
D/ImeService: onStartInputView, restarting : false
D/ImeService: onUnbindInput
D/ImeService: onFinishInputView, finishingInput :   true
D/ImeService: onFinishInput
D/ImeService: onDestroy

思わぬ所でイベントが発火されるケース

と、述べましたが onStartInput, onStartInputViewが何故かonFinishXXXの後に呼ばれています。
私はStartと書いてあるのでIMEが立ち上がって入力が開始された時だけ発火すると勘違いしていました。

ではなぜ発火されているか。それは、編集していたEditTextのフォーカスが外れた時に、IMEの状態をリフレッシュするためです。

IMEは1つのインスタンスであるのに対し、画面には複数のEditTextが存在することが多いです。
編集するEditTextが切り替わると、すでに入力されているテキストや入力タイプ(Numeric, AlphaNumeric, Passwordなど)が変わります。
したがって、onStartInputでは一時的な入力データなどを破棄し、引数で与えられているEditorInfoオブジェクトの情報から次の入力に備える必要があります

実はSDKのドキュメント冒頭にあるGenerating Textという項目で述べられています。ドキュメントはしっかり読もう。

そして、ログに出てきてないので気づきにくいのですがonWindowShownに対し、onWindowHiddenが呼ばれていません。
onWindowHiddenIMEが破棄されないが非表示になるときタスクマネージャ起動時に発火されます。

従ってonWindowHiddenでTearDownするのは好ましくない実装だと思います。

onStart系のライフサイクルメソッドでスクラップアンドビルドしていくのが良いかなと個人的に思います。

Fragmentが使えない

私はIMEでもFragmentが使えると思いこんでいました。
ところがFragmentはActivityに依存しているのでServiceで使えないのは当然なわけであります。

iOSのLINEのスタンプのようなUIを実装してみようと思っていたのですが、
Fragmentが使えないのでViewPagerを使うにはAdapterの独自実装が必要となります。

LINEのUIなので、画像が多い前提となるため、Fragmentのライフサイクルの様にページを破棄することも考慮に入れる必要があります。

ということで、ひとまず最低限の実装でFragment・FragmentManager・FragmentPagerAdapterの実装を真似て作ってみました。FragmentのTransactionは実装していません。

f:id:matsuokah:20161211035021g:plain

ImeFragment.kt

abstract class ImeFragment() {
  lateinit var service : InputMethodService
  val context : Context
  get() = service


  var tag : String = ""
  var containerId : Int = 0
  var view : View? = null

  open fun onCreate() {}
  open fun onCreateView(inflater: LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View? { return null }
  open fun onAttach() {}
  open fun onDetach() {}
  open fun onDestroyView() {}
  open fun onDestroy() {}
}

ImeFragmentManager.kt

class ImeFragmentManager(val service : InputMethodService, val rootView : View) {

  val fragments : HashMap<String, ImeFragment> = HashMap()
  val attached : HashMap<String, ImeFragment> = HashMap()

  fun add(containerId : Int, imeFragment : ImeFragment, tag : String) {
    if (fragments.containsKey(tag)) throw IllegalArgumentException("already container has fragment")

    imeFragment.containerId = containerId
    imeFragment.tag = tag

    fragments[tag] = imeFragment
    attach(containerId, imeFragment, tag)
  }

  fun remove(tag : String) {
    if (attached.containsKey(tag)) {
      detach(attached[tag]!!)
    }

    val fragment = fragments[tag]!!
    fragment.onDestroy()
    fragments.remove(tag)
  }

  fun findFragmentByTag(tag : String) : ImeFragment? = fragments[tag]

  fun attach(containerId : Int, imeFragment : ImeFragment, tag : String) {
    if (!fragments.containsKey(tag)) throw IllegalArgumentException("fragment is not added")
    if (attached.containsKey(tag)) throw IllegalArgumentException("already container had attached")
    attached[tag] = imeFragment

    imeFragment.service = service
    val container = rootView.findViewById(containerId) as? ViewGroup
    imeFragment.view = imeFragment.onCreateView(LayoutInflater.from(container?.context), container, null)

    container?.addView(imeFragment.view)
    imeFragment.onAttach()
  }

  fun detach(imeFragment : ImeFragment) {
    if (!attached.containsValue(imeFragment)) throw IllegalArgumentException("fragment not found")
    val container = rootView.findViewById(imeFragment.containerId) as? ViewGroup
    container?.removeAllViews()
    imeFragment.onDestroyView()

    attached.remove(imeFragment.tag)
    imeFragment.onDetach()
  }
}

ImeFragmentPagerAdapter.kt

abstract class ImeFragmentPagerAdapter(private val imeFragmentManager : ImeFragmentManager) : PagerAdapter() {

  abstract fun getItem(position : Int) : ImeFragment

  override fun instantiateItem(container : ViewGroup?, position : Int) : Any {
    container ?: throw IllegalArgumentException("")

    val tag = createTag(container.id, position)
    var fragment = imeFragmentManager.findFragmentByTag(tag)

    if (fragment == null) {
      fragment = getItem(position)
      imeFragmentManager.add(container.id, fragment, createTag(container.id, position))
    } else {
      imeFragmentManager.attach(container.id, fragment, createTag(container.id, position))
    }

    return fragment
  }

  override fun destroyItem(container : ViewGroup?, position : Int, obj : Any?) {
    val fragment = obj as ImeFragment
    imeFragmentManager.remove(fragment.tag)
  }

  override fun isViewFromObject(view : View?, obj : Any?) : Boolean = (obj as ImeFragment).view == view

  companion object {
    fun createTag(viewId : Int, itemId : Int) : String = "android:ime_switcher:$viewId:$itemId"
  }
}

Fragmentっぽい実装を用意することで、Page単位にコントローラを分離できること・ドメインレイヤーとの繋ぎの所にもできるので欠かせないな〜という所。
ココらへん、ライブラリ化して公開します。多分。

小ネタ. Macで音のボリュームを無段階調節

知らなかったので驚いた

Shift + Option + Functionキーで音量とかディレスプレイ輝度の調整がより細かくできる!!!

普通にボリュームup/downすると以下のようにメモリ毎にボリュームが変わりますが

f:id:matsuokah:20161205223454g:plain

Shift + Optionを推しながら調節すると・・・

f:id:matsuokah:20161205223539g:plain

うおおおおおおおおおおおおおおおおお!!

f:id:matsuokah:20161205223815g:plain

うおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお!!

f:id:matsuokah:20161205223902g:plain

ま、そんなに細かく調整する必要ないんですけどね

僕のPCはMBPですが壁紙はiMacの基盤です

Androidのコードを書く前にコーディングに集中できる状態を作る

はじめに

この投稿はAndroid その3 Advent Calendar 2016 - Qiitaの5日目の記事です。

4日目はkimukouさんのrealm-gradle-plugin 2.2.1 と Android Realm Browserでした。
6日目はkimukouさんの2016年末のAndroidでのSSL対応に関してです。

Androidのコードを書く前にコーディングに集中できる状態を作る

今年のAdvent CalendarはAndroidでKotlinを導入する話がかなり多くて、Kotlinが浸透しているんだな〜と感じています。
かくいう私もKotlinを使ってみた所感やテクニックのネタを考えてたんですが、Kotlinは愚かAndroidを本格的に開発し始めて2ヶ月ですので、エキスパートな部分は先人達にお願いするとします。

最近異動して、0からのプロジェクトに携わらせてもらっていて、コードを書く前に環境を整えることを最初にやりました。その時のまとめになります。

目次

  • なぜやるべきか。ずばり何をするのか
  • 命名規則, Code Style
  • プロジェクト構成, BuildType/Product Flavor, DI
  • データ層からプレゼンテーション層のサンプル実装
  • CI
  • プルリクのルールを作る
  • 必ず使うSDK, ツールの導入
  • テンプレートコード・スニペットをつくる
  • 開発環境のプロビジョニングをつくる

なぜやるべきか。ずばり何をするのか

プロジェクト初期になぜやるべきか。
先に決めて開発期〜リリースの間にコーディングに集中できる環境があると、エンジニアの精神衛生が良い状態が保たれるからです。 そして、プロジェクトが発足したての頃は仕様が 無い or 部分的 or 一朝一夕で変わるが当然なので機能実装以外に時間を割く時間が作りやすいです。

ずばり何をするのか。
ルール化自動化です。
プルリクを前提とした開発では、コードレビューのコストを大幅にされるでしょう。ルールと自動化をメンテしましょう。コードレビューで主観的(書き方の好み)な議論をするのは楽しいですが開発スピードとのトレードオフになります。世に出ていないサービスはスピードの方が重要でしょう。

では、さっそく各項目について、まとめをつらつらと書いていきます。

命名規則, Code Style

命名規則

大雑把なルールを作り、必要になったらルールを追加していきます。

接頭辞 or 接尾辞

リソースは接頭辞ベース、クラスは接尾辞ベース
Android Best Practices#Resourcesをベースにすると良い。日本語にも翻訳されています。

レイアウトの変数に名前をつける

レイアウトの変数名に概念や機能性をもたせることで、デザイナーと列挙された数値の共通認識をもつことが出来ます。 Androidはldpi(x0.75)を考慮して4の倍数でレイアウトをする必要があるので、そこだけ3dpみたいなことは極力避けたいです。

現在のプロジェクトではマージンやパディングの数値(4, 8, 16, 24)にspacing_s, spacing_m ... と名前をつけてます。

フォントのサイズにはHTMLのタグ名を参考にすると良いかもしれません。
title, header, body, paragraph ...
コンテンツの優先順位でフォントサイズを変えるということが直感的になります。

※ルール化することでデザイナーの発想の範囲を狭めることがあります。

Code Styleをととのえる

スペースや改行は好みが分かれるので、先にルールを決めるのがいいです。
Code StyleはAndroid界隈の神らしい、Jakeが在籍するSquareのコードフォーマットを拝借しましょう。

フォークして微調整してプロジェクトのルールとするのが手っ取り早いです。Google Java Style Guideをベースにチューニングします

プロジェクト構成, BuildType/BuildVariants, DI

プロジェクト構成をつくる

いわゆるアーキテクチャです。MVP/MVVM/MVCなどのパターンから、どれで実装していくかを決める必要があります。

BuildType/Product Flavorを追加する

ビルドタイプを分ける(Debug, Release)
  • ロギングの切り替え(コンソールログ/クラッシュログをサーバーに転送する)など
環境を分ける(development, staging, production)
  • Endpointの切り替え
  • アプリアイコンなどのリソースを環境毎に変える
  • KeyStoreの切り替えをtaskに含める

DIを導入する

上記のアーキテクチャとビルドタイプを統合した構成を考える必要があります。 勘所はAPIのエンドポイントやログ、モックデータを返却するAPIなどを切り替えられるように意識しましょう。

例えば、Retrofitを使っているプロジェクトでdebug/release毎にRetrofitのインタセプタのDIの戦略を変えるというような事です。 debug時だけloggerのインタセプタのDIを有効にしてAPIアクセス時のに詳細なロギングをするといったことが可能です。

現プロジェクトではDIにDagger2を使っており、インスタンス戦略は

  • Context(Application)スコープ
  • View(Activity/Fragment)スコープ

の2つに着地しています。Contextレベルなのはドメインレイヤーから下です。

データ層からプレゼンテーション層までの一気通貫サンプルを実装する

プロジェクト構成が出来たら、その構成が本当に使いやすいか検証する必要があります。自分で実装してみるのが一番です

サンプル実装でマニュアルも同時に終わらせることが出来ますし。そして、Android初心者な私にとって一気通貫させるのは実装イメージを沸きたてるにはベストでした。

CIを導入する

とりあえずFastlaneを導入してFastfileで各環境のビルドをできるようにしておくことが重要。

Gemfileも定義して、bundle exec fastlane [ENV] type:Debugくらいのコマンドでビルドできるようにしておけば、Circle CIを導入してもdeploymentディレクティブでの細かな設定が不要になります。

実際に運用しているのは

  1. Circle CIでbundlerをつかってfastlaneをフック
  2. ターゲットとなる環境のアプリをビルド
  3. Crashlytics Betaにアプリをポストし、テスターグループにアプリを公開
  4. Slackにビルド完了通知

Fastfileにはフローを定義し、Contextにプロジェクト情報を埋め込む形に着地しています。

※FastfileはBuildType, BuildVariants, Keystoreの設定と合わせる必要があります。

プルリクエストルールを作る

前のプロジェクトのチームのプルリクにはルールが定められていて、1年以上つづけていて、とてもよかったたので概要を紹介。

  1. プルリクのフォーマット化
    1. 概要、バグフィクスの原因など
    2. 目的やアクションを記載する(仕様を含む、編集の意図をソースコードから汲み取らない)
    3. 修正の影響範囲がわかるURLを含める(開発ロードマップやCSのバグチケ)
  2. UI変更はBefore/Afterのスクショ必須
  3. インタラクションならGIFアニメ必須

詳細は割愛します。Cookpadさんの開発速度を上げるための Pull-Request のつくり方に近いです。

必ず使うSDK, ツールの導入やリスト作成する

仕様にかかわらず必要となる機能やツールは少なくとも決まってるので時間があるときに導入だけしておくことで、終盤で導入して急遽Multi Dex対応が必要になるみたいな事が減らせると思います。

テンプレートコード・スニペットをつくる

Dagger2を使う場合にはComponent, Module, Scopeを大量生産するでしょう。
IntelliJにはファイルテンプレート機能があり、予めApache Velocityのフォーマットに従った形式でソースコードを書いておけば、ファイルの新規作成時に選ぶことが出来ます。 テンプレート化によって、フレームワークを使うときのフットワークを軽くすることが出来ます。

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}

#end
#parse("File Header.java")

import javax.inject.Scope
import kotlin.annotation.AnnotationRetention.RUNTIME

@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class ${NAME}

開発環境のプロビジョニングをつくる

AnsibleでAndroid SDKのインストールを図る。

Android Studioがよしなにやってくれることも多いので、ツール群の導入くらい。

まとめ

プロジェクトを始める発射台となるような手順をまとめた。とにかく最初は開発しやすいように、大雑把なルールや開発を加速させる周辺を整える事が重要。

そして、ユニットテストやUIテストの導入がまだできてないので、これからやりたい。

あわせて読みたい

blog.matsuokah.jp

Android 2.3系, 3.0系を対応しているならそろそろ潮時なのかもしれない

Highlights from the Google Play services 10.0 release.

Google Play Servicesのv10系がリリースされ、リリース文の序文に

Google Play services 10.0.x is the final release that includes full support for Android version 2.3.x

2.3を切るよと書かれている。

android-developers.blogspot.jp

The next scheduled release of these libraries, version 10.2.0, will increase the minimum supported API level from 9 to 14 (Android 4.0.1, Ice Cream Sandwich).

次のリリース予定である10.2.0ではminSdkをv14(Android 4.0.1)に引き上げる予定とのこと。

更にAndroid Developersブログの案内では続けて v10.0.0系をlegacy, v10.2.0系をcurrentというProduct Flavorsを作成し、Multiple APKを使えばいいと案内しているが

メンテコストが膨らむのが目に見えてるでしょ。

10.0.0系と10.2.0系以降のライブラリのインターフェースや動きが同じとは限らない。

切り時なのだね。きっと。

Androidの開発にはIntelliJでも良いじゃんと気づいた話

f:id:matsuokah:20161204181038p:plain

IntelliJをインストールしていながらもAndroid Studioを使っていたが IntelliJAndroidプロジェクトを読み込んでみたら、Android Studioと全く同じように開発できた。

そして、上位互換だった。そんな話。

社会人になってからの職歴とエディタ歴は

ざっくりこんな感じ。

IntelliJに1年だけデビューしておき、その後は惰性でアップデートしていたので損してたな〜。

Android StudioIntelliJの若干古いバージョンがベースとなって無料配布されているだけ

Android Studio2.2はIntelliJ IDEA 2016.2がベースとなっている。

IntelliJ最新バージョンは 2016.3である。

Constraints Layoutは2016.2ベースのAndroid2.2に含まれているのに対し、2016.3の機能となっている。

メリット/デメリット

メリット: Kotlinの最新の機能がいち早く使える

ちょっとしたメリット. どっちも持ってるならIntelliJを使うという選択をすべき。

What's New in IntelliJ IDEA - 2021.3

上記の2016.3 whats newにも記載されていますがKotlinのPostfix Completionが先行して使えるようになっている。

Postfix Completionというのは以下のGIFのようなコード補完機能です

f:id:matsuokah:20161204171400g:plain

いわゆるLiveTemplateをその変数にスコープを絞った機能といった所。

以下のGIFはLiveTemplateで同じコードを書いた場合。変数を絞り込んでいく手間を感じる。

f:id:matsuokah:20161204171834g:plain

ちなみに、Android Studio 2.2ではまだ使えない

blog.jetbrains.com

上記の記事によると

Note that the feature depends on platform changes made in IntelliJ IDEA 2016.2 and is therefore unavailable in Android Studio 2.2;

ということで、Android Studio 2.2ではこの恩恵を授かれない。LiveTemplateは使える。

もちろん、IDEとしての機能はIntelliJを使ったほうが先に使えるので、そのアドバンテージはあると思います。

デメリット: IntelliJのほうがAndroidの最新機能を使えるようになるのが遅いかも

Android Studi 2.2 Release
-> 2016/09/19 Release!

IntelliJ IDEA 2016.3 GA: Java 8 and ES6, Debugger and UI improvements, and a Ton More
-> 2016/11/22 Release

  1. IntelliJ 新機能(Android Studioのベースとなるバージョン)
  2. Android Studio(ここでAndroidの機能が追加)
  3. IntelliJ(IntelliJAndroid Studioと同等の機能が追加される)

というアップデート順だとしたら、Androidの新機能が使えるようになるのは若干遅いかも?

Android Studioで試験的に導入してから、IntelliJに導入してるのだろうか。

Android StudioからIntelliJへの移行をするには?

Android SDKを設定する

  1. Android Studioの設定からAndroid SDKのパスを設定する

  2. Confiture > Project Defaults > Project Structure f:id:matsuokah:20161204172242p:plain

  3. SDK > + > Android SDK f:id:matsuokah:20161204172331p:plain

これでAndroidプロジェクトが作成・ビルド可能になります。

f:id:matsuokah:20161204173032p:plain

見慣れた編集画面。

Kaptを使っている場合はgenerateStubsを有効化する

kapt {
    generateStubs true
}

上記の設定を入れるだけで筆者の環境ではビルドできた。

before : 17sec after : 20sec

コンパイル時間が若干、長くなる。

参考:
qiita.com

IntelliJユーザーとAndroid Studioユーザーが共存できるのか?

できます。 Code Styleの設定ファイルなんかも、形式が同じなのでAndroid Studioの設定をExportしてIntelliJに読み込むとも可能

メルカリでロードバイクを売った話と防犯登録の手続きでハマった話※追記あり

全然、最近乗ってなかったので持ち腐れと思いメルカリで売ってみた。その時の話。

自転車を譲渡するって意外と大変だなーって思った事が意外とあった。
特に自転車の場合は防犯登録があるが、手続きの順序をしらないと手間が増えるのでメモ書き程度に残してみた。

TR;DR

1. メルカリで売ってみる

実は使ったことがなかったので、売るシステムがどんなものか知りたくて使ってみた。

写真を投稿する

写真は約4枚。ロードバイクの全体像、おまけ、そして保証書(シリアルナンバー)の写真を投稿した。

価格の設定

強気に設定してたら何度か値段交渉をされましたが、どれもYahooオークションでの相場を遥かに下回る価格だった。
そういうもんかと思ってたら、メルカリの通知で「このくらい下げてみましょう」というサジェストが来た。

実際下げてみると、だいたい妥当な交渉額が提示されたのでそれで手を打つこととした。

合計30万くらいかかったロードバイク・アクセサリが14万円で売れた。
ロードバイクは型落ち品の値落ちが激しい部類のようで、他のバイクもだいたいそんなもんだった。

交渉ははっきり断る

個別で販売するのが面倒で、アクセサリをおまけとして売っていたら、別売のコメントがいくつもついた。
全部断った。何度も運送会社とやり取りするのがだるい。

2. ロードバイクを送る

他のロードバイク販売者の輸送方法をみてたらカンガルー自転車輸送便が紹介されていた。
最初はヤマトなどを使おうと思っていたが、他の運送会社では自転車を扱う場合には大きい荷物として送るので、輸送費が非常に高くなってしまうようだった。

カンガルー自転車便はレンタル箱代と輸送費で1万円以内に収まるので割安で送ることができる。

  1. 輸送申請(料金前払い)
  2. 輪行箱が届く
  3. 集荷
  4. 配達

という流れになっていて、輸送申請から集荷までは約1週間かかった。輪行箱が届く日は申請日から3, 4日以降でないといけないらしく気長な感じ。

箱が届く

f:id:matsuokah:20161127161612j:plain

フタはこんな感じ

f:id:matsuokah:20161127161613j:plain

フタには説明書が貼り付けてある

f:id:matsuokah:20161127161614j:plain

箱の横面には高価品などの扱いが書かれている。

f:id:matsuokah:20161127161618j:plain

前輪を外していれる

f:id:matsuokah:20161127161619j:plain

フロントフォークに傷がつかないようにプチプチで包んで送りました。

すっぽり入る

f:id:matsuokah:20161127161621j:plain

ハンドルを曲げて入れる必要があったのと、ペダルを外す必要があった。
ペダルレンチを持ってなかったので、近くの自転車ショップに持っていって外してもらった。

ペダルもプチプチに。

受取の評価を待つ

メルカリでは受取人の評価と販売人の評価をして初めてお金が入るシステム。 それによってトラブルが起きないようになっているようだった

簡単に出品できたのと手数料がヤフオク(落札額の10%)に比べて格安だったのでなかなかよかった。

防犯登録の抹消と再登録

抹消は本人がするか、譲渡先に書類を渡すことで再登録の手続きと同時に行うことができる。

正しくは

抹消は本人がするか、譲渡先に書類を渡すことで再登録の手続きと同時に行うことができるのは同じ都道府県内の譲渡のみ。譲渡先と都道府県が一致しない場合は管轄が変わるため、先に抹消手続きを完了してからでなければ、他県で手続きすることができない。

神奈川県の自転車防犯協会に問い合わせた所、上記のような回答がもらえた

必要な書類とは

  • 防犯登録のときにもらった防犯登録のお客様控え
  • 譲渡証明書

のどちらか。

神奈川県の自転車防犯協会によると、

譲渡証明書の書式は定めておりません。サンプルがありますのでダウンロードしてご使用ください

と、サンプルが載っている。これは自治体ごとに必要書類が変わるかもしれないので、譲渡元と譲渡先の防犯登録の管理団体に問い合わせるのがベスト

marble diagram

marble diagramとは

Reactiveプログラミングの説明に使われるあの図の名前。

f:id:matsuokah:20161109005612p:plain

RxMables#mapより転載

X軸を時間、Y軸をストリームとしていて、4つの登場人物は以下の通り

○: input data event
X: error event
|: complete event
中間の□: transformer

つまり、

データ入力イベントが発火→transformerでデータの変換→出力という一連の流れを表している。

何のために使われている?

Reactive Programmingは数多くのオペレータ(transformer)があります。その役割の説明のために使われている。