xiaomiが日本についにやって来る
世界トップクラスのスマホメーカーxiaomiがとうとう日本に来るみたいですね。
Xiaomiの日本参入は12月9日 Twitterで発表 「予定よりも早く会える」 - ITmedia NEWS
xiaomiといえばなんといっても他メーカーであれば10万クラスのハイエンドスマホが約半額くらいで買える高コスパが魅力。
スマホの技術も頭打ちして、消費者も価格を重視している昨今、国内スマホ市場の黒船になりうる存在でしょう。
ただ、あの価格設定で国内スマホ市場に参入するとあっという間にシェアを席巻されかねないので、おま国価格になってしまうんじゃないかなー、と個人的には危惧してます。
今まで日本市場に参入してこなかったのも、市場独占を恐れた日本側が参入を阻んでいたのではと思ってますし。
一部では反日企業だから日本市場に入って来なかったのでは?みたいな話もありますが
中国スマホ大手「日本語専攻出て行け」 抗議相次ぎ謝罪:朝日新聞デジタル
中国人は合理的ですから、そんな理由で日本市場を無視していたとは思えないですね。
それにだいぶ前からxiaomi端末は日本語に対応してますし、参入する気は満々だったが外部的な要因で参入出来てなかったんだろうなと思ってます。
個人的にはミクフォンを日本でも発売してほしい…
シャオミが初音ミクスマホ Miku Special Edition Xiaomi Mi 6X発表 - Engadget 日本版
ポケモンはバグ技使ってもあまり叩かれてないのはなぜか
ポケモン剣盾がリリースされて、発売前はリストラ問題だので色々叩かれたもののフタを開けてみればやはりポケモンブランドということもあり、売れてるし皆やってますね。
そんなポケモンですが『ワット』っていうゲーム内で使うポイントが本体の日付設定と通信を使って無限に増やせるバグが有って
まあ、Twitterとか見てるとみんなコレを使って金策やら厳選をしておるのです。
例えば自分がやっているレイボーシックスシージだとこの手のバグを使った技はグリッチだ何だで
やってるなんて言おうもんならめちゃくちゃに叩かれるのですがポケモンではそういう風潮は一切ないですね。
PvPに直接的には関係ない部分にせよ、厳選とかはPvPのためにやっているわけで間接的には無関係とは言い切れないと思うのだけれど。。。
ポケモンとバグ
なんで叩かれないのか考えたときに、ポケモンにはバグを許容する文化っていうか風潮みたいのが前からあるような気がする。
初代の頃から割とバグだらけで、アイテム無限増殖バグや100レベのバグやらミュウのバグが裏技ってことでポジティブな文脈で語られている。
そのへんのバグは二作目以降は修正されているが、伝説と戦う前にレポートして捕まえられなかったらリセットしてやり直すっていうのは以降も結構定番の技だった。
これも仕様の穴を突いたバグに近い技のような気がするが。
今作でこそ伝説は確定で入手できるようになっていてこの技はなくなったが
伝説の厳選をするのであればこの技は必須だ。
そのようなポケモンシリーズの歴史があるからこそバグに寛容な今の風潮が生まれている気がする。
ストーンズ原野巣Jで太い光を出してメタモンリセマラをするのなんて、作業内容的には初代から受け継がれる伝説リセマラとほぼ同じだ。
ゆえにこのバグ技利用をあーだこーだ言う人は少ないのかもしれない。
とはいえ、バグ技は作業ゲー感が強すぎて面白くない、というか何なら苦痛でしかなかった
ワット目当てにワイルドエリアを駆け回ってる方がゲームとしては楽しいので、遊び方としてはこっちがオススメだ。
更新滞ってたのでブログについて考えるゾ
はい、3ヶ月ぶりに書いてます。
忙しかったとかじゃなくて単純にめんどくさくなってヤメてました。
で、そんな私がなんで今更浮上したかというと、、
やっぱりアウトプットは大事
前の会社が企画系の会社で、常にガンガン情報をインプットしてガンガンアウトプットしていく風土があったんですけど
今の会社はまあ、むしろ真逆な感じでアウトプットする習慣がなくなっちゃったんですよね。
その結果、情報収集する機会は減るわ、たまにニュースとか見ても何の感動も覚えないわで、あっこれはマズイぞと思ったわけです。
そんな訳でもう一回ココを活用していこうと。
なんで更新が途切れたか考えて今後の方針
★とりあえず毎日更新する
毎日やらないと3日位いいやが1週間になって結局3ヶ月になってしまうので、ここは無理をするポイントなのかも。
★プログラムメインのブログにしようと思ってたけどやめる。
プログラムのこと書かないとって切迫感がよくなかった気がする。ニュースでもゲームでもアニメでも生活でも何でもいいからアウトプットしよう。
別に収益化とかが目的ではなく自己満のアウトプットが目的なのだから、ジャンルは絞る必要なし。
★短文でもいいから更新する。
正直PCから毎日まとまった記事だすとか忙しくなったら無理なんで、スマホからニュースサイトのリンクベタ張り、コメントを一言だけってのもアリで。
そんなクソ記事もまとまった量になれば見れるようになるから。
★カッコいいの禁止
禁止はまあ言いすぎですけど、なんかカッコいいこと言おうとして調べたり文章を推敲しすぎたりで疲れて更新滞ってしまう気がするのでカッコいいのもほとほどに。
まあカッコイイこと言おうとして色々調べるのも大事だったりするんだけど、ここは一旦ほとほどに抑えて。
かっこ悪くてもいいから毎日書きましょう。
★タグはちゃんと付けよう
たぶん以上の更新方針だと、駄文散文だらけになるので、いい感じにまとめられるようにタグで整理しよう。
★画像の挿入もほどほどでいいぞ
前やってた時は見た目に癒し?が欲しいとか思って適当にアニメの絵とか入れてたけど、まあそれが逆に負担になってたとこあったんでそれもやりたかったらやれば?って感じで。
現状、萌にそんな興味なくなっちゃったしな〜。
とまあ、以上今後の方針!
次は何日持つのか…
【kotlin】関数についてのお話
表題の通り、まず「関数」周りの章をやっていてのメモ書き。
Javaの参考書とかに比べて関数・ラムダについての機能やらが手厚い印象ですね。
・単一式関数
コード量を減らすテクニック的なもの
自分で使うことはあまりないかもだけど
他人のコードを読んだ時に慌てないようにメモ
fun myFunction(int : Int): String{ val test = if (int == 0){ "it is ZERO" }else{ "it is not ZERO" } return test }
上のコードは以下の形で書き換えることができる。
fun myFunction(int : Int) = if (int == 0) { "it is ZERO" }else{ "it is not ZERO" }
今までの自分の感覚だと
「関数は何かを返すためのもの」
というイメージだったのが、このコードを見ると
なんというか、関数を変数とかと同じように定義している?みたいな?
うまく説明できないけど関数に対する新しいイメージをつかめました。
・Nothing型
Unit型の説明に付随して説明されました。
なかなかにふーんと思ったのでメモ。
Nothing型の関数は
「コンパイラに関数が決して正常に完了しないことを保証する」関数です。
一体こんなもん何に使うのかというと
interfaceとかをクラスに実装した時に出てくるTODO()で使っています。
/** * Always throws [NotImplementedError] stating that operation is not implemented. */ @kotlin.internal.InlineOnly public inline fun TODO(): Nothing = throw NotImplementedError()
豆知識みたいなもんですが、面白かったので。
・無名関数
書には「kotlinの本質的な部分」とあります。
それほど大事なことなのです。
この無名関数でできることの一つは
「標準ライブラリ関数にルールを追加することで、その振る舞いをカスタマイズできる」
どういうことなのか見ていきます。
val test = "kokinwakashu".count ({letter -> letter == 'k' })
ここのcount関数を呼び出すのに使っているドットは「ドット構文」(そのまんま)という。
ドット構文は型の一部として含まれている関数を呼び出すのに使う。
このコードでは変数testに"kokinwakashu"というStringに含まれている"k"の数を代入している。
ここでcount関数のコードを見てみる。
/** * Returns the number of characters matching the given [predicate]. */ public inline fun CharSequence.count(predicate: (Char) -> Boolean): Int { var count = 0 for (element in this) if (predicate(element)) ++count return count }
ここで注目して欲しいのは、count関数の引数の型。
この"predicate: (Char) -> Boolean"はブーリアン型を返す無名関数を意味する。
つまり、このメソッドは引数としてboolean型を返す関数を要求している。
この無名関数は前述のコードで言うところの"letter == 'k'"にあたる。
無名関数についてのもっとわかりやすい例は以下
println({ val day = "0707" "hello!! today is $day" }())
{}で括られた箇所が関数の定義
これまで関数は名前をつけて定義した上で使っていたが
その作業を省略して、直接使っているようなイメージ。
この無名関数も実はIntやStringのような型を持っており
その型の名前を"関数型"という。
他の型と同様に関数型も変数を定義することが可能で
その方法で先ほどのコードを書き直すと以下になる。
val sayHelloWithDate: () -> String = { val day = "0707" "hello!! today is $day" } println(sayHelloWithDate())
sayHelloWithDate()メソッドでは
String型を返しているが、無名関数の場合は"return"キーワードを使わない。
無名関数においては暗黙的に関数定義の最後の行を返す
そのため、基本的には"return"キーワードは許容されない。
・無名関数に引数を渡す
先ほどの関数の引数を渡してみる。
val sayHelloWithDate: (String) -> String = {name -> val day = "0707" "hello, $name!! today is $day" } println(sayHelloWithDate("taro"))
引数としてString型を受け取れるようにした。
まず型定義で一つのStringを受け取ることを指定。
そのパラメータを関数内で扱う際の名前を、開き波カッコの直後に定義。
名前の後に矢印を書いて、以降に関数処理を書いていく。
また、引数が一つだけの場合は"it"キーワードを使うことで
引数の名前の定義を簡略化することができる。
val sayHelloWithDate: (String) -> String = { val day = "0707" "hello, $it today is $day" } println(sayHelloWithDate("taro"))
"it"は暗黙的にパラメータを指す。
コード量を減らす上では有効だが
多用するとコードが読みにくくなるので
使いどころには注意が必要。
複数の引数を受け取る場合は以下となる。
val sayHelloWithDate: (String, Int) -> String = { name, year -> val day = "0707" "hello, $name today is $year $day" } println(sayHelloWithDate("taro", 2017))
引数が複数ある場合は"it"は使えない。
・型推論を使う
型推論を使うことで無名関数の返り値を明示せずに使うこともできる。
型推論なし
val sayHelloWithDate: () -> String = { val day = "0707" "hello!! today is $day" }
型推論あり
val sayHelloWithDate = { val day = "0707" "hello!! today is $day" }
引数がある場合は書き方がちょっと変わるので注意。
val sayHelloWithDate = { name: String, year: Int -> val day = "0707" "hello, $name today is $year $day" }
・関数を受け取る関数の定義
val sayHelloWithDate: (String, Int) -> String = { name, year -> val day = "0707" "hello, $name today is $year $day" } fun aisatsu(name: String, sayHello: (String, Int) -> String ){ val year = 1999 println(sayHello(name,year)) } fun test(){ aisatsu("emi", sayHelloWithDate) }
sayHelloWithDate が無名関数
aisatsuメソッドがString型と「第一引数にStringを第二引数にIntをとる無名関数」を引数にとる。
実際に使う際はtestメソッドの中のような感じで。
・インライン化
無名関数(ラムダ)は便利だが利用するのにはコストがかかる。
ラムダは一つ定義すると、JVM上で1個のインスタンスオブジェクトとして表現される。
また、ラムダが利用できる全ての変数に対してメモリ割り当てを実行するので、メモリのコストが発生する。
その結果、ラムダによるメモリのオーバーヘッドが加わり、性能に影響が及ぶ可能性もある。
このリスクを回避するために用いるのが"インライン化"である。
インライン化する方法は簡単で、ラムダを受け取る関数にinlineキーワードをつけるだけだ。
inline fun aisatsu(name: String, sayHello: (String, Int) -> String ){ val year = 1999 println(sayHello(name,year)) }
こうすることでオーバーヘッドのリスクを回避することができる。
しかし、このインライン化は使用できない場合もある。
例えばラムダを受け取るのが再帰関数の場合などはインライン化を行うことはできない。
・関数リファレンス
名前付き関数を引数として用いたい場合は関数リファレンスを使う。
val sayHelloWithDate: (String, Int) -> String = { name, year -> val day = "0707" "hello, $name today is $year $day" } fun aisatsu(name: String, testPrintMethod: (String) -> Unit ,sayHello: (String, Int) -> String ){ val year = 1999 testPrintMethod("") println(sayHello(name,year)) } fun testMethod(test: String){ println(test) } fun test(){ aisatsu("taro", ::testMethod, sayHelloWithDate ) }
名前付き関数を引数として使いたい場合の引数の書き方は
aisatsuメソッドの第二引数。
aisatsuメソッドを実際に使う場合の書き方はtestメソッドにて。
今回はここまで。
関数型はkotlinを使う上では重要だが
書き方がちょっと特殊な感じがするので
慣れるまでに時間がかかりそうだなーと。。。
【kotlin】使う参考書と書き方について
予告した通りkotlinについてやっていきます。
使っている参考書
"kotlin"についての参考書が少ない昨今
"AndroidStudioの中のkotlin"ではなく"kotlinという言語"について解説してくれている貴重な書だと思います。
それも、かなり基礎的なところから教えてくれる。
著者が日本人ではないので
翻訳調の日本語が苦手という人にはちょっとしんどいかも
個人的には全然読みやすい部類ですが。
あと、Amazonのレビューを見てると
「RPGの用語に例えまくっているのが非常にわかりにくい」
みたいなレビューがありますが
逆にいうとゲームが好きな人にはかなりわかりやすいので
ゲーム好きプログラマーにはむしろオススメかもしれないですね。
あと、記事更新の方針ですが。
とりあえずこの本をやりながら気になった箇所とか覚えておこうと思った箇所を掻い摘んでメモっていくような形式にします。
ブログの全体の見易さの事情とかで、今回は短いですが
一旦、こんなもんで切ります。
【Androidプログラム】AABファイルの作成やってみた
表題についてやります。
kotlinの勉強も並行してやってるんですが
業務でAABについて扱ってせっかくなので書きます。
そもそもAABファイルとは?
Androidアプリを動かす際
これまではAPKファイルというものを端末に入れたり、ストアに登録したりしていました。
APKファイルにおいては端末やバージョンごとの違いに対して
1つのAPKファイルで対応していました。
そのため、一つのAPKファイルの大きさは場合によってはかなり大きなものになってしまいます。
一方でこのAABファイルというものは
いうなれば「APKファイルの生成機」でそれぞれの端末やバージョンに最適化されたAPKを発行してくれるものになります。
これを使うことで個々のAPKファイルの大きさは小さくなり
アプリのダウンロードサイズを小さくすることができます。
発行の準備
AABファイルの発行には以下の準備が必要になります。
・build.gradle のバージョンを3.2以上にする
・AndroidStudioのバージョンを3.2以上にする
build.gradleについては以下であげることができます。
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
gradle/wrapper/gradle-wrapper.properties で
distributionUrlを
"https\://services.gradle.org/distributions/gradle-5.1.1-all.zip"に設定
build.gradleをあげると色々なエラーが起きるので対応していく
エラーの内容はプロジェクトによって千差万別だとは思いますが
自分のプロジェクトで起きたことについて書いていく。
"fablic"周りと思われる箇所でSyncさせた際に以下のようなWARNINGが発生。
WARNING: API 'variant.getJavaCompile()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'
ひとまずググってみるとfabricのバージョンを最新にしてやると直るみたいなことが書いてあったので
gradleのdependenciesにて
classpath 'io.fabric.tools:gradle:1.+'
→ classpath 'io.fabric.tools:gradle:1.29.0'
を試してみたがこれは意味なかった。
もっと探していくと良さげなサイトを見つけたのでそこに倣ってやっていく
とりあえずエラーの箇所がわからないとどうしようもないので以下のコードでエラー箇所を発見できるようにする。
gradle.properties に
android.debug.obsoleteApi=true と記入。
これでエラーの箇所を特定可能になる。
すると"variant.getJavaCompile"ではなく"variant.javaCompiler"が問題だと判明
"variant.javaCompiler"は"variant.javaCompileProvider.get()"に書き換えられるみたいなので書き換える。
この方法で該当のワーニングはでなくなったが、次は新たに以下のワーニングが発生。
API 'variant.getAssemble()' is obsolete and has been replaced with 'variant.getAssembleProvider()'.
この発生箇所については"current state"とあるだけで具体的な場所ははっきりせず。
ググると無理やり直す方法もあるらしいが、Google様が対応してくれるのを待つ方が良いみたいなので
これは放置しておく。
動かないわけではないし
ついでにandroidxに対応させる
「Refactor -> Migrate to AndroidX…」で「Do Refactor」すれば自動でリファクタまでやってくれるのでこれは簡単。
外部ライブラリを使っている場合などは対応できない場合があったりするので
そこはライブラリの更新などを確認して、適宜対応する。
実際にAABを発行してみる
発行自体は簡単で
メニューのBuild>APK/BuildBundles>BuildBundles から発行できる。
発行したら、発行完了の通知とともにファイルの場所も案内されるのでファイルを確認。
https://github.com/google/bundletool/releases
上のjarファイルを使ってaabからapksファイルを発行する。
apksファイルはその名の通り、apkの集合体のようなファイルで
そのままだと結構容量が大きい。
apksを発行するコマンドは以下。
$ java -jar bundletool-all-0.7.1.jar build-apks \
--bundle=app.aab --output=app.apks \
--ks=keystore.jks --ks-pass=pass:PASSWORD --ks-key-alias=ALIAS \
--key-pass=pass:PASSWORD
キーストアとかは無しでも発行自体は可能だが
端末で動かしたりする際は必須。
apksを端末で動かす
端末をPCに繋いで以下のコマンドを叩けばインストールできる。
$ java -jar bundletool-all-0.7.1.jar install-apks --apks=app.apks
なお、環境によっては環境変数の設定を求められることもあるので
その場合は以下のように設定した上でコマンドを叩く。
export ANDROID_HOME="/Users/name/Library/Android/sdk"
コマンドをたたいてその処理が終了するとアプリが端末に自動でインストールされているので、コマンドをたたく前に端末内に同名アプリがある場合は消しておくこと。
デバッグしてる時とかはありがち。
ちなみにbundletoolでデバイス情報が観れるらしいが
$ bundletool get-device-spec --output essential.json
で端末のスペック情報が取得できるらしいが、これは以下のエラーが出る。
[BT:0.10.0] Error: null
java.lang.NullPointerException
at java.nio.file.Files.provider(Files.java:97)
at java.nio.file.Files.exists(Files.java:2385)
at com.android.tools.build.bundletool.commands.GetDeviceSpecCommand.writeDeviceSpecToFile(GetDeviceSpecCommand.java:175)
at com.android.tools.build.bundletool.commands.GetDeviceSpecCommand.execute(GetDeviceSpecCommand.java:164)
at com.android.tools.build.bundletool.BundleToolMain.main(BundleToolMain.java:83)
at com.android.tools.build.bundletool.BundleToolMain.main(BundleToolMain.java:46)
色々試したけどこいつは原因不明ダレカタスケテ
【プログラミング】Vimについて簡単に備忘録
前回告知したとおり、Vimについて簡単に書いていきます。
今のこの記事もVimで書いています。
なんともcommand + 矢印キーで行の端に飛べないし、行の左端で←キー押しても上の行に行けないしでなんとも慣れない。。。
・Vimにはモードがある
vimには通常のノーマルモードと編集用のインサートモードの二つのモードがあり
インサートモードでの操作中は原則としてカーソル移動をしない(マジか・・・)
入力漏れなどを見つけて書いたテキストを変更したい場合は
一旦ESCキーを押してノーマルモードに戻った上でカーソルを移動するとか、、、
カーソルの移動
k → 上
j → 下
h → 左
l → 右
軽く操作してみると、まあ慣れてないのでやりにくい
このキーバインドにした必然性も見えてこないし
ゲームやってる身としてはwasdの方がよいのでは?と思ってしまう。
とはいえ、もう何十年も使われているであろうキー配置なんだし
使っているうちに必然性も見えてくるだろうと思っておく。
基本的な操作
x で文字の削除
i でインサートモードへの変更ができる。
o で次行を新規行として挿入してインサートモードへ(今の行の下に追加)
O で現在行に新しい行を追加してインサートモードへ(今の行の上に追加)
日本語で文章書いてるからなんでしょうが
ノーマルモードになった後には必ず"英数"キーを押さないとコマンドが効かないのがめんどい
ファイルの操作を行うコマンド
:w で上書き保存
:w "name" で"name"というファイル名で保存
:q で編集終了
:wq で保村して終了
:e でファイルを開く
ちなみにvimでは上書き保存していない編集中のファイルを閉じようとすると怒られる
編集したけど保存しないで閉じる場合は":q!"のように最後に"!"をつける事で強制的に操作を行える。
Swiftとかkotlinの強制アンラップみたいですね。
移動に関するチートシート
w で次の単語の先頭へ
e で単語の最後へ
b で前の単語の先頭へ
0 で行頭へ
$ で行末へ
gg でファイルの先頭へ
G でファイルの最終行へ
% でマッチする文字へ移動(対応するカッコへの移動)
control + f で次のページへ
control + b で前のページへ
"w"とか”e”の単語関係のコマンド使った時に日本語の単語にもしっかり対応しててちょっと感動
"%"は()とか[]みたいなカッコ内での移動に便利だけど、この括弧は半角じゃないとコマンドは機能しないので注意
操作に関するチートシート
y でヤンク(コピー)
Y で行をヤンク
p でペースト(プット)
P で現在位置にペースト(プット)
x でカーソル下の1文字を削除
d で削除
D で行内のカーソル以降を削除
dd で行を削除
u で元に戻す
control + R で操作を進める
r で1文字変更
R で入力したもの全て変更
c で1文字消してインサートモードへ
C で一行消してインサートモードへ
A で行末に移動してインサートモードへ
a でカーソルの一つ右からインサートモードへ
I で行の始まりからインサートへ
> で右へインデント< で左へインデント
gu で小文字へ
gU で大文字へ
. で事前の操作を繰り返す
ヤンクについてですが、ただ"y"を押しただけだと一行丸々コピーされたり、一文字だけコピーされたりと挙動がちょっとよくわからない。
基本的には"Y"または”yy”で一行丸々コピーの形か、範囲選択して使った方がよさそう。
範囲選択の方法については、カーソルを選択開始位置に持って行って"v"で選択開始
選択を終了させたいところで"y"でOKだそうです。
ヤンクについてもう少し話します。
"y"でコピー(ヤンク)された文字列は無名レジスタに蓄えられる。
"c"とか"d"で削除された文字も同様
そのため、"y"で文字をコピペしようとしても、そのあとの操作で文字を削除すると上書きされてしまう。
また、"ayy"とか"bdw"とやってやることで、明示的に書き込むレジスタをしてしてやることも可能で
ペースト(プット)する際も"ap""bp"とすることで明示的に文字列を選ぶことができる。
ちなみに、さきほど上書きされてしまうと書いたが
実はヤンクを行なった際には"0"というレジスタにも自動的に書き込まれるため
"0p"でヤンクした値を貼り付けることができる。
あと、PCのクリップボードから貼り付けを行いたい場合は""*p"
"d"とか"gu"の処理はそのままだとヤンクと同様によくわからない挙動を示しているので
"v"を使って範囲指定してやるのがよさそう。
"x"と"r"は1文字に対しての挙動を示していそう。
検索に関するチートシート
f[アルファベット] で行内のアルファベットへ飛ぶ
/[word] でファイル内での単語検索
アルファベット検索は行内のカーソルより右側に対してのみ有効な模様
単語検索は単語打込み後エンターで検索し、次の候補がある場合は"n"で次に飛ぶ、前の候補に戻るときは"N"
以上の操作と移動のコマンドは組み合わせて使うことができます。
例えば"dw" で次の単語の先頭までの削除。
また、操作やモーションは回数指定が可能で
"10dd" で10行削除できる。
テキストオブジェクトのチートシート
iw は単語を指す
is は文を指す
it はタグを指す
i] はカッコを指す
テキストオブジェクトとは例えば
diw と入力するとカーソルの示す単語を消すことが可能。
dis なら示す文単位での削除が可能。
という風に使えます。
とりあえずはこのくらいでしょうか、全て使いこなせれば便利ですが
覚えるのは大変そう・・・
しばらくは横にカンペでも用意して使ってみようと思います。
以上。
今回参考にしたサイト
qiita.com
vi.chin3.net
cohama.hateblo.jp