ページ

2017年12月17日日曜日

kotlin入門1

kotlin
絶滅しないようにkotlinの勉強を進めていこうかと思いますw
今回はkotlin自体の基本的なところを見てみます。

様々なプラットフォーム

  • Kotlin for Server Side
  • Kotlin for Android
  • Kotlin for JavaScript
    • KotlinをJavaScriptにコンパイルする
  • Kotlin/Native
    • Kotlinのコンパイラ LLVMを使っている様子
知らない間に色々ある。。。

:pencil: 基本実装


変数

kotlin
fun main(args: Array<String>) {
    val a: Int = 1  // Int型として変数宣言かつ値代入
    val b = 2   // `Int` 型を推論
    val c: Int  // 値代入しない場合は型は必須
    c = 3       // 後で値を設定
    println("a = $a, b = $b, c = $c") // a = 1, b = 2, c = 3
}

文字列テンプレート

kotlin
fun main(args: Array<String>) {
    var a = 1
    // 文字列中に`$a`で値を展開できる
    val s1 = "a is $a" 

    a = 2
    // 展開時に式も書ける
    val s2 = "${s1.replace("is", "was")}, but now is $a"
    println(s2) // a was 1, but now is 2
}

メソッドの書き方

  • 2つのInt型の引数をとって1つのInt型の戻り値を返す
    kotlin
    fun sum(a: Int, b: Int): Int {
        return a + b
    }
    
  • 上のはこんな感じでも書ける
    kotlin
    fun sum(a: Int, b: Int) = a + b
    
  • 戻り値が無い場合
    kotlin
    fun printSum(a: Int, b: Int): Unit {
        println("sum of $a and $b is ${a + b}")
    }
    
  • Unitは省略できる
    kotlin
    fun printSum(a: Int, b: Int) {
        println("sum of $a and $b is ${a + b}")
    }
    
  • if-expressions.
    kotlin
    fun maxOf(a: Int, b: Int) = if (a > b) a else b
    
    fun main(args: Array<String>) {
        println("max of 0 and 42 is ${maxOf(0, 42)}") // max of 0 and 42 is 42
    }
    
  • nullが返るかもしれない場合 Int?みたいにかく
    kotlin
    fun parseInt(str: String): Int? {
        return str.toIntOrNull()
    }
    

is オブジェクトがキャスト可能か調べる

kotlin
fun getStringLength(obj: Any): Int? {
    if (obj is String) {
        // `obj` is automatically cast to `String` in this branch
        return obj.length
    }

    // `obj` is still of type `Any` outside of the type-checked branch
    return null
}

for ループ

kotlin
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
    println(item)
}
// or
val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
    println("item at $index is ${items[index]}")
}

when - switchみたいなもの

kotlin
fun describe(obj: Any): String =
when (obj) {
    1          -> "One"
    "Hello"    -> "Greeting"
    is Long    -> "Long"
    !is String -> "Not a string"
    else       -> "Unknown"
}
fun main(args: Array<String>) {
    println(describe(1)) //One
    println(describe("Hello")) // Greeting
    println(describe(1000L)) // Long
    println(describe(2)) // Not a string
    println(describe("other")) // Unknown
}

range

kotlin
for (x in 1..5) {
    print(x) // 12345
}

collection

kotlin
fun main(args: Array<String>) {
    val items = setOf("apple", "banana", "kiwi")
    when {
        "orange" in items -> println("juicy")
        "apple" in items -> println("apple is fine too")
    }
} // apple is fine too
リスト内に特定の文字が含まれているかチェックできる!
kotlin
fun main(args: Array<String>) {
    val fruits = listOf("banana", "avocado", "apple", "kiwi")
    fruits
    .filter { it.startsWith("a") }
    .sortedBy { it }
    .map { it.toUpperCase() }
    .forEach { println(it) }
} 
// APPLE
// AVOCADO

クラス

kotlin
fun main(args: Array<String>) {
    val rectangle = Rectangle(5.0, 2.0) //no 'new' keyword required
    val triangle = Triangle(3.0, 4.0, 5.0)
    println("Area of rectangle is ${rectangle.calculateArea()}, its perimeter is ${rectangle.perimeter}")
    println("Area of triangle is ${triangle.calculateArea()}, its perimeter is ${triangle.perimeter}")
}

abstract class Shape(val sides: List<Double>) {
    val perimeter: Double get() = sides.sum() // getterの`perimeter`プロパティ
    abstract fun calculateArea(): Double
}

interface RectangleProperties {
    val isSquare: Boolean
}

// Primary なコンストラクタは`height`と`length`の引数を受け取る
class Rectangle(
    var height: Double,
    var length: Double
) : Shape(listOf(height, length, height, length)), RectangleProperties {
    override val isSquare: Boolean get() = length == height
    override fun calculateArea(): Double = height * length
}

class Triangle(
    var sideA: Double,
    var sideB: Double,
    var sideC: Double
) : Shape(listOf(sideA, sideB, sideC)) {
    override fun calculateArea(): Double {
        val s = perimeter / 2
        return Math.sqrt(s * (s - sideA) * (s - sideB) * (s - sideC))
    }
}
// Area of rectangle is 10.0, its perimeter is 14.0
// Area of triangle is 6.0, its perimeter is 12.0

2017年12月10日日曜日

改めてReactをやってみる1

