投稿

Handler(mainLooper).post() を使うやり方と、runOnUithread() を使うやり方の違い

基本的に runOnUiThread() は Handler(mainLooper).post() へのラッパーとして用意されているが、 メイン UI スレッドから実行する場合は挙動が異なる 。 メイン UI スレッドから実行した場合は、Handler(mainLooper).post() されずにスルーされて、そのまま Runnable の内容を実行する扱いとなる。なので、View の再描画など、強制的にタスクを発生させたいがために Handler(mainLooper).post() したい場合に、メイン UI から runOnUiThread() を使っても無意味なので、この場合は明示的に Handler(mainLooper).post() を記述して実行する必要がある。 cf. runOnUiThread vs Looper.getMainLooper().post in Android

PreferenceFragment

1 年以上ぶりくらいに本格的な Android プログラミングに回帰。そのせいか、固定観念から多少自由になったかもしれない。 例えば、PreferenceFragment。古い PreferenceActivity が obsolete になって、代わりに PreferenceFragment を使うように 公式リファレンス に書かれている。それで、ネット上の情報をいくつか見ても、受け売りの解説ばかりなものだから、皆が自前の MyPreferenceActivity 的なるものを用意して、その中で PreferenceFragment を実装するような感じにしてる。 そこで今回、「そもそも、MainActivity で直接 PreferenceFragment を使っちゃいけない理由なんてあるのかい」と思って、やってみたら──できた! 今までの MyPreferenceActivity をわざわざ専用に用意して PreferenceFragment を使うやり方って、何だったのだろうか……。 受け売り情報撒き散らすのやめて欲しい。 いや、まあ、ブログなんだから、本来は各人の私的なメモという性格のものではあるんだろうけど。

OOP なるプログラミング・パラダイム

イメージ
結局、「オブジェクト指向プログラミング(OOP)」というのは、1) 手続指向は構造化で、2) データは構造体で、ということであり、この両者を、3) 構造化された手続(メソッド)を、構造体(オブジェクト)単位で整理することでまとめた、というだけの話であり、これ以上でもないし、これ以下でもないのではないかと思う。 手続自体は、あくまでも構造化プログラミング的な観点で整理を行なうべきで、これを生半可なオブジェクト指向的観点で整理すると、コードが無茶苦茶になって却って“百害あって一利なし”といっても言い過ぎにはならない気がする。少なくとも、自分の場合はそうである。 そうやって、構造化プログラミング的にすっきりと整えられた個々のコードが、集合して複数のコード群としてそのままそこいらにぶちまけられている時に、手続指向の限界が急にクローズアップされてくる。 この時に整理整頓の〝容れ物〟として俄かに脚光を浴びることになるのが、構造体(オブジェクト)である。手続のためのコードをそのまま〝裸〟でそこいらにぶちまけては置かないようにしよう、必ず、構造体に入れられた(カプセル化)状態で置いておくことにしようね、というのが僕流のオブジェクト指向像である。 上のことをちゃんと自覚していないで、「オブジェクト指向スゲー」で何でもかんでもオブジェクト指向のノリを持ち込もうとすると、むしろコードの見通しが悪くなって、あっちへ飛んだり、こっちへ飛んだりと、ダイクストラ先生が「goto は使わないようにしよう」といった時代の事情に逆戻りして、あっちのメソッドこっちのメソッドを飛び回るような、いわば「goto なきスパゲッティ化プログラミング」に陥ってしまう。 新しいコードをスクラッチで組んでいく時、ここは手続指向で素直に、一つ一つの処理を継ぎ足して行ってプログラミングするのが、やはり王道なのではないかと思う。そしてそのコードが伸びるにつれ、(2回以上)多用される同様の処理は、サブルーチンとして分離する。そのことで、「コードをコピー&ペーストして使い回すことを避ける」というのが、構造化プログラミングの単純かつ肝となる原点だと思う。ある処理に関するコードが記述される場所を一元化することで、後に変更の必要が生じた時に、あちこちを修正して回るというようなことは避けないと、例えば、一部を修正し...

オブジェクト指向プログラミングと構造化プログラミング

