LinearLayoutやRecyclerViewの、もともと用意されている区切り線について
LinearLayout
android:divider="?android:dividerHorizontal" android:showDividers="beginning|middle|end"
RecyclerView
final DividerItemDecoration decoration = new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL); recyclerView.addItemDecoration(decoration);
もともと用意されているDrawable
android:background="?android:attr/listDivider"
Androidで、v7.Toolbarに高さ指定するときについて
ActionBarをMaterial対応させると、Heightは
56dp (デフォルト)
48dp (横向き)
64dp (タブレット、sw600dp)
になると思うが、実際に直指定するのはださい。
ICSからNougatまでに対応し、なおかつ直指定しない方法として、
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/original" />
とすれば良さそう。
?android:attr/actionBarSize
ではなく
?attr/actionBarSize
と指定する。つまり、Compatの値を呼ぶようにする。
コードによる、actionBarSize の確認方法
// これは56dp final TypedArray styledAttributes = getContext().getTheme().obtainStyledAttributes( new int[]{R.attr.actionBarSize}); final int px = (int) styledAttributes.getDimension(0, 0); styledAttributes.recycle(); final int dp = px / (int) getResources().getDisplayMetrics().density; Log.d("size", String.valueOf(dp));
// これだと48dpになる final TypedArray styledAttributes = getContext().getTheme().obtainStyledAttributes( new int[]{android.R.attr.actionBarSize}); final int px = (int) styledAttributes.getDimension(0, 0); styledAttributes.recycle(); final int dp = px / (int) getResources().getDisplayMetrics().density; Log.d("size", String.valueOf(dp));
appcompat-v7 を使って、カスタマイズ可能な、 Dialog のような画面を超楽にめちゃ綺麗につくる
Androidで、カスタマイズ可能なDialogのような画面を楽につくる方法について考える。
Android でカスタマイズダイアログをつくるのは、AlertDialogよりはDialogFragmentのほうが楽にはなっているが、相変わらず骨が折れる。
今回は、DialogはAlertDialogやDialogFragmentで作るもの、という発想は捨てて、ActivityにMaterial Themeに用意されているDialogのStyleを適応することで、簡単に綺麗に実装していく方法で進めるというアプローチを取る。
ライブラリ的に用意するものは、Googleから提供されている、Support Libraryのうちの一つ、 appcompat-v7のみ。今Android Studioで新規プロジェクトを作ると、予めappのbuild.gradleに記載されているので、導入に特別な手順も必要ない。
後は、AppCompatActivityを用意し、Manifest側でDialogのThemeを適応するだけ。
Dialogの起動も、Activityと同じくstartActivityを呼び出すだけですし、回転やタスク切り替えの特別な配慮も必要なくなる。なんと素晴らしい!
GitHubにサンプルを置く。局所的にコードを書き記すよりも全体を見たほうが状況を把握しやすいはずである。このサンプルは、Dialogの中身がWebViewとなっていて、画面を立ち上げるとGoogleのトップページが開く。Activityをベースにつくると、こういった奇抜な画面も作成可能(笑)。
https://github.com/tatuas/AndroidWebViewDialogSample
Deploygateから、サンプルコードをビルドしたAPKを配布する。
上記サンプルで使用している Theme は、中身の大きさが Style 側で dp 指定されている、 Theme.Base.AppCompat.Dialog.FixedSize という Theme だが、要件によっては、そのサイズをカスタマイズしたい需要もあるかもしれない。ただ、ちょっと Style の命名が直感的でないので、以下の Stackoverflow を参考にされると良い。
http://stackoverflow.com/questions/29003591/android-fixed-size-dialog-dimension-what-is-major-minor
上記を参考に、
values
values-large
values-xlarge
にそれぞれdimens.xmlでサイズを定義して、style.xmlでその値に Override すればよい。サンプルコードには、サイズを変更する実装も含む。
Androidで今開いているアクティブなActivityを調べるコマンド
adb shell dumpsys activity activities | grep mResumed
FragmentLifecycleCallbacksってのがあるらしいが…
使えそうだなーと思い。
が、ドキュメントではstaticでメンバークラスぽいけど、実際のコードではインナークラスだった…
なのでこんな感じで書けばいけました。
final FragmentManager.FragmentLifecycleCallbacks cb = getSupportFragmentManager().new FragmentLifecycleCallbacks() { @Override public void onFragmentStarted(FragmentManager fm, Fragment f) { super.onFragmentStarted(fm, f); Log.d("log", "onFragmentStarted"); } }; getSupportFragmentManager().registerFragmentLifecycleCallbacks(cb, true);
FirebaseCrashクラスにあるlogとlogcatメソッドの違い
# 致命的クラッシュや、FirebaseCrash.report()した場合に送られる際に、直近のログを同時に送信するため保存しておく。保存する内容はlogcatには出力しない。 FirebaseCrash.log(message); # 致命的クラッシュや、FirebaseCrash.report()した場合に送られる際に、直近のログを同時に送信するため保存しておく。保存する内容はlogcatにも出力する。 FirebaseCrash.logcat(Log.ERROR, tag, message);
メッセージ自体は、レポートの直近に出力されたログとしてFirebase Consoleで見られるだけで、BigQueryには自動的にエクスポートはされない模様。
macOS Sierraで、Homebrew経由でMySQLをインストール&使用開始できる状態にする
Macにインストール
$ brew install mysql
MySQLの初期設定
$ mysqld --initialize --explicit_defaults_for_timestamp
で初期設定。
--initialize specified but the data directory has files in it. Aborting
というエラーメッセージが出た場合は、${Homebrewのインストールディレクトリ}/var/mysql
ディレクトリが存在しているから。存在していれば削除して初期設定をやり直す。
成功したら
A temporary password is generated for root@localhost: XXXXXXXX
などと仮のrootパスワードが出てくるので忘れずにメモ。
my.cnf
でsockファイルの場所を指定
$ mysql --help | grep my.cnf
でmy.cnfの場所を検索。
order of preference, my.cnf, $MYSQL_TCP_PORT, /etc/my.cnf /etc/mysql/my.cnf ${Homebrewのインストールディレクトリ}/etc/my.cnf ~/.my.cnf
などと出てくるはず。好みの場所にmy.cnfファイルを作成。 中身は
[client] socket=/tmp/mysql/mysql.sock [mysqld] socket=/tmp/mysql/mysql.sock
とする。
Sockファイル作成
$ cd /tmp $ sudo mkdir mysql $ cd mysql $ sudo touch mysql.sock
権限設定
${Homebrewのインストールディレクトリ}/var/mysql
/tmp/mysql
${好みの場所に書いたmy.cnfのディレクトリ}/my.cnf
/tmp/mysql/mysql.sock
4つのディレクトリ・ファイルの権限を整える。
$ cd /tmp/mysql $ sudo chown -R ${Macのユーザ名。whoamiで出るもの。}:wheel mysql/ $ cd ${Homebrewのインストールディレクトリ}/var $ sudo chown -R ${Macのユーザ名。whoamiで出るもの。}:wheel mysql/ $ cd ${好みの場所に書いたmy.cnfのディレクトリ} $ sudo chown ${Macのユーザ名。whoamiで出るもの。}:wheel my.cnf $ cd /tmp/mysql $ sudo chown ${Macのユーザ名。whoamiで出るもの。}:wheel mysql.sock
MySQLのサーバを起動
$ mysql.server start
とやって、
Sucess!
と出れば成功。
MySQLのクライアントを起動
$ mysql -u root -p
で上記でメモした仮パスワードを入れてログイン。 ログインできたら成功。 ログイン後は、仮パスワードを変更しないと何も操作できないので、
mysql> set password for root@localhost=password('パスワード');
で、rootのパスワードを更新する。
セキュア設定
$ mysql_secure_installation
を実行するだけ。
Androidで表示されているViewをファイル保存する
View view = findViewById(R.id.preview); Bitmap bitmap = null; OutputStream stream = null; boolean result = false; try { final String filename = "saved.jpg"; final File saved = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), filename); final int quality = 100; stream = new FileOutputStream(saved); // 通常はCacheを使用したほうが処理は早い。 final boolean isAutoScale = false; view.buildDrawingCache(isAutoScale); bitmap = view.getDrawingCache(isAutoScale); result = bitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream); view.destroyDrawingCache(); // 上のキャッシュを利用するやり方だと // ”View too large to fit into drawing cache, needs ~ bytes, only ~ available” // と出ることがある。其の場合は下記のやり方で。 // ただし端末によっては処理が遅い。 bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(bitmap); view.draw(canvas); Toast.makeText(getContext(), (result && saved.exists()) ? "Succeed." : "Failure.", Toast.LENGTH_SHORT).show(); } catch (Throwable throwable) { throwable.printStackTrace(); } finally { try { if (bitmap != null) { bitmap.recycle(); } if (stream != null) { stream.close(); } } catch (Throwable throwable) { throwable.printStackTrace(); } }
Ubuntu の Unity ランチャーに任意のアプリケーションを登録する
$ cd /usr/local/applications $ vim 任意.desktop
以下は内容
Desktop Entry] Version=1.0 Type=Application Name=任意 Exec="コマンドの場所" %f Icon=アイコン画像の場所 Categories=Development;IDE; Terminal=false StartupNotify=true StartupWMClass=任意 Name[en_GB]=任意.desktop
再ログイン後反映されているはず。
Robolectric 3.0でApplicationクラスやConstantsクラスをrobolectric.propertiesに書き出す時の注意点
src/test/resources/robolectric.properties(正しい例)
application=com.sample.MyApplication constants=com.sample.BuildConfig sdk=21 packageName=com.sample
src/test/java/com/sample/test/MyTest.java(端折っています)
import com.sample.MyApplication; @Config(application = MyApplication.class)
流れ的に@Config(application = MyApplication.class)
の要領でapplication=com.sample.MyApplication.class
と書くと
java.lang.RuntimeException: Could not load class: com.sample.MyApplication.class
となると思う。
が、.class
はpropertiesに書く際は必要ない。
クラスパスはフルパスで記載するので注意。
Android Studio, IntelliJ, Pycharmなどでプロジェクト全体から検索
Search EveryWhere。 IntelliJ系共通。 Shift2回。
Google App Engine for Pythonでdev_appserver.pyした際エラーが出たら
ImportError: cannot import name docker
などと出るだろう。 以下の方法で対処可能。
$ pip install docker-py $ vim ~/google-cloud-sdk/platform/google_appengine/google/appengine/tools/docker/containers.py - from docker import docker + import docker :wq