少し前にReactやったが、時間が過ぎたので改めてやってみる。

React

:computer:環境構築


Create React App というものが用意されているらしい。
折角なのでそれを使って環境を構築してみる。
sh
$ npm install -g create-react-app
$ create-react-app react-sample
Editor
こちらにおすすめパッケージやらが乗っている
とりあえずAtom使いなのでlanguage-babelはインストール

:pencil: 実装


簡単なサンプル

チュートリアルにもあるように一旦src/*のファイルを削除
index.cssindex.jsを追加し、index.jsを以下のように修正
js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
yarn startすると空のページが表示される。

コンポーネントを作る

チュートリアルにあるサンプルのコンポーネントを試してみる
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

ReactDOM.render(<ShoppingList name="Mark" />, document.getElementById('root'));
実行結果
image.png (15.3 kB)

:bomb: バッドノウハウ


create-react-appでエラー
error An unexpected error occurred: "https://registry.yarnpkg.com/setimmediate: socket hang up".
info If you think this is a bug, please open a bug report with the information provided in "/Users/xxxxx/react-sample/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
Error: socket hang up
    at TLSSocket.onHangUp (_tls_wrap.js:1124:19)
    at TLSSocket.g (events.js:292:16)
    at emitNone (events.js:91:20)
    at TLSSocket.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickCallback (internal/process/next_tick.js:104:9)
Error: socket hang up
    at TLSSocket.onHangUp (_tls_wrap.js:1124:19)
    at TLSSocket.g (events.js:292:16)
    at emitNone (events.js:91:20)
    at TLSSocket.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickCallback (internal/process/next_tick.js:104:9)
原因: 自分の場合はウィルス対策ソフトを一時的に無効化したらすんなり通った。。

:link: 関連リンク


2017年11月28日火曜日

AmazonFireTV上で動くアプリを作る


FireTV用のアプリは大きく
  • Androidアプリ
  • Webアプリ
の2つある。

FireOS用と通常アプリの違い

  • FireOS
    AndroidからフォークされたOS
    (拡張範囲はLollipopおよびバックポートされたMarshmallowコードまで)
  • Fire TVでは、AndroidのLeanback Support Libraryが一部サポートされている
    CATEGORY_LEANBACK_LAUNCHERがFire TVでは認識されない
  • Google Play Servicesが使用できない
詳しくはこちら

:computer:環境構築


通常のAndroidアプリの様にAndroidStudioを使う

ADB接続

  1. Amazon Fire TVでデバッグを有効にする
  2. Android Debug Bridgeを設定する
  3. 接続
sh
$ adb kill-server
$ adb start-server
$ adb connect <IPアドレス>
詳しくはこちら

:pencil: 実装


簡単なサンプル

サンプリとしてFire App Builderが公開されている
詳しくはこちら

AndroidTV

ベースはAndroidTVでいけるらしいので、
簡単なサンプルをAndroidTV用プロジェクトで作成してみる。
  1. 新規プロジェクトでTarget DeviceをTVにする
  2. 「Add No Activity」を選択
  3. 「MainActivity」を作成
    java
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    }
    
  4. activity_main.xmlを作成
    xml
    <?xml version="1.0" encoding="utf-8"?>
    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main_browse_fragment"
              android:name="com.slowhand.androidtvsample.MainFragment" android:layout_width="match_parent"
              android:layout_height="match_parent" tools:context=".MainActivity" tools:deviceIds="tv"
              tools:ignore="MergeRootFrame" />
    
  5. MainFragmentを作成
    java
    public class MainFragment extends BrowseFragment {
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
        }
    }
    
とりあえずここまでで何も表示されない画面ができる
image.png (152.1 kB)
BrowseFragment
HeaderFragment (ヘッダー) が右側、 RowsFragment (コンテンツ部分) が左側の構成を含むFragment

AndroidManifest.xml

Launcherとして表示させるには以下の様に修正
xml
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />

2017年9月15日金曜日

複数アカウントでFirebaseCLIを使う

個人や会社のアカウント等、プロジェクト毎にアカウントが違うような
複数アカウントでFirebaseCLIを使う時に自分がやっている方法です。
(他に良い方法があればご教示ください)


状態


すでにfirebase loginしててログイン済み
$ npm install -g firebase-tools
$ firebase login

configstore


firebase-toolsconfigstoreを使ってアカウント情報を
~/.config/configstore/firebase-tools.jsonに保存している。
また、configstoreはデフォルトでは~/.configを見に行くが
XDG_CONFIG_HOMEの環境変数が設定されていればそちらを見に行く。

direnv


ディレクトリ毎に環境変数を定義してくれるdirenvを使用して
各プロジェクトのルートディレクトリに移動した時にXDG_CONFIG_HOMEを変えます
各プロジェクトのルートディレクトリに.envrcを配置
export XDG_CONFIG_HOME=~/.config-xxxx
こんな感じにして、事前にログインした~/.config/configstore/firebase-tools.json
~/.config-xxxx/configstore/firebase-tools.jsonにコピーします。
するとプロジェクトに移動した時点で
> cd  XXXXX
direnv: loading .envrc   
direnv: export +XDG_CONFIG_HOME
環境変数XDG_CONFIG_HOMEが設定されます。

アカウント確認方法


$ firebase list
でプロジェクト一覧が見れます。