- 投稿日:2019-09-29T22:38:19+09:00
[Android]常にフルスクリーンにしておきたい時のTIPS
目的
- ナビゲーションバーが邪魔で基本常に非表示にしておきたい
方法
以下の処理を実装する。
MainActivity.ktoverride fun onStart() { super.onStart() hideSystemUI() } fun hideSystemUI() { window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) } override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) if (hasFocus) hideSystemUI() }View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
「外部からスワイプしないとナビゲーションバーが出てこない上に、出てきたナビゲーションは半透明になる」というモードを指す。
なお、ナビゲーションバーは普通がいいという場合はSYSTEM_UI_FLAG_IMMERSIVEを使う。View.SYSTEM_UI_FLAG_FULLSCREEN
ステータスバーを非表示にする。
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
ナビゲーションバーを非表示にする
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
ナビゲーションバーが非表示になった時にレイアウトが崩れないようにする。
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
ステータスバーが非表示になった時にレイアウトが崩れないようにする。
onWindowFocusChangedでhideSystemUIする理由
これがないとDialogを表示するタイミングで再度ナビゲーションバーが表示されてしまう。
それでもDialogFragment表示時にナビゲーションが表示されてしまう場合
私は表示されしまったので以下の実装を行い対処した。
このためにBaseDialogFragmentができてしまったのであまり良い方法ではないかも。BaseDialogFragment.ktoverride fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) hideSystemUI() } // ソフトウェアキーの非表示 private fun hideSystemUI() { dialog?.window?.setFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE ) activity?.window?.decorView?.systemUiVisibility?.let { dialog?.window?.decorView?.setSystemUiVisibility(it) } dialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) }参考
全画面モードを有効にする
https://developer.android.com/training/system-ui/immersive
- 投稿日:2019-09-29T17:49:26+09:00
/proc/meminfoのviewerをつくった
やりたいこと
/proc/meminfo
の内容を理解するために、色々実験しながら各要素の変遷が見たい。
ただ、メモリ使用状況を可視化するツールはたくさんあるがどれも抽象度が高く、
/proc/meminfoの粒度での変遷を表示するツールを見つけられなかった。やったこと
/proc/meminfo
をできるだけそのまま表示するmiviewerをつくった。
といっても/proc/meminfo
を取得して積み上げグラフにしただけ。miviewer
$ ./miviewer.py -h usage: miviewer.py [-h] [-a] [-i INTERVAL] [-c COUNT] [--check] [-w WINDOW] [-t {active,buff-cache,available,user-kernel}] optional arguments: -h, --help show this help message and exit -a, --adb Get meminfo via adb. -i INTERVAL, --interval INTERVAL The delay between updates in milli-seconds. Default is 200. -c COUNT, --count COUNT Number of updates. Default is infinite. --check Check some formulas. -w WINDOW, --window WINDOW Shown period time in seconds. Default is 60. -t {active,buff-cache,available,user-kernel}, --type {active,buff-cache,available,user-kernel} Graph type. Default is active.デフォルトでは、スクリプトを実行したPCの
/proc/meminfo
を、200ms間隔で取得し、グラフにプロットする。
--adb
オプションを指定することで、adb
経由でAndroid端末の/proc/meminfo
を取得することも可能。
また、/proc/meminfo
の要素はそれぞれ重なりがあり、一つの積み上げグラフですべての要素を表示することはできないので、
4つの選択肢からグラフタイプを選択できるようにしている。グラフタイプ
active
デフォルト。
Activeかどうか、つまり、LRUリストに乗ってるかどうかで分類された要素を積み上げている。
冒頭のグラフはこのタイプ。
なお、凡例の要素名が@で始まるものは、それそのものが/proc/meminfo
にあるわけではなく、何らかの方法で算出した値であることを示す。グラフタイプ
buff-cache
Buffers
とCached
、つまりバッファキャッシュ(メタデータやraw I/O用のキャッシュ)とページキャッシュ(ファイル自体のページのキャッシュ)の変遷を見るとき用。グラフタイプ
available
シンプルに
MemAvailable
とそれ以外を表示する。
Linux観点でSwappingが始まるまでの余力をザクッと見るとき用。グラフタイプ
user-kernel
ユーザ空間とカーネル空間のどちらで使っているかで分類してプロットする。
なんか使うことがあるかなとおもって用意したものの、デフォルトのactive
があれば必要ない気がしないでもない。環境
動作確認環境は、以下のとおり。
- Ubuntu 18.04
- Linux 5.0.0-29-generic
- Python 3.6.8
- matplotlib 2.1.1
とはいえあまり環境に依存する実装ではないので、
MemAvailable
がある(3.14以降)Linux環境なら動くんじゃないかと。
もしかしたらadb
モードならMac/Windowsでも動くかもしれない(未確認)。おわりに
なにかお気づきの点やご要望などありましたらぜひご指摘ください。
参考
/proc/meminfo
matplotlib.animation
matplotlib.stackplot
- 投稿日:2019-09-29T16:30:21+09:00
【Android】ダークテーマの対応方法
はじめに
Android 10から本格サポートされたダークテーマ(ダークモード)のアプリ側の対応方法について説明します。
res/values/styles.xml
まず初めに、通常のテーマカスタマイズでも利用するstyles.xmlを更新し、ダークモードON/OFF時に切り替えたいカラーを定義しておきます。
<resources> <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:colorBackground">@color/colorBackground</item> <item name="android:textColor">@color/textColor</item> <item name="android:textColorPrimary">@color/textColorPrimary</item> <item name="android:textColorSecondary">@color/textColorSecondary</item> </style> </resources>colors.xmlの作成
システム設定でダークモード有効時に参照されるカラー定義をres/values-night/colors.xmlに、通常時のカラーをres/values/colors.xmlにそれぞれ記載しておきます。
例) res/values-night/colors.xml
<resources> <color name="colorPrimary">#212121</color> <color name="colorPrimaryDark">#212121</color> <color name="colorAccent">#80cbc4</color> <color name="colorTransparent">#00000000</color> <color name="textColor">#FFFFFF</color> <color name="textColorPrimary">#FFFFFF</color> <color name="textColorSecondary">#808080</color> <color name="colorBackground">#313131</color> <color name="colorCardBackground">@color/colorPrimary</color> <color name="colorBackgroundBottomAppBar">#353535</color> </resources>ここまで対応すれば、システム設定に連動して、コードは一切書かなくても表示が切り替わります。
アプリ内の設定で動的に切り替えたい場合
AppCompatDelegate.setDefaultNightModeを利用します。
常にダークテーマで表示
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES);常にダークテーマOFF(通常表示)
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO);システム設定に連動する(特に指定しない場合はこちらがデフォルトです)
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM);
- 投稿日:2019-09-29T01:16:18+09:00
Class.getSimpleName()の罠
学び
Android開発において、SimpleNameは使うべきではなさそう。
背景
SimpleNameを使った実装で予期せぬ動作を経験しました。
全く違うクラス名にも関わらず、同一のSimpleNameになっていたのです。
例えば、下記のコードがtrue
になるのです。if (MainFragment.simpleName == SubFragment.simpleName) { // "MainFragment" と "SubFragment" の比較になることを期待したので、 // falseを期待しているのに、trueになる場合がある }ちなみに、私の環境ではdebugビルドでは
false
になるのに、
releaseビルドではtrue
になりました。勘のいい人はわかったかもしれませんね。
何が起きたのか
難読化。ProGuardの仕業。
上記の例では、MainFragment
とSubFragment
が別のパッケージだった場合に、
難読化されて同一のクラス名に置き換わる可能性があります。初期設定のProGuardの設定では、
パッケージ内のクラス名はアルファベット順に置き換わります。例えば、下記の二つのクラスは、このように変換されます。
com.yoshinori.sandbox.main.MainFragment
→b.b.a.a.a
com.yoshinori.sandbox.sub.SubFragment
→b.b.a.b.a
このように変換された時の
SimpleName
は、両方ともa
です。
元々のクラス名は全然違うのに、難読化後は同一のクラス名として処理されてしまうのです。
当たり前のようで、気付きにくいミスです。どうやって対応すれば良いのか
SimpleName
ではなくてName
を使用する。
name
は、パッケージ名 + クラス名です。
難読化前ならcom.yoshinori.sandbox.main.MainFragment
となります。
これであれば、難読化後であっても、同一になることはありません。if (MainFragment.name == SubFragment.name) { // 常にfalseになる }終わりに
もし
SimpleName
を使用している場合、本当に問題ないか確認してみてください。
基本的に普段の実装時にはProGuardは無効にしていると思います。ですので、リリース直前で気づくことになったり、
最悪の場合は不具合に気付かずストアリリースされちゃいます。
怖いですね。
- 投稿日:2019-09-29T01:02:36+09:00
Windows/Macでapkを動かす
Androidのアプリの画面をWindowsやMacで見たいという場合、apk自体をエミュレーターで動かしてしまう方法と、apkが動いているAndroidの画面をミラーリングする方法があります。
apk自体をエミュレーターで動かす方法
BlueStacksのインストール
BlueStacksをインストールします。Windows/iOS両方対応しています。
https://www.bluestacks.com/ja/index.html起動すると、こうなります。
縦画面にしたい場合は、右上のボタンでサイドバーを開き、一番下の切り替えボタンを押します。
apkのインストール
分かりにくいですが、インストールアプリメニューからインストールします。
apkが動いているAndroidの画面をミラーリングする方法
ミラーリングする方法はいろいろありますが、USB接続するだけでお手軽にミラーリングする方法です。
VysorというChrome拡張を入れます。
https://chrome.google.com/webstore/detail/vysor/gidgenkbbabolejbgbpnhbimgjbffefm?hl=jaAndroid側は、USBデバッグを有効にする必要があります。
その状態でVysorを起動し、USBでつなぐと、Vysorの画面にAndroid側の画面が表示されます。
Android側にはVysorアプリがインストールされます。
Windows側の画面からAndroidの画面をマウスで操作することもできます。一定時間操作がないと広告が表示されます。戻るボタンで消せます。
おしまい。