androidアプリのスプラッシュが遅くて無意味問題が解決した
本来スプラッシュはアプリの読み込み待ちの間だけ見せるもので、iosではそれができるらしい。
iosのアプリではsplashあるからとかなんとか言われてandroidでも作らざるを得ないこと多いと思うけど 自分が作ったのも含めいままで見たことある実装は全部 アプリの読み込みが終わったあとわざわざ画像を見せて使用開始を遅らせるだけのsplashだった
googleカレンダーのスプラッシュ表示が異様に早くて、実装方法が検討つかなかったんだがlayoutなしのactivityにthemeでバックグラウンドを指定するらしい。
https://www.bignerdranch.com/blog/splash-screens-the-right-way/ ありがとうございます。
git instaweb の lighttpd で undefined symbol: FAMNoExists
Ubuntu 16.04 で git instaweb を見てみたかったんだけど下記エラー。
someone@somewhere:~/anyware$ git instaweb lighttpd: symbol lookup error: lighttpd: undefined symbol: FAMNoExists Could not execute http daemon lighttpd -f.
gamin を入れて治った。
sudo apt install -y gamin
Android アプリが OutOfMemory で落ちるときに確認を忘れがちなこと -> Bitmapのサイズ, src, View.INVISIBLE
確認した端末の環境
- Galaxy S6
- Android 6.0
- 普段の空きメモリ 600m くらい
結論
- 動的にリソース指定する ImageView に レイアウトしやすいからって xml 上の src に画像指定しない
アプリの内容と状況
- 大体全画面くらいのサイズの画像を2枚 ViewPager で 1枚ずつ全画面表示するタイミングがある
- Gallary のような。
- 今後増えるので ViewPager を使用
- 全画面大の画像は1枚あたりのサイズ 450k, 700k の png
- 80k と 370 k の png があるページを足したら OutOfMemoryError が出るようになった
- ViewPager での画像読み込みは Picasso 使用
当時の苦しみ
- 全画面で表示したいので小さいサイズで読み込めない
- そもそも 数百k 単位の画像数枚で OOM にまでなる ? 全部足しても 1.6m くらいなのに …
- 全画面大の画像はファイルサイズ最大 700k だったけど View に入った Bitmap は 64m
- bitmap だから当たり前だけど忘れていた…
作業内容
ログが長いので先に修正点から。 Android Studio の Android Monitor -> Monitors タブで確認 - 80k, 370k の画像をとりあえず 30k と 90k に -> 最初のこのベージすら表示できなかったものがまずは表示できるように。 全画面の画像も読み込んで最大 220m allocated. - ViewPager で表示する fragment の Layout XML の Image View の src に 700k の png を指定していた -> もちろん画像は動的に java 側で指定しているので外した。外すだけで allocated 最大 160m. - 80k, 370k の画像は表示し終わったら非表示にするので View に setImageResource(0) 指定 -> allocated 160m で変わらず。 - 80k, 370k の画像は表示し終わったら非表示にするので View に setVisibility(View.INVISIBLE) を指定していたので View.GONE に変更 -> allocated のサイズは変わらず 160m
Log
80k と 370 k の画像のページから既に表示できない
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example, PID: 22875 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.MainActivity}: android.view.InflateException: Binary XML file line #14: Binary XML file line #17: Error inflating class <unknown> at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3254) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7237) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by: android.view.InflateException: Binary XML file line #14: Binary XML file line #17: Error inflating class <unknown> at android.view.LayoutInflater.inflate(LayoutInflater.java:551) at android.view.LayoutInflater.inflate(LayoutInflater.java:429) at android.view.LayoutInflater.inflate(LayoutInflater.java:380) at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474) at android.app.Activity.setContentView(Activity.java:2387) at com.example.MainActivity.onCreate(MainActivity.java:45) at android.app.Activity.performCreate(Activity.java:6876) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7237) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by: android.view.InflateException: Binary XML file line #17: Error inflating class <unknown> at android.view.LayoutInflater.createView(LayoutInflater.java:657) at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) at android.view.LayoutInflater.onCreateView(LayoutInflater.java:706) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:774) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716) at android.view.LayoutInflater.rInflate(LayoutInflater.java:847) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1001) at android.view.LayoutInflater.rInflate(LayoutInflater.java:843) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) at android.view.LayoutInflater.inflate(LayoutInflater.java:527) at android.view.LayoutInflater.inflate(LayoutInflater.java:429) at android.view.LayoutInflater.inflate(LayoutInflater.java:380) at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474) at android.app.Activity.setContentView(Activity.java:2387) at com.example.MainActivity.onCreate(MainActivity.java:45) at android.app.Activity.performCreate(Activity.java:6876) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7237) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Constructor.newInstance(Native Method) at android.view.LayoutInflater.createView(LayoutInflater.java:631) at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) at android.view.LayoutInflater.onCreateView(LayoutInflater.java:706) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:774) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716) at android.view.LayoutInflater.rInflate(LayoutInflater.java:847) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1001) at android.view.LayoutInflater.rInflate(LayoutInflater.java:843) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) at android.view.LayoutInflater.inflate(LayoutInflater.java:527) at android.view.LayoutInflater.inflate(LayoutInflater.java:429) at android.view.LayoutInflater.inflate(LayoutInflater.java:380) at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474) at android.app.Activity.setContentView(Activity.java:2387) at com.example.MainActivity.onCreate(MainActivity.java:45) at android.app.Activity.performCreate(Activity.java:6876) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7237) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) Caused by: java.lang.OutOfMemoryError: Failed to allocate a 200450764 byte allocation with 16765264 free bytes and 140MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:856) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:675) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:2228) at android.content.res.Resources.loadDrawableForCookie(Resources.java:4215) at android.content.res.Resources.loadDrawable(Resources.java:4089) at android.content.res.Resources.loadDrawable(Resources.java:3939) at android.content.res.TypedArray.getDrawable(TypedArray.java:886) at android.widget.ImageView.<init>(ImageView.java:157) at android.widget.ImageView.<init>(ImageView.java:145) at android.widget.ImageView.<init>(ImageView.java:141) at java.lang.reflect.Constructor.newInstance(Native Method) at android.view.LayoutInflater.createView(LayoutInflater.java:631) at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) at android.view.LayoutInflater.onCreateView(LayoutInflater.java:706) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:774) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716) at android.view.LayoutInflater.rInflate(LayoutInflater.java:847) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1001) at android.view.LayoutInflater.rInflate(LayoutInflater.java:843) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) at android.view.LayoutInflater.inflate(LayoutInflater.java:527) at android.view.LayoutInflater.inflate(LayoutInflater.java:429) at android.view.LayoutInflater.inflate(LayoutInflater.java:380) at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474) at android.app.Activity.setContentView(Activity.java:2387) at com.example.MainActivity.onCreate(MainActivity.java:45) at android.app.Activity.performCreate(Activity.java:6876) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) at android.app.ActivityThread.access$1100(ActivityThread.java:222) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7237) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) I/System.out: (HTTPLog)-Static: isSBSettingEnabled false I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
USB メモリを Ubuntu 16 で exFAT にフォーマットする (フォーマット名は小文字でないとエラー)
確認した環境
Install utils
sudo apt-get install -y exfat-fuse
gnome-disks への設定
in terminal
gnome-disks
- Erase: Don’t overwrite existing data (Quick)
- Type: Custom (Enter filesystem type)
- Name: data (何でもいい)
- Filesystem: exfat
exFAT と書いてあるところが多いけど私の環境ではエラーになった
Error formatting volume Creation of file system type exFAT is not supported (udisks-error-quark, 11)
諦めた頃に GParted の View -> File System Support で使えるフォーマットのマトリクスを見つけて気づいた。
バージョンとかで違うんだろか . .
フィードがないサイトの RSS を自動で作ってくれる 「Happyou Final Scraper」の精度が良い
Feed43は辛かったからなぁ... ありがとうございます m( )m 「Happyou Final Scraper」
秋葉原で Uber EATS 頼めた
いつの間に .. . 千代田区はまだだったんだけど ok googke で遊んでたら出てきたのでつい頼んでしまった
Hungry? Get ¥2000 off your first order on #UberEATS with my code: eats-lgiaj. http://ubr.to/EatsGiveGet
クーポンが出てきたのでどうぞ
TypeScript のコードレビューサービスは CODEBEAT, Codacy 2つ (2017.04時点
当然 tslint, test, coverage は取った上でソースコードのレビューをしてほしい。
経緯
- TypeScript は書いたことないけど使ってみたい -> お作法とかベストな書き方とか多分できてない
- チームはたいてい1〜2人 -> 経験のみでのレビューだと指摘の内容が偏りがち。しかも今回はチーム1人
- Java だと無料で優秀なツールがそろっていたのでその時のような環境を作りたい
- lint が CheckStyle のイメージ。 FindBug とか PMD のような、もう一歩踏み込んだ指摘がほしい
環境
- API サーバー用
- TypeScript 2.0
候補のサービス
共通の特徴
- 両方共有料。それなりのお値段。 githubと同じかそれ以上くらい
- PMDとかFindBugとかのインストール型の解析サービスに比べて
- OAuth でポチポチやるだけなので設定は簡単
- default で Commit, Pull Request を hook して、結果を勝手にgithub上に押し込んでくれる(CIサービスがやってるような感じ)
- Badge 嬉しい
Codacy
- Scala でお世話になった。
- これも一人だったので助かった
- サイトがすごく重い .. analyze 済みのものも重いし画面に表示する内容のものがそんなになくても重い
- exclude の設定をサイト上でするのでリポジトリに固有のファイルをコミットしなくて良い
- グラフで issue が減っていくのを見ると小さい issue でも対応した時の満足感がちょっと増す
- Coverage も表示してくれるはずだけど Scala の時は使っていたバージョンが対応していなくて使えなかった
- TypeScriptに関しては、全然指摘してくれない。今 All A であまり面白くない
- しばらく使って様子見する予定
CODEBEAT
- swagger-ui のソースをたくさん指摘してくれる。(書いたところの指摘はあんまりまだ無いけど、codacy よりは多い。)
- exclude するファイルは gitignore 形式で、コミット必要
- 画面というか機能は Codacy より少ない印象。(まだ使いこなせてないだけかも)
- こちらも使いながら様子見
あと、 SideCI も tslint 対応しているみたい 今のところこんな感じだろうか。 他にあったら教えてください . . ..
nginx, ubuntu 16.04, Let's encrypt, webroot で SSL 導入したあと、http アクセスを https アクセスに転送する
やりたいこと
nginx, ubuntu 16.04, Let’s encrypt, webroot で SSL 導入したあと、http アクセスを https アクセスに転送する
LB 挟まず、1台に複数のアプリケーションをのせている開発用の小さい環境での設定です。
環境
- Ubuntu 16.04 LTS
- nginx 1.10.0
- letsencript ( webroot
- ドメイン、サブドメイン何個かのアクセスですべて別々のところに転送している
- let’s encrypt は導入済み
- let’s encrypt 自体の導入手順
- 簡単、このまま
- https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04
- もう小さい環境なのでここのとおり sites-available/default を直接いじってます。きちんとされてる方は読み替えてください。
- let’s encrypt 自体の導入手順
http から https への転送
1. 設定ファイルをエディタで開く
sudo vi /etc/nginx/sites-available/default
2. 80番を受け付けている server の server_name を消して location / ブロックに 301 で https アクセスし直すよう設定
下記で設定の場合です
- ドメイン yourdomain.example.com
- http アクセスは https に転送
- yourdomain.example.com に来たら 9000番に転送
- できればそのまま letsencrypt renew は動く状態にしたい # これは未確認。早めに確認しないと。。。
server { listen 80 default_server; root /var/www/html; location ~ /.well-known { allow all; } location { return 301 https://$server_name$request_uri; } } server { server_name yourdomain.example.com; listen 443 ssl; include snippets/ssl-yourdomain.example.com.conf; include snippets/ssl-params.conf; location / { proxy_pass http://localhost:9000; } }
3. reload
sudo nginx -t # テスト 心配なら sudo systemctl reload nginx
で大丈夫なはず . . 多分。
日本語が入力できない (Ubuntu 16.04 LTS, chrome, fcitx, mozc)
日本語入力ができない。今までいつもすんなりいかず、 ibus を使ったり何かの設定をいじってたらいつの間にか動いたりでよくわからない。
ibus がいよいよ動かなくなってきたので fcitx - mozc に変更、動いた方法のメモです。
環境
対応
GTK_IM_MODULE 等の設定で動いた。 ibusの時も似たようなのをやってやっと skype で日本語が入力できるようになった気がする。
.profile に下記設定
export GTK_IM_MODULE=fcitx export QT_IM_MODULE=fcitx export XMODIFIERS=@im=fcitx fcitx -d
ansibleにはこうしました
- lineinfile: dest=/home/{{ username }}/.profile regexp='GTK_IM_MODULE' line='export GTK_IM_MODULE=fcitx' - lineinfile: dest=/home/{{ username }}/.profile regexp='QT_IM_MODULE' line='export QT_IM_MODULE=fcitx' - lineinfile: dest=/home/{{ username }}/.profile regexp='XMODIFIERS' line='export XMODIFIERS=@im=fcitx' - lineinfile: dest=/home/{{ username }}/.profile regexp='fcitx' line='fcitx -d'
Chrome だけ動かない時
flash の設定云々の情報が多いので試したけど変わらず。 chrome を 一度プロセス全部 kill して起動し直すと大丈夫でした。 .profile でログイン時にブラウザを起動する設定を入れていたので、その時点で fcitx が起動しきれていなかったのではないかと思います。 sleep 入れて治りました。
Gemfile.lock もコミットしていいらしい
.lock はもうロックファイルではなかったんだ .. 知らなかった
yarn.lock はコミットしていいらしい
.lock だとロックファイルかと思ってしまうよ。。。
playbook の値にコロンを入れると「ERROR! Syntax Error while loading YAML.」「We could be wrong, but this one looks like it might be an issue with unbalanced quotes. If starting a value with a quote, make sure the line ends with the same set of quotes.」
問題
Ansible の playbook 内の lineinfile の値にコロンが入っていると Syntax error になる。
- playbook の該当箇所
- lineinfile: dest="/etc/elasticsearch/elasticsearch.yml" regexp="# network.ost" line='network.host: 0.0.0.0'
- エラーメッセージ
ERROR! Syntax Error while loading YAML. The error appears to have been in '/anywhere/tasks/main.yml': line 6, column 102, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: - apt: name=elasticsearch update_cache=yes - lineinfile: dest="/etc/elasticsearch/elasticsearch.yml" regexp="# network.host" line='network.host: 0.0.0.0' ^ here We could be wrong, but this one looks like it might be an issue with unbalanced quotes. If starting a value with a quote, make sure the line ends with the same set of quotes. For instance this arbitrary example: foo: "bad" "wolf" Could be written as: foo: '"bad" "wolf"' Ansible failed to complete successfully. Any error output should be visible above. Please fix these errors and try again.
対応
ダブルクオートで囲ってコロンだけ中括弧とクオートで囲むと動いた。
- lineinfile: dest="/etc/elasticsearch/elasticsearch.yml" regexp="# network.ost" line="network.host{{':'}} 0.0.0.0"
環境
user@somehost:~/somewhere$ uname -a Linux somehost 3.13.0-88-generic #135-Ubuntu SMP Wed Jun 8 21:10:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux user@somehost:~/somewhere$ ansible --version ansible 2.1.0.0 config file = /etc/ansible/ansible.cfg configured module search path = Default w/o overrides user@somehost:~/somewhere$ ansible-playbook --version ansible-playbook 2.1.0.0 config file = /etc/ansible/ansible.cfg configured module search path = Default w/o overrides user@somehost:~/somewhere$ vagrant --version Vagrant 1.4.3
作業ログ
vagrant の provisioning です
user@somehost:~/somewhere$ vagrant provision [default] Running provisioner: ansible... [DEPRECATION WARNING]: Instead of sudo/sudo_user, use become/become_user and make sure become_method is 'sudo' (default). This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg. ERROR! Syntax Error while loading YAML. The error appears to have been in '/anywhere/tasks/main.yml': line 6, column 102, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: - apt: name=elasticsearch update_cache=yes - lineinfile: dest="/etc/elasticsearch/elasticsearch.yml" regexp="# network.host" line='network.host: 0.0.0.0' ^ here We could be wrong, but this one looks like it might be an issue with unbalanced quotes. If starting a value with a quote, make sure the line ends with the same set of quotes. For instance this arbitrary example: foo: "bad" "wolf" Could be written as: foo: '"bad" "wolf"' Ansible failed to complete successfully. Any error output should be visible above. Please fix these errors and try again.
バックスラッシュ入れてもダメ
user@somehost:~/somewhere$ vagrant provision [default] Running provisioner: ansible... [DEPRECATION WARNING]: Instead of sudo/sudo_user, use become/become_user and make sure become_method is 'sudo' (default). This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg. ERROR! Syntax Error while loading YAML. The error appears to have been in '/anyware/tasks/main.yml': line 6, column 103, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: - apt: name=elasticsearch update_cache=yes - lineinfile: dest="/etc/elasticsearch/elasticsearch.yml" regexp="# network.host" line='network.host\: 0.0.0.0' ^ here We could be wrong, but this one looks like it might be an issue with unbalanced quotes. If starting a value with a quote, make sure the line ends with the same set of quotes. For instance this arbitrary example: foo: "bad" "wolf" Could be written as: foo: '"bad" "wolf"' Ansible failed to complete successfully. Any error output should be visible above. Please fix these errors and try again.
クオートで囲って解決
user@somehost:~/somewhere$ vagrant provision [default] Running provisioner: ansible... [DEPRECATION WARNING]: Instead of sudo/sudo_user, use become/become_user and make sure become_method is 'sudo' (default). This feature will be removed in a future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg. PLAY [all] ********************************************************************* TASK [setup] ******************************************************************* ok: [default]
コロンの後にスペースが入っているとエラーになるらしい