イメージ
オブジェクト指向プログラミング(OOP)と構造化プログラミング(手続指向)を対立する概念だと思っていたが、どうやら間違っていたようだ。 詳細は別の機会でもあれば書くかもしれないが、両者は共存可能、というか共存させるのが適切だと思った。 この結論に達することで、メソッド定義の private と public、static と dynamic の使い分けもはっきり線引きできるようになったと思う。 構造化プログラミングは static で、そのうちのサブルーチン部分は private、メインルーチンは public。 オブジェクト指向プログラミングは dynamic で、オブジェクトの操作に関するインターフェイスとしてのメソッドは public。 大ざっぱな分け方としてはそんな感じ。

Amateras Modeler

Eclipse (neon) に Amateras Modeler(プラグイン)を追加した。 GEF SDK のインストール(http://download.eclipse.org/releases/neon から GEF をフィルタリングして見つければよい) Amateras Modeler のインストール(http://takezoe.github.io/amateras-update-site/ からインストールすればよい) 使い方は、File > New > other > AmaterasUML > クラス図 で新規作成し、クラスファイルをドロップすれば自動的にクラス図が表示される。

旧 Ubuntu 機のデータを完全消去

Core 2 Duo のデスクトップ PC から、HP の Core i7 のノート PC に移行して 1 ヶ月以上が経過した。当初は、様子を見て、旧環境をそのまま放置しておいたのだが、どうやら新環境で問題はなさそうなので、旧マシンは処分することにする。 差し当たって、HDD のデータを完全消去しておく。「 Linuxを利用したHDDの完全消去 」を参考にした。よくまとまっていて、むしろ Live 環境の作成について字数が多くなり過ぎというくらいで、特に他に情報を参照する必要はなかった。 簡単にポイントをまとめておくと: Live 環境 スーパーユーザー化 デバイスファイル名の調査 shred コマンド で、デバイスファイル名自体は除くとして、su や shred の各コマンドのオプションもそのまま使えるものだった。 Live 環境は、色々なやり方があり、僕の場合、UNetbootin を使った Live USB を作成した(ISO イメージは Ubuntu GNOME のものを使った)。

正規購入の iPhone が偽物という事件

イメージ
「 ソフトバンクがiPhoneの修理を拒否?Twitterユーザーの報告が話題 」というニュースを目にした。 このニュースは、そもそものソースのユーザーの印象をそのまま受けたニュースとして拡散しているので、基本的には「ソフトバンクの対応が酷い」という主旨の話題として取り上げられている。 しかし、僕が個人的に、このニュースにひっかかるものを感じて、ピンときたものがあったのは、昨年 2015 年の 5 月頃の出来事のことである。 当時、知人(女性)が古くなって使い勝手の悪くなった Windows ノート PC をどうにかしたいと相談してきたので、たまたま、新しい 12 インチの MacBook が登場したばかりのタイミングだったので、「渡りに船」とばかり、勧めて、彼女は MacBook を購入したのだった。アップル・オンラインからの直接購入である。 そしてその際、一つだけ、僕の趣味を反映してもらって、US キーボード版にしてもらった。そのためか、日本国内からではなく、香港からの発送となった。 従来の MacBook Pro や MacBook Air のユーザーが様子見で、まだ世間では MacBook の評価が定まっていない時期、彼女は届いた MacBook に大喜びだった。しかし── その MacBook が、約 1 ヶ月で故障し、立ち上がらなくなったのである。 彼女は、アップル製品の正規サービスプロバイダである クイックガレージ に持ち込むなどして、数日の紆余曲折を経た結果、最終的に「初期不良」との診断となり、交換となった。 次に送られてきた新品は、見違えるように、快調なものだった。 事態が落ち着いてから、彼女が漏らした感想は、「最初の機体はりんごのマークのロゴが腐食してくすんでいた。新しい機体はピカピカだ」というものだった。 僕は、「もしかして、香港から送られてくる、その過程で、内部の人間が偽物(または廃棄されるべき不良品)とすりかえた可能性があるかもしれない」と思った。アップルという会社自体に対する信頼が揺らぐものでもないが、あれだけ大きなグローバル企業だから、内部に不貞の輩が入り込んでくることは、どうやっても避けられないだろう。 MacBook も 2016 年版くらいになると、そろそろ従来のアップル信者も使い出してきているようだが、当...

QNAP の Web UI にログイン不可能になった場合の対処法

仮想ホストの HTTPS や証明書の設定をしていた時、何かの拍子、というか XXX.myqnapcloud.com の証明書の設定をリセットした拍子に、Web UI にログインできなくなり、困った状態になった。延々と Web 画面がリダイレクトされるループ状態になってしまう。 原因は、デフォルトでは、Web UI の HTTP ポートが 80、HTTPS ポートが 443 で、仮想ホストの Web サーバーの HTTP ポートが 8080、HTTPS ポートが 8081 のところを、Web UI と仮想ホストで入れ替えて、Web UI が HTTP(8080)と HTTPS(8081)、仮想ホストが HTTP(80)と HTTPS(443)にしていた。さらに、Web UI を HTTPS のみでログインできるようにして、HTTP ではログインできないようにしていた。ポート設定が、証明書のリセットのタイミングで Web UI のポート設定がデフォルトに戻り、HTTP はログインを拒絶して HTTPS にリダイレクトするのだが、リダイレクト先が間違っており、仮想ホストの無効なポートへのアクセスとして処理されて Web UI の HTTP へとリダイレクトを戻す、というループに陥ってしまったようだ。 最悪、NAS の設定をリセットして再起動すればいいわけだが、SSH によるログインはまだできる状態だったので、リセットが避けられればそれに越したことはない。情報を検索すると、 QNAP のフォーラム にまさしく同じ状況に陥っている人がいて、達人の pwilson さんが対処法を回答していた。お蔭様で、設定リセットすることなく、復帰することができた。 pwilson さんは一連のコマンドをアドバイスしてくれているが、僕のケースでは、HTTP でのログインさえ再び有効化すればよかったので、SSH で、 setcfg System 'Force SSL' '0' /etc/init.d/Qthttpd.sh restart /etc/init.d/stunnel.sh restart だけ実行して、HTTP でのログインを有効にして、あとは、HTTPd と stunnel を再起動するだけで十分だった。 それで Web UI にログイン...

SSLLabs のテストで A 評価を得る

イメージ
中間証明書の問題はクリアしても、 SSLLabs のテスト は、RC4 を使っているせいで B 評価となる。ところが、myqnapcloud の方は A 評価なのに気付いた。 これもおそらく、QNAP の中の人が、仮想ホストでの使い勝手を考慮していないためだろう。 myqnapcloud の設定は、/etc/config/apache/extra/apache-ssl.conf ではないかと推測し、その SSLCipherSuite の設定を /etc/config/apache/extra/httpd-ssl-vhosts-user.conf に移植してみた: - SSLCipherSuite ALL:!aNULL:!ADH:!eNULL:!SSLv2:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM + SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL...

QNAP の仮想ホストで SNI

昨日はどうにか仮想ホストでちゃんと中間証明書を有効にする方法を確立した。さらに一日経って、頭が整理できて、全体的により洗練されたやり方に行き着くことができた。昨日の成功をベースにして SNI(仮想ホストのそれぞれで別々の証明書を使い分けること)も余裕でできることがわかったので、それも含めて、全体を整理し、洗練したやり方になったので、それをまとめておこうと思う。 Web サーバーのポートの設定 Web UI 用のポートは「システム設定 > 一般設定 > システム管理」で 8080(HTTP)と 8081(HTTPS)に設定した。さらに、「HTTPS のみを使用する」設定にした。 Web サーバーのポートは「Webサーバ > Webサーバ」で 80(HTTP)と 443(HTTPS)に設定した。さらに仮想ホストの設定で、 443(HTTPS)の設定の仮想ホストだけをエントリーした。 StartSSL での証明書の取得 StartSSL で、仮想ホストそれぞれの証明書と、XXX.myqnapcloud.com 用の証明書もついでに取得する。これらの中間証明書はすべて共通(StartSSL)の中間サーバーのものとなるので、中間証明書は別々に用意しなくてもいいのが洗練されたやり方となるポイント。 それぞれの Web サイト認証は、「Website Control Validation」のリンクをクリックして、認証用の HTML をダウンロードし、ウェブサイトのルートに設置してから、認証ボタンを押して、認証を成功させることができる(認証後は、認証用 HTML を削除して構わない)。ちなみに、XXX.myqnapcloud.com のルートは、/share/Web そのものである。 XXX.myqnapcloud.com 用の証明書の設定 XXX.myqnapcloud.com(Web UI)用の証明書は、Web UI から「システム設定 > セキュリティ > 証明書とプライベートキー」で行える。StartSSL からダウンロードした zip の中の さらに ApacheSever.zip の中の 2_XXX.crt を証明書としてアップロード、秘密キーには、StartSSL のツールボックスの「Decrypt Private ...