<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-28877138</id><updated>2024-09-20T23:36:17.537+09:00</updated><category term="NetBSD"/><category term="Android"/><category term="python"/><category term="C"/><category term="subversion"/><category term="Linux"/><category term="pkgsrc"/><category term="firefox"/><category term="pthreads"/><category term="mercurial"/><category term="w3m"/><category term="english"/><category term="thunderbird"/><category term="Fragment"/><category term="codereview"/><category term="google"/><category term="googlenotewiki"/><category term="unix"/><category term="windows"/><category term="CPU"/><category term="GTD"/><category term="MacOSX"/><category term="OpenSSL"/><category term="agile"/><category term="book"/><category term="golang"/><category term="greasemonkey"/><category term="itron"/><category term="kernel"/><category term="programming"/><category term="sakura"/><category term="test"/><category term="xen"/><category term="Adapter"/><category term="Bluetooth"/><category term="DMA"/><category term="Enigmail"/><category term="PGP"/><category term="SSL"/><category term="amazon"/><category term="arm"/><category term="bash"/><category term="cache"/><category term="debian"/><category term="debug"/><category term="disklabel"/><category term="distcc"/><category term="embedded"/><category term="gcc"/><category term="gmail"/><category term="gradle"/><category term="hardware"/><category term="patch"/><category term="trac"/><category term="vim"/><category term="web.py"/><category term="wiki"/><category term="702NK"/><category term="705NK"/><category term="AES"/><category term="Activity"/><category term="Android Studio"/><category term="Dropbox"/><category term="IE"/><category term="IntelliJ"/><category term="LaTeX"/><category term="ListView"/><category term="Loader"/><category term="MBR"/><category term="MD5"/><category term="N73"/><category term="OpenOffice"/><category term="OpenSolaris"/><category term="Qt"/><category term="SEO"/><category term="SHA1"/><category term="SSH"/><category term="Spinner"/><category term="TortoiseHG"/><category term="Ubuntu"/><category term="WPA"/><category term="add-on"/><category term="assembler"/><category term="bridge"/><category term="canna"/><category term="catch.com"/><category term="cruisecontrol"/><category term="current"/><category term="cygwin"/><category term="dictionary"/><category term="encfs"/><category term="etch"/><category term="evernote"/><category term="fastdx.jar"/><category term="filesystem"/><category term="fuse"/><category term="gdb"/><category term="git"/><category term="global"/><category term="llvm"/><category term="make"/><category term="markdown"/><category term="math"/><category term="multiprocessor"/><category term="palm"/><category term="pdf"/><category term="postscript"/><category term="print"/><category term="puffs"/><category term="quiz"/><category term="ruby"/><category term="samba"/><category term="scm"/><category term="security"/><category term="superh"/><category term="svs"/><category term="t-code"/><category term="thread"/><category term="tiddlywiki"/><category term="todo"/><category term="web2.0"/><category term="webdav"/><category term="wget"/><category term="wif"/><category term="wifi"/><category term="x86"/><category term="xzgv"/><category term="ネタ"/><title type='text'>夜でもアッサム</title><subtitle type='html'>AndroidとかGo言語とか、そのあたりの技術メモ。</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default?start-index=26&amp;max-results=25'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>268</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-28877138.post-5404775028543933105</id><published>2015-06-23T10:55:00.001+09:00</published><updated>2015-06-23T10:55:58.885+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>Android4.0以前と4.1以降では、親のViewをクリックした時に子のViewがどう見えるのかが異なる</title><content type='html'>Android4.0以前と4.1以降では、親のViewをクリックした時に子のViewがどう見えるのかが異なるので注意が必要。&lt;br /&gt;
&lt;br /&gt;
以下のようなViewがあったとする。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRSh0otltktaIZqVMMIBbdz_TpA2KHrKCpJV5MujSsENRq4SfOAUmzUmVsi2nfRqKzIL2REvYHKClrZAQPMHrtSxcsx02GyjXsvVva1sHpX8DyPZWGKj3TPzkctD2-hvqMjitoZQ/s1600/android40_normal.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRSh0otltktaIZqVMMIBbdz_TpA2KHrKCpJV5MujSsENRq4SfOAUmzUmVsi2nfRqKzIL2REvYHKClrZAQPMHrtSxcsx02GyjXsvVva1sHpX8DyPZWGKj3TPzkctD2-hvqMjitoZQ/s320/android40_normal.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Clickできる箇所は、外側の白い部分(下図のA)と、上の水色の部分(下図のB)。残りはnon clickable。すべてのViewのbackgroundDrawableは、stateful（pressedステートだと色が暗くなる)とする。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsaQck7hrhZg0EWAhkwGPTuuJ883xyvXk8KLGj188754d_YIp6NiqKUWcJq3McsIHB0ecYNQJ_S5d33c06s-YFmMXFv7FoPYgtHelby0vx_ljXXYc4hqvE_0Rr0QGXTbdMcVzY3g/s1600/AB.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsaQck7hrhZg0EWAhkwGPTuuJ883xyvXk8KLGj188754d_YIp6NiqKUWcJq3McsIHB0ecYNQJ_S5d33c06s-YFmMXFv7FoPYgtHelby0vx_ljXXYc4hqvE_0Rr0QGXTbdMcVzY3g/s320/AB.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Android 4.1以降では、子にもpressedステートが伝わる&lt;/h2&gt;&lt;br /&gt;
Android4.1以降でAをクリックした場合は、Aの領域すべてが暗くなる(子にもpressedステートが伝わる)。ただしclickableなBには伝わらない。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN3_DhlOFku1PImoezaoacRvznxJtqNN2WmtSQ3k3dF_qgjgfF9XrWXPHzS-vBVOBFI9xH3ynTFMYGbqenCKXT9Q-9EeIbmzERG8ViGCa_lvagNQi8ycX-YuPoOx9qevdlYWo6_A/s1600/android43_A.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN3_DhlOFku1PImoezaoacRvznxJtqNN2WmtSQ3k3dF_qgjgfF9XrWXPHzS-vBVOBFI9xH3ynTFMYGbqenCKXT9Q-9EeIbmzERG8ViGCa_lvagNQi8ycX-YuPoOx9qevdlYWo6_A/s320/android43_A.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Android4.1以降でBをクリックした場合は、Bの領域が暗くなる(Bの中にあるnon clickableな子にもpressedステートが伝わっている)。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfsvKjjlVvIep5IgyYZ9BYKxIQrG_mPy-eGlbZ1bcIr-y-eqgGD0kw-U-CkylnRB0DyOHc3R0XfDuo4C4oLCL4nb6fdrfbUnf6jypNp-qn0Gon5bgsised9rPXEpp9-vDCM7F_DA/s1600/android43_B.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfsvKjjlVvIep5IgyYZ9BYKxIQrG_mPy-eGlbZ1bcIr-y-eqgGD0kw-U-CkylnRB0DyOHc3R0XfDuo4C4oLCL4nb6fdrfbUnf6jypNp-qn0Gon5bgsised9rPXEpp9-vDCM7F_DA/s320/android43_B.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Android 4.0以前では、子にpressedステートが伝わらない&lt;/h2&gt;&lt;br /&gt;
一方、Android4.0でAをクリックした場合。子にpressedステートが伝わっていないので、子の色が変わらない。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXTCiph1IGxkAsWjLMTohvvlN1leJL3ta33oxfUe06QZuESxLQ3AlqX70ZrVcpFEduyA4w4xu1IgWa6xp483X13Bf3Gec2HsHQyLghR_JmKcNHEbcdMc-mg_5_qXtt7wAl_dYqog/s1600/android40_A.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXTCiph1IGxkAsWjLMTohvvlN1leJL3ta33oxfUe06QZuESxLQ3AlqX70ZrVcpFEduyA4w4xu1IgWa6xp483X13Bf3Gec2HsHQyLghR_JmKcNHEbcdMc-mg_5_qXtt7wAl_dYqog/s320/android40_A.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Android4.0でBをクリックした場合。同様にBの中にある子の色は変わっていない。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTMLz4FtwAsk6XK7Sc1sGt0oPK3LHfRe3irFDZKmU4hmkwCtU7p-zZTBkhppm9WRTP5tPftWHwvBtlx1z5Pa5sPpkWENONW36LFmMao6hOY72hKFQMfuavU0fY5eM3R3spvZfmBw/s1600/android40_B.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTMLz4FtwAsk6XK7Sc1sGt0oPK3LHfRe3irFDZKmU4hmkwCtU7p-zZTBkhppm9WRTP5tPftWHwvBtlx1z5Pa5sPpkWENONW36LFmMao6hOY72hKFQMfuavU0fY5eM3R3spvZfmBw/s320/android40_B.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;なぜ動作が違うか&lt;/h2&gt;&lt;br /&gt;
おそらく関係しているのはView.javaの&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/4d6f066b19f654917bbbd4650a68bea79a471270%5E%21/core/java/android/view/View.java&quot;&gt;このcommit&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
変更後は、ACTION_DOWNでsetPressed()が呼ばれるようになった。setPressed()が呼ばれるとdispatchSetPressed()が呼ばれ、そこから子のViewのsetPressed()が呼ばれる。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/5404775028543933105/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/5404775028543933105' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5404775028543933105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5404775028543933105'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2015/06/android4041viewview.html' title='Android4.0以前と4.1以降では、親のViewをクリックした時に子のViewがどう見えるのかが異なる'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRSh0otltktaIZqVMMIBbdz_TpA2KHrKCpJV5MujSsENRq4SfOAUmzUmVsi2nfRqKzIL2REvYHKClrZAQPMHrtSxcsx02GyjXsvVva1sHpX8DyPZWGKj3TPzkctD2-hvqMjitoZQ/s72-c/android40_normal.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-6237722091225019526</id><published>2015-06-10T12:05:00.000+09:00</published><updated>2015-06-12T09:00:12.351+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Activity"/><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Fragment"/><title type='text'>Activityの再生成にまつわる処理を書くベストな方法</title><content type='html'>AndroidでActivityの再生成にまつわる問題をちゃんと解決しようとすると、非常に煩雑なコードになる。&lt;br /&gt;
&lt;br /&gt;
その煩雑さを解消するクラスを作った。今の所、この方法がベストな方法だと思う。&lt;br /&gt;
&lt;a href=&quot;https://gist.github.com/anolivetree/dd9963f137ebc721ae0f&quot;&gt;Retain.java&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
以下、Activityの再生成に関する典型的な対処法とその問題点。&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Activityの再生成のパターンは２つある&lt;/h2&gt;&lt;br /&gt;
Activityは、以下の場合に再生成される。&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Configuration changeの時(画面の回転など)。プロセスは生きたまま。&lt;br /&gt;
&lt;li&gt;バックグラウンドにいる間にOSによってプロセスごと殺された後、アプリに戻ってきた時。&lt;br /&gt;
&lt;/ol&gt;再生成後の新しいinstanceにデータを渡したいときにどう渡すかが問題となる。  &lt;h3&gt;方法1. onSaveInstanceStateでbundleに入れる&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;processが死んでいた場合でも、データが残っている。&lt;br /&gt;
&lt;li&gt;Bundleに入る型しか保持できない(Integer, Boolean, String, Serializableなど)。&lt;br /&gt;
例えば、通信処理スレッドを再生成後のinstanceに引き渡す、ということは直接はできない。&lt;br /&gt;
&lt;li&gt;onSaveInstanceState()が呼ばれた後には、もうbundleに入れることができない。&lt;br /&gt;
&lt;/ul&gt;&lt;h3&gt;方法2. staticな領域に覚えておく&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;processが死んでいない場合は、データは残っている。&lt;br /&gt;
&lt;li&gt;processが死んでいた場合は、データは残っていない。&lt;br /&gt;
&lt;li&gt;Activityが２つ存在するときに、間違って別のActivityにデータを渡さないようにしなくてはならない。&lt;br /&gt;
&lt;/ul&gt;&lt;h3&gt;方法3. retain用のFragmentを使う&lt;/h3&gt;setRetainInstance(true)なFragmentを用意して、そのretain用Fragmentにデータを覚えさせておく方法。 &lt;a href=&quot;http://developer.android.com/guide/topics/resources/runtime-changes.html&quot;&gt;http://developer.android.com/guide/topics/resources/runtime-changes.html&lt;/a&gt;  &lt;ul&gt;&lt;li&gt;processが死んでいない場合は、データは残っている。&lt;br /&gt;
&lt;li&gt;processが死んでいた場合は、データは残っていない。&lt;br /&gt;
&lt;li&gt;Activityに紐付いたデータ(ThreadにおけるThread Local Storageのように)なので、別のActivityに間違ってデータを渡してしまうことはない。&lt;br /&gt;
&lt;li&gt;Activityがいなくなると、自動でFragmentも消してくれる。&lt;br /&gt;
&lt;/ul&gt;&lt;b&gt;方法3の問題点&lt;/b&gt; &lt;ul&gt;&lt;li&gt;あくまでActivityに結びついた情報なので、Activityに含まれるFragmentごとに別々のretain用fragmentをもたせる、と言ったことは非常にしにくい。&lt;br /&gt;
&lt;li&gt;retain用Fragmentを削除するタイミングが難しい。下手なタイミングでFragmentTransactionをすると、IllegalStateExceptionが出る。&lt;br /&gt;
&lt;li&gt;FragmentActivity, Fragmentを使わなくてはならない。&lt;br /&gt;
&lt;li&gt;コードが読みにくい&lt;br /&gt;
&lt;/ul&gt;&lt;h2&gt;解決方法&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;processが死んだ場合でも、できるだけ情報を残したい、&lt;br /&gt;
&lt;li&gt;でも、bundleに入る情報以外も保持したい&lt;br /&gt;
&lt;li&gt;3の方法は嫌だ&lt;br /&gt;
&lt;/ul&gt;となると結局1と2のハイブリッドな方法で行くしか無い。  1,2の問題点を解消しつつ、1も2も統一的な方法で扱えるためのクラスを作った。 &lt;a href=&quot;https://gist.github.com/anolivetree/dd9963f137ebc721ae0f&quot;&gt;Retain.java&lt;/a&gt;  &lt;h2&gt;使い方&lt;/h2&gt;&lt;pre class=&quot;prettyprint linenums&quot;&gt;private Retain&amp;lt;somedata&amp;gt; retain; // SomeDataは、ParcelableまたはSerializableであること

@Override
protected void onCreate(Bundle savedInstanceState) {
    retain = Retain.forSerializable()
    someData = retain.onCreate(savedInstanceState);
    if (someData == null) {
        someData = new SomeData()
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    retain.onSaveInstanceState(outState, someData);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    retain.onDestroy(this);
}
&lt;/pre&gt;&lt;br /&gt;
これだけで、someDataの情報はできるだけ保持されるし、画面回転等にも対処できる。</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/6237722091225019526/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/6237722091225019526' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6237722091225019526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6237722091225019526'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2015/06/activity.html' title='Activityの再生成にまつわる処理を書くベストな方法'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-3209386068106420480</id><published>2015-05-20T00:48:00.001+09:00</published><updated>2015-05-20T00:48:43.421+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>AndroidのcompileSdkVersionとかbuildToolsVersionとか</title><content type='html'>build.gradleに指定する、compileSdkVersionやtargetSdkVersionなどの説明。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;compileSdkVersion&lt;/h3&gt;Javaのソースをコンパイルするときに使うSDKのバージョン。新しいSDKではAPIやandroid.R.id.xxxの定義が追加されていたりする。&lt;br /&gt;
&lt;br /&gt;
例えば、&lt;a href=&quot;http://developer.android.com/reference/android/view/View.html#requestUnbufferedDispatch(android.view.MotionEvent)&quot;&gt;ViewのrequestUnfufferedDispatch&lt;/a&gt;はAPIレベル21で追加されているので、このAPIを使う場合にはcompileSdkVersionは21以上にする必要がある。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;buildToolsVersion&lt;/h3&gt;ビルドに使うツールチェイン(aapt/dxなど)のバージョン。上位互換なので、最新バージョンを追っていってもあまり問題はない。&lt;br /&gt;
&lt;br /&gt;
SDKバージョンと連動していて、あるバージョンのSDKがリリースされると、一緒に対応する.0.0のバージョンのbuildToolsがリリースされる。例えばAPI 20がリリースされたときには、20.0.0のbuildToolsがリリースされた。&lt;br /&gt;
&lt;br /&gt;
compileSdkVersionの値以上にする必要がある。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;minSdkVersion&lt;/h3&gt;このバージョン未満の端末には、アプリをインストールできなくなる。アプリの動作には影響はない。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;targetSdkVersion&lt;/h3&gt;targetという意味が分かりにくいが、どのバージョンの端末を念頭に置いて開発されたかを表す。この値を変えると、アプリの見た目や挙動が変わるので注意が必要。&lt;br /&gt;
&lt;br /&gt;
例えば、targetSdkVersionが19(Kitkat)の場合、&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;端末バージョンが19以下の場合、特に影響はない。&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;端末バージョンが20(Lollipop)以上の場合には、19互換モードでアプリが動く。アプリの見た目は19の見た目になり、20で新たに導入された挙動はOFFになる。&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
targetSdkVersionで挙動が変わる例:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;19以上の端末でtargetSdkVersionを19以上にすると、AlarmManagerのset()でセットしたアラームのなるタイミングは若干不正確になる(バッテリ消費を抑えるため)&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;14以上の端末でtargetSdkVersionを14以上にすると、hardware accelerationがデフォルトでONになる。&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;10以上の端末でtargetSdkVersionを10以上にすると、UIスレッドでネットワークアクセスできなくなる。&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;a href=&quot;http://developer.android.com/guide/topics/manifest/uses-sdk-element.html&quot;&gt;公式ドキュメントのtargetSdkVersion&lt;/a&gt;には、テストした端末のバージョンを書けと書いてあるが、まさにその通り。20の端末でしかテストしていないのにtargetSdkVersionを21にすると、21の端末で動かない可能性がある。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/3209386068106420480/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/3209386068106420480' title='1 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3209386068106420480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3209386068106420480'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2015/05/androidcompilesdkversionbuildtoolsversi.html' title='AndroidのcompileSdkVersionとかbuildToolsVersionとか'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-3215921728405212797</id><published>2014-05-05T11:52:00.000+09:00</published><updated>2014-05-05T11:54:27.879+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="fastdx.jar"/><category scheme="http://www.blogger.com/atom/ns#" term="gradle"/><title type='text'>dx.jarをfastdx.jarに入れ替えて、Androidのビルドを50%くらい速くする</title><content type='html'>Androidのアプリのビルドは非常に遅い。原因の一つはGradleが重いことなのだが、実はDEXとPRE-DEXのフェーズも無駄な処理を行なっているため、非常に時間がかかる。&lt;br /&gt;
そこで、DEXとPRE-DEXを行なっているdx.jarの高速版のfastdx.jarを作成した。全体のビルド時間は、私の環境では50%くらい高速化された。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://fastdex.edicy.co/&quot;&gt;fastdx.jarのダウンロードはこちら&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
オリジナルのdx.jarが遅い原因は、大きく２つある。&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;無駄に.classから.dexの作成を行なっている(キャッシュしていない)&lt;/li&gt;
&lt;li&gt;複数のdexのマージの処理に無駄がある&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;h3&gt;無駄に.classから.dexの作成を行なっている(キャッシュしていない)&lt;/h3&gt;&lt;br /&gt;
オリジナルのdx.jarでは、.jarに含まれていた.classが一つでも変更された場合、.jarに含まれていた全.classファイルを再度.dexにコンバートし直している。&lt;br /&gt;
例えば、.jarの中身が以下の3つの.classを含んでいたとする。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;a.class
b.class
c.class&lt;/pre&gt;&lt;br /&gt;
a.classが変更された場合、dx.jarはa.dexのみならず、b.dex, c.dexも再度生成する。このコンバートに結構時間がかかる。&lt;br /&gt;
&lt;br /&gt;
fastdx.jarでは、コンバート済みの.dexをキャッシュすることで、無駄に.dexへのコンバートが発生しないようにした。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;複数のdexのマージの処理に無駄がある&lt;/h3&gt;&lt;br /&gt;
複数のdexをマージする際、例えばa.dexからd.dexまでをマージする際、オリジナルのdx.jarは以下のようにdexをひとつずつマージする。&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;a.dex + b.dex = ab.dex
ab.dex + c.dex = abc.dex
abc.dex + d.dex = abdc.dex
&lt;/pre&gt;dexファイルをいちいち生成、再読み込み、を行うため、非常に時間がかかる。&lt;br /&gt;
&lt;br /&gt;
fastdx.jarでは、マージを一気に行う。&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;a.dex + b.dex + c.dex + d.dex = abcd.dex
&lt;/pre&gt;&lt;br /&gt;
このため無駄なdexの生成と読み込みが無くなり、高速化されている。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/3215921728405212797/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/3215921728405212797' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3215921728405212797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3215921728405212797'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2014/05/dxjarfastdxjarandroid50.html' title='dx.jarをfastdx.jarに入れ替えて、Androidのビルドを50%くらい速くする'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-6059999391902641803</id><published>2014-04-24T15:58:00.000+09:00</published><updated>2014-06-10T10:56:02.856+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Android Studio"/><category scheme="http://www.blogger.com/atom/ns#" term="gradle"/><category scheme="http://www.blogger.com/atom/ns#" term="IntelliJ"/><title type='text'>AndroidのGradleでのビルドが遅いのをちょっと速くする</title><content type='html'>Gradleを使ってAndroidアプリのビルドをしていると、あまりのビルドの遅さについついGradleに移行したことを後悔してしまいそうになる。&lt;br /&gt;
遅い原因を調べて、2つほどビルドを速くするポイントを発見した。&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;実はGradleデーモンが使われていない問題&lt;/li&gt;
&lt;li&gt;実はlibrary projectはReleaseとDebugの両方がビルドされている問題&lt;/li&gt;
&lt;/ul&gt;以下、IntelliJ 13.1.2での症状&amp;対処法だが、Android Studioでも同じ方法で速くなると思われる&lt;br /&gt;
&lt;br /&gt;
&lt;font color=&quot;red&quot;&gt;前者は、Android Studio 0.6.0で直ったようです。&lt;/font&gt;&lt;br&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;実はGradleデーモンが使われていない問題&lt;/h2&gt;&lt;br /&gt;
.gradle/gradle.propertiesに&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;code&gt;org.gradle.daemon=true&lt;/code&gt;&lt;/pre&gt;と書いておけばGradleデーモンが使われるので立ち上がりが速くなる、というのはあちこちに書いてあるが、実はGradleデーモンが使われていない可能性がある。&lt;br /&gt;
&lt;br /&gt;
その理由は2つ。&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;IntelliJはGradleデーモンがいない場合にはGradleデーモンを起動するが、アイドルタイムアウトが60秒(固定値)。そのため、次にビルドするときにはGradleデーモンが既に死んでいる。&lt;/li&gt;
&lt;li&gt;手動でGradleデーモンを立ち上げたとしても、IntelliJが起動しようとするGradleとあまりに引数が違うと、新たに別のGradleデーモンが(timeout60秒で)起動する。&lt;/li&gt;
&lt;/ul&gt;Gradleデーモンの引数やアイドルタイムアウトは、ps all wwで確認できる。&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;code&gt;0  1000 10170     1  20   0 2124512 1254752 futex_ Sl pts/3    11:15 /usr/lib/jvm/java-6-oracle/bin/java -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -Dfile.encoding=UTF-8 -cp /home/sakurai/.gradle/wrapper/dists/gradle-1.11-all/7qd8qq8te5j4f5q9aaei3gh3lj/gradle-1.11/lib/gradle-launcher-1.11.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 1.11 /home/sakurai/.gradle/daemon &lt;font color=red&quot;&gt;10800000&lt;/font&gt; 7e2c5ad5-a731-455d-a37b-699b5c251ea6 -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -Dfile.encoding=UTF-8&lt;/code&gt;&lt;/pre&gt;IntelliJでのビルド直後にps all wwで、timeoutの値をチェックしてみると良い。数値が60000の場合には、60秒で死ぬデーモンが使われている。タイムアウトが長いデーモンを使うには、手動でGradleを立ち上げるしか無い。&lt;br /&gt;
&lt;br /&gt;
また、Gradleの引数が一致していない場合には、IntelliJのSettings-&gt;Gradle-&gt;Gradle VM Optionsの値を、手動で起動したGradleと合わせておく必要がある。私の場合には、以下を設定してある。&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;-XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;実はlibrary projectはReleaseとDebugの両方がビルドされている問題&lt;/h2&gt;&lt;br /&gt;
Build VariantsをDebugにしていると、library projectはReleaseとDebugの両方がビルドされている(library以外は関係ない)。&lt;br /&gt;
&lt;br /&gt;
現状、Debugビルドをしていても、必ずReleaseビルドのlibraryが使われてしまうというバグがある。&lt;br /&gt;
&lt;a href=&quot;https://code.google.com/p/android/issues/detail?id=52962&amp;can=1&amp;q=gradle%20compileRelease%20library&amp;colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&quot;&gt;Gradle plugin does not propagate debug/release to dependencies&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
このバグの副作用として、アプリをDebugビルドした場合に、library projectはReleaseとDebugの両方がビルドされてしまうようだ。&lt;br /&gt;
&lt;br /&gt;
Gradleの出力例: (DebugもReleaseもビルドされている)&lt;br /&gt;
&lt;pre class=&quot;code&quot;&gt;&lt;code&gt;:ActionBarSherlock:preReleaseBuild
:ActionBarSherlock:checkReleaseManifest
...
:ActionBarSherlock:preBuild
:ActionBarSherlock:preDebugBuild&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
どうせReleaseビルドしか使われないのだから、最初からlibraryはReleaseビルドしかしないようにしてしまえばよい。&lt;br /&gt;
&lt;br /&gt;
IntelliJのウィンドウの左下のBuild Variantをクリックし、libraryプロジェクトのBuild Variantは全てReleaseに変えておく。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjyomwKm3AoPQdJ2EVoB7edidPLxFCY480MxxumFkbBeel6sZ_jLUuvqmDXtb-aHvngKobw0WGpVdIw4qHoMw_uQvInDgJ6QOGpXwiP0Qz9703pyJe5VmLxR2bzKxZOBLows1c7w/s1600/variant.png&quot; imageanchor=&quot;1&quot; &gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjyomwKm3AoPQdJ2EVoB7edidPLxFCY480MxxumFkbBeel6sZ_jLUuvqmDXtb-aHvngKobw0WGpVdIw4qHoMw_uQvInDgJ6QOGpXwiP0Qz9703pyJe5VmLxR2bzKxZOBLows1c7w/s320/variant.png&quot; /&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/6059999391902641803/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/6059999391902641803' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6059999391902641803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6059999391902641803'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2014/04/androidgradle.html' title='AndroidのGradleでのビルドが遅いのをちょっと速くする'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-8980048530915909561</id><published>2013-11-19T10:08:00.001+09:00</published><updated>2013-11-19T10:08:42.318+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>ある特定の文字列をTAGにすると、Log.xが出力されない</title><content type='html'>Androidのandroid.util.Logで、ある特定の文字列をTAGにした場合には、ログが出力されない。&lt;br /&gt;
&lt;br /&gt;
ログが出力されないTAGは、以下の通り。&lt;ul&gt;&lt;li&gt;HTC_RIL&lt;br /&gt;
&lt;li&gt;RILで始まる文字列&lt;br /&gt;
&lt;li&gt;AT&lt;br /&gt;
&lt;li&gt;GSM&lt;br /&gt;
&lt;li&gt;STK&lt;br /&gt;
&lt;li&gt;CDMA&lt;br /&gt;
&lt;li&gt;PHONE&lt;br /&gt;
&lt;li&gt;SMS&lt;/ul&gt;電話番号を扱うアプリを作っていてTAGを&quot;PHONE&quot;にしていたところ、ログに何も出力されずに悩んでしまった。
&lt;p&gt;参考:&lt;br/&gt;
&lt;a href=&quot;http://tools.oesf.biz/android-4.0.1_r1.0/xref/system/core/liblog/logd_write.c#__android_log_buf_write&quot;&gt;logd_write.c&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/8980048530915909561/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/8980048530915909561' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/8980048530915909561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/8980048530915909561'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/11/taglogx.html' title='ある特定の文字列をTAGにすると、Log.xが出力されない'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-6155817604419790270</id><published>2013-06-18T14:31:00.000+09:00</published><updated>2013-06-18T14:31:04.509+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><title type='text'>Androidアプリのテストに役立つサービス</title><content type='html'>Androidアプリのテストに役立つサービス。&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;&lt;a href=&quot;http://developer.samsung.com/remotetestlab/rtlDeviceList.action&quot;&gt;Samsung Remote Test Lab&lt;/a&gt;&lt;/h2&gt;サムスンの端末をリモートで操作でき、アプリのインストールやテストが行える。サムスンの機種がいろいろそろっている。無料。&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;&lt;a href=&quot;https://www.apkudo.com/&quot;&gt;Apkudo&lt;/a&gt;&lt;/h2&gt;apkをアップロードすると、多数(250くらい)の端末上でのmonkeyテストを自動で行なって結果を表示してくれるサービス。無料。日本の端末はあまり用意されていない。&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;&lt;a href=&quot;http://appkitbox.com/testkit&quot;&gt;Remote TestKit&lt;/a&gt;&lt;/h2&gt;端末をリモートで操作でき、アプリのインストールやテストが行える。日本の端末が豊富に用意されているので、日本向けのアプリを出す際には便利なサービス。&lt;br /&gt;
以前とある端末でのみ落ちるバグがあり、その原因を調べるときに同じ作者の&lt;a href=&quot;http://www.katomakku.com/rental.html&quot;&gt;リモート・スマホ・レンタル&lt;/a&gt;にお世話になった。&lt;br /&gt;
&lt;br /&gt;
Linux版のクライアントが無いため私は試せていないが、デバッガでリモートデバッグができたり、adb shellが動作したりもするらしい。&lt;br /&gt;
1時間945円ほど。&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/6155817604419790270/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/6155817604419790270' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6155817604419790270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6155817604419790270'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/06/android.html' title='Androidアプリのテストに役立つサービス'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-5371686129124482134</id><published>2013-06-07T13:06:00.000+09:00</published><updated>2013-06-07T13:06:21.208+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Fragment"/><title type='text'>onCreateの引数savedInstanceStateは、Fragmentが再生成したかどうかの判断には(厳密には)使えない</title><content type='html'>Fragmentの再生成が起こるときには、onCreate(Bundle savedInstanceState)のsavedInstanceStateが必ず!=nullになる。&lt;br /&gt;
&lt;br /&gt;
…と思っていたのだが、そうはならない条件があることがわかった。&lt;br /&gt;
つまり、Fragmentが再生成されたにも関わらず、savedInstanceState=nullとなる場合がある。&lt;br /&gt;
&lt;br /&gt;
再生成されたのにsavedInstanceState=nullになるのは、以下の2つの条件を満たした場合。&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;FragmentがUIを持たない。つまり、onCreateViewでnullを返している&lt;/li&gt;
&lt;li&gt;onSaveInstanceState(Bundle outState)で、outStateに何もputしていない&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
要は、Bundleに誰も何もセットしていない場合には、再生成時のsavedInstanceStateはnullになる(空のBundleが渡されてくるわけではない)。&lt;br /&gt;
&lt;br /&gt;
なお、Viewは自らの状態をBundleに保存しているので、FragmentがViewを持つ場合には通常Bundleは空にはならない。そのため、savedInstanceStateがnullかどうかによって、再生成かどうかを判断できる。</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/5371686129124482134/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/5371686129124482134' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5371686129124482134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5371686129124482134'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/06/oncreatesavedinstancestatefragment.html' title='onCreateの引数savedInstanceStateは、Fragmentが再生成したかどうかの判断には(厳密には)使えない'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-3666437375634677809</id><published>2013-04-18T22:55:00.001+09:00</published><updated>2013-04-18T22:56:27.119+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Fragment"/><category scheme="http://www.blogger.com/atom/ns#" term="Loader"/><title type='text'>Fragmentでloaderを使っている場合は、setRetainInstance(true)してはいけない</title><content type='html'>&lt;p&gt;FragmentでsetRetainInstance(true)としていると、loaderのonLoadFinished()が呼ばれないことがある。&lt;br /&gt;
そのため、loaderを使っている場合は、setRetainInstance(true)としてはいけない。&lt;/p&gt;&lt;p&gt;自作アプリでloaderとsetRetainInstance(true)を混ぜて使っていて、なぜかonLoadFinished()が呼ばれないことがあるのでググってみたら、Dianne Hackborn(Googleの人)も&lt;a href=&quot;https://groups.google.com/d/msg/android-developers/DbKL6PVyhLI/4BZKQd1dJ6UJ&quot;&gt;loaderとsetRetainInstance()を混ぜて使うな&lt;/a&gt;と言っていた。&lt;/p&gt;&lt;p&gt;以下の方法で、「onLoadFinished()が呼ばれない場合」を再現できる(GalaxyNexus + JellyBeanで確認)。&lt;/p&gt;&lt;h3&gt;ソースコード&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;http://developer.android.com/guide/components/loaders.html&quot;&gt;Googleによるサンプルコード&lt;/a&gt;に従った書き方をしている。onActivityCreated()でinitLoader()をし、onLoaderReset()でswapCursor(null)している。&lt;/p&gt;&lt;pre class=&quot;prettyprint linenums&quot;&gt;public class MyFragment extends ListFragment implements LoaderManager.LoaderCallbacks&lt;cursor&gt; {

    private MyAdapter adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        adapter = new MyAdapter(getActivity());
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setListAdapter(adapter);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        setListAdapter(null);
    }

    @Override
    public Loader&lt;cursor&gt; onCreateLoader(int id, Bundle args) {
        return new CursorLoader(getActivity(), ...);
    }

    @Override
    public void onLoadFinished(Loader&lt;cursor&gt; loader, Cursor data) {
        adapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader&lt;cursor&gt; loader) {
        adapter.swapCursor(null);
    }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;手順&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;携帯を横(landscape)にしておく。この状態ではListFragmentにCursorの中身が表示されている。&lt;br /&gt;
&lt;li&gt;電源ボタンを押して、スリープに入れる。&lt;br /&gt;
&lt;li&gt;携帯を縦に持ちかえる。電源ボタンを押してスリープを解除し、ロックも解除する。すると、ListFragmentの表示が空になっている。&lt;br /&gt;
&lt;/ol&gt;&lt;h3&gt;何が起きているのか&lt;/h3&gt;&lt;p&gt;電源ボタンを押してスリープに入れた時に、以下の順でcallbackが呼ばれる。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;onLoaderReset&lt;br /&gt;
&lt;li&gt;onDestroyView&lt;br /&gt;
&lt;li&gt;onViewCreated&lt;br /&gt;
&lt;li&gt;onActivityCreated&lt;br /&gt;
&lt;/ol&gt;&lt;p&gt;ロック画面が縦だからだと思うのだが、landscapeのActivityが破棄され、portlaitのActivityが再生成される。 onLoaderReset()は呼ばれているが、Activity再生成後のonLoaderFinish()は呼ばれていない。そのため、スリープとロックを解除すると、ListFragmentが空になっている。&lt;/p&gt;&lt;h3&gt;対処方法&lt;/h3&gt;&lt;p&gt;setRetainInstance(true)を呼ばない、というのが一番確実な対処方法だが、onActivityCreatedでinitLoader()ではなくrestartLoader()を呼ぶという方法でも、試した限り動作するようだ。ただしrestartLoader()を使う方法だと、多少無駄にqueryを行うことになる。&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/3666437375634677809/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/3666437375634677809' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3666437375634677809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3666437375634677809'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/04/fragmentloadersetretaininstancetrue.html' title='Fragmentでloaderを使っている場合は、setRetainInstance(true)してはいけない'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-5767302812037341369</id><published>2013-04-15T09:37:00.000+09:00</published><updated>2013-04-15T09:37:51.145+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Adapter"/><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Spinner"/><title type='text'>Spinnerでは、AdapterのgetItemViewType()とgetViewTypeCount()が使えない</title><content type='html'>ListViewでは、AdapterのgetItemViewType()とgetViewTypeCount()をoverrideすることで、行ごとに違うViewを使うことができる。&lt;br /&gt;
しかし、SpinnerではgetItemViewType()とgetViewTypeCount()が呼ばれなく、行ごとに違うViewにするにはListViewとは異なる方法を取る必要がある。&lt;br /&gt;
&lt;br /&gt;
Spinnerのprivateな内部クラスである&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/Spinner.java&quot;&gt;DropDownAdapter&lt;/a&gt;がAdapterをラップしているのだが、このラッパーは以下のように固定値を返すように実装されていて、setAdapter()でセットしたAdapterのgetItemViewType()とgetViewTypeCount()を呼んでくれない。&lt;br /&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;        public int getItemViewType(int position) {
            return 0;
        }

        public int getViewTypeCount() {
            return 1;
        }
&lt;/pre&gt;Spinnerで行ごとに違うViewを使うには、以下のようにすると良い。&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Viewの中に複数のViewを含めておいて、見せたいViewのVisibilityだけvisibleにし、その他をgoneにする。&lt;br /&gt;
&lt;li&gt;getView()でconvertViewを再利用するのをやめて、毎回Viewをinflateする。もしくは、convertViewで渡されるViewのタイプを見て、再利用するかどうかを自分で決める。&lt;br /&gt;
&lt;/ul&gt;参考: 
&lt;a href=&quot;https://code.google.com/p/android/issues/detail?id=17128&quot;&gt;https://code.google.com/p/android/issues/detail?id=17128&lt;/a&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/5767302812037341369/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/5767302812037341369' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5767302812037341369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5767302812037341369'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/04/spinneradaptergetitemviewtypegetviewtyp.html' title='Spinnerでは、AdapterのgetItemViewType()とgetViewTypeCount()が使えない'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-3385581472721202828</id><published>2013-04-15T09:23:00.000+09:00</published><updated>2013-04-15T09:25:04.924+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Adapter"/><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="ListView"/><title type='text'>ListViewで、行ごとに違うViewを使う</title><content type='html'>ListViewでAdapterを使う際、getItemViewType()とgetViewTypeCount()をoverrideすることで、ListView中に複数のViewを混ぜることができる。&lt;br /&gt;
例えば、3種類のviewが存在する場合、&lt;br /&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;int getItemViewType(int position) {
    return position % 3; // 行じ応じたViewのタイプを返す。タイプは0,1,2,3...と0始まりであること。
}

int getViewTypeCount() {
    return 3; // Viewのタイプの数
}
&lt;/pre&gt;としておく。&lt;br /&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;View getView(int position, View convertView, ViewGroup parent)
&lt;/pre&gt;に渡されてくるconvertViewには再利用されるべきViewが渡されてくるのだが、上記のようにgetItemViewType()とgetViewTypeCount()をoverrideしていれば、そのpositionに応じた正しい種類のViewがconvertViewに渡されてくる。&lt;br /&gt;
&lt;br /&gt;
コード例:&lt;br /&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;int getItemViewType(int position) {
    return position % 3; // 行じ応じたViewのタイプを返す。タイプは0,1,2,3...と0始まりであること。
}

int getViewTypeCount() {
    return 3; // Viewのタイプの数
}

View getView(int position, View convertView, ViewGroup parent) {
    switch (getItemViewType(position)) {
    case 0:
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item1, parent, false);
        }
        break;
    case 1:
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item2, parent, false);
        }
        break;
    case 2:
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item3, parent, false);
        }
        break;
    }
    return convertView;
}
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/3385581472721202828/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/3385581472721202828' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3385581472721202828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3385581472721202828'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/04/listviewview.html' title='ListViewで、行ごとに違うViewを使う'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-8403601453702885182</id><published>2013-04-02T21:26:00.000+09:00</published><updated>2013-04-02T21:26:34.993+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="SEO"/><title type='text'>Google PlayでAndroidアプリのSEO(検索エンジン最適化)をするためのツール</title><content type='html'>Google Playでアプリをキーワード検索する際に、アプリの説明文によって検索順位が大きく異なる。&lt;br /&gt;
つまり、自分のアプリを見つけてもらいやすくするには、SEO(検索エンジン最適化)が必要になる。&lt;br /&gt;
&lt;br /&gt;
しかし、Google Playで自分のアプリの検索順位を調べるのは結構骨が折れる。&lt;br /&gt;
&lt;br /&gt;
そこで、指定したキーワードで検索した場合にアプリが何位に位置するのかを調べるツールを作った。&lt;br /&gt;
&lt;a href=&quot;https://github.com/anolivetree/android-search-ranking&quot;&gt;android-search-ranking&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;使い方&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;
  $ android-search-ranking -pkg com.gmail.anolivetree -lang en &quot;shrink&quot; &quot;photo resize&quot;
  #2 for shrink
  #20 for photo resize
&lt;/code&gt;&lt;/pre&gt;出力の意味は、&quot;shrink&quot;で検索した場合にはランキングは2位、&quot;photo resize&quot;で検索した場合には20位という事。ランク外の場合には#0と表示される。&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/8403601453702885182/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/8403601453702885182' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/8403601453702885182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/8403601453702885182'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/04/google-playandroidseo.html' title='Google PlayでAndroidアプリのSEO(検索エンジン最適化)をするためのツール'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-4624932120766331243</id><published>2013-03-21T12:29:00.000+09:00</published><updated>2013-03-21T12:29:50.456+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="gmail"/><title type='text'>Gmailでsubject入りのテンプレートを実現する方法</title><content type='html'>&lt;p&gt;GmailのLabでは、Canned Responsesというテンプレート機能が提供されている。&lt;br /&gt;
しかし、この機能は本文部分だけしかテンプレートに含めることができず、SubjectやToなどは覚えておいてくれない。&lt;/p&gt;&lt;p&gt;いろいろ試行錯誤した結果、bookmarkとmailto:を組み合わせることでテンプレートが実現できることに気づいた。&lt;/p&gt;&lt;p&gt;&lt;b&gt;準備&lt;/b&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://sislands.com/coin70/week6/mailtoCreator.htm&quot;&gt;mailto: Creator&lt;/a&gt;のページをローカルに保存する。&lt;br /&gt;
&lt;li&gt;保存したhtmlの中で、escape()関数を呼んでいる二箇所を、encodeURIComponent()に書き換える&lt;br /&gt;
&lt;/ol&gt;&lt;p&gt;&lt;b&gt;テンプレート作成方法&lt;/b&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;先程保存したhtmlをブラウザで開く&lt;br /&gt;
&lt;li&gt;ToやSubject, Bodyなどを適当に埋め、&quot;Create URL&quot;を押す。&lt;br /&gt;
&lt;li&gt;bookmarkを作り、Nameをテンプレート名、URLは&quot;Create URL&quot;で作成したURLを入れる。&lt;br /&gt;
&lt;/ol&gt;&lt;p&gt;これで完了。以後はそのbookmarkを開くとメールのToやSubject,Bodyが入った状態でGmailが起動する。&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/4624932120766331243/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/4624932120766331243' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/4624932120766331243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/4624932120766331243'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2013/03/gmailsubject.html' title='Gmailでsubject入りのテンプレートを実現する方法'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-2494234617547664481</id><published>2012-11-01T23:45:00.000+09:00</published><updated>2012-11-01T23:45:29.574+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Fragment"/><title type='text'>DialogFragmentの落とし穴にはまらないための方法</title><content type='html'>AndroidにFragmentが導入されて以来、Dialogを直接使うことは非推奨となり、DialogFragmentを使うことが推奨されている。&lt;br /&gt;
&lt;br /&gt;
Dialogはあまり深く考えずに使っても大丈夫だったのだが、DialogFragmentは落とし穴が多数あり、正しく使わないとアプリが落ちてしまう。具体的には、Fragmentの再生成が発生したときに正しく動作しなくなる。&lt;br /&gt;
&lt;br /&gt;
以下では「FragmentからDialogFragmentを開き、結果(OK/Cancel)をFragmentに返す」という場合を例にして、DialogFragmentの落とし穴を回避するための書き方を説明する。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;正しいコード&lt;/h3&gt;&lt;pre class=&quot;prettyprint linenums&quot;&gt;public class OkCancelDialog extends DialogFragment {

    static public interface OkCancelListener {
        void onDialogPositiveClick(long id);
        void onDialogNegativeClick(long id);
    }

    // Fragmentの再生成の時に呼ばれるので、引数なしのpublicなコンストラクタが必要
    public OkCancelDialog() {
    }

    // targetFragmentは、結果を受け取るFragment。OkCancelListenerを実装したFragmentであること。
    public OkCancelDialog(long dataId, OkCancelListener targetFragment) {
        if (targetFragment != null &amp;amp;&amp;amp; !(targetFragment instanceof Fragment)) {
            throw new RuntimeException(&quot;targetFragment is not Fragment&quot;);
        }
        // Fragmentの再生成後でも使いたい値は、bundleに入れてsetArgumentしておく。
        Bundle bundle = new Bundle();
        bundle.putLong(&quot;id&quot;, dataId);
        setArguments(bundle);
        // 結果を受け取るFragmentは、直接Fragmentの変数には入れずに、
        // setTargetFragment()/getTargetFragment()を使う
        setTargetFragment((Fragment)targetFragment, 0);
    }

    public long getDataId() {
        return getArguments().getLong(&quot;id&quot;, -1);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(&quot;Message&quot;);
        builder.setPositiveButton(&quot;OK&quot;, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // getTargetFragment()は、Fragmentが再生成された場合でも、正しいinstanceを返してくれる。
                OkCancelListener listener = (OkCancelListener) getTargetFragment();
                listener.onDialogPositiveClick(getDataId());
                dialog.cancel();
            }
        });
        builder.setNegativeButton(&quot;Cancel&quot;, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                OkCancelListener listener = (OkCancelListener) getTargetFragment();
                listener.onDialogNegativeClick(getDataId());
                dialog.cancel();
            }
        });
        return builder.create();
    }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;間違い1 DialogFragmentをinner classにする&lt;/h3&gt;&lt;pre class=&quot;prettyprint linenums&quot;&gt;public class MyFragment extends Fragment {

    public class OkCancelDialog extends DialogFragment {
        ...
    }
}
&lt;/pre&gt;Fragmentの再生成時には、自動的にFragmentのpublicな引数なしのコンストラクタが呼ばれる。inner classにするとFragmentの自動生成ができないため、落ちる。&lt;br /&gt;
&lt;br /&gt;
staticなinner classにするのでも良いが、出来ればファイルを分けるほうが(間違えにくいので)良い。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;間違い2 引数なしのコンストラクタを作らない&lt;/h3&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint linenums&quot;&gt;    public OkCancelDialog() {
    }
&lt;/pre&gt;を省略、またはprivateにすると、Fragmentの再生成時に落ちる。Fragmentの再生成時には、外から引数なしのコンストラクタが自動で呼ばれるためである。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;間違い3 結果を受け取るFragmentへの参照を直接保持する&lt;/h3&gt;&lt;pre class=&quot;prettyprint linenums&quot;&gt;    private OkCancelListener listener = null;

    public OkCancelDialog(long dataId, OkCancelListener targetFragment) {
        listener = targetFragment;
        ...
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        ...
        builder.setPositiveButton(&quot;OK&quot;, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                listener.onDialogPositiveClick(getDataId());
            }
        }
    }
&lt;/pre&gt;上のようにすると、Fragmentの再生成時にはメンバ変数listenerはnullになってしまう。なぜなら新しく作られたFragmentは以前とは別のオブジェクトで、かつ引数なしのコンストラクタが呼ばれているためである。しかも結果を受け取るFragmentも再生成されて別のオブジェクトになっているので、もはやlistenerの値は意味を持たない。&lt;br /&gt;
&lt;br /&gt;
setTargetFragment()/getTargetFragment()を使えば、Fragmentが再生成された場合でも、新しく生成されたFragmentの参照を取得することができる。&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;間違い4 setArguments()を使わずに、値をメンバ変数に覚えておく&lt;/h3&gt;&lt;pre class=&quot;prettyprint linenums&quot;&gt;    private long dataId = -1;

    public OkCancelDialog(long dataId, OkCancelListener targetFragment) {
        this.dataId = dataId;
        ...
    }
&lt;/pre&gt;間違い3と似ているが、Fragmentが再生成されたときには、メンバ変数dataIdは-1になっている。再生成後でも使いたい値はBundleに入れ、setArguments()しておけばよい。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/2494234617547664481/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/2494234617547664481' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/2494234617547664481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/2494234617547664481'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/11/dialogfragment.html' title='DialogFragmentの落とし穴にはまらないための方法'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-1262628139458320276</id><published>2012-11-01T11:53:00.000+09:00</published><updated>2012-11-01T11:53:41.088+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>AndroidのActivityのライフサイクルに関して多くの人が誤解している点</title><content type='html'>AndroidのActivityに関していろいろ調べた。おそらく(私も含めて)多くの人が誤解している点をまとめた。
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
メモリ不足の時、あるActivityだけが破棄されるという事は無い&lt;/h3&gt;
システムのメモリが足りなくなったときにはLow Memory Killerが動作するが、Low Memory Killerはprocessの中の、あるActivityだけを破棄するということはせず、process全体をkillする。
&lt;br /&gt;
&lt;br /&gt;
メモリ不足により、「あるActivityはonDestroyが呼ばれずに破棄され、他のActivityは生きている」、ということは起こらない。processがkillされたとき以外は、onCreateとonDestroyはセットで呼ばれる。
&lt;br /&gt;
&lt;br /&gt;
メモリが足りなくなってprocessがkillされるのをシミュレートするには、単にDDMSでprocessを選択し、STOPボタンを押せば良い。
&lt;br /&gt;
&lt;br /&gt;
参考:&lt;br /&gt;
&lt;a href=&quot;https://groups.google.com/forum/#!msg/android-developers/WF-STG7GdrI/QrBL0btjCxYJ&quot;&gt;https://groups.google.com/forum/#!msg/android-developers/WF-STG7GdrI/QrBL0btjCxYJ&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
processがkillされても、Activityのスタックの記録は残っている&lt;/h3&gt;
Low Memory Killerによりprocessがkillされても、Activityのスタックの記録(TaskRecord)は残っている。onSaveInstanceState()で保存したBundleも残っているし、Activityを起動したIntent(=getIntent()で取得できるIntent)も残っている。&amp;nbsp;
&lt;br /&gt;
&lt;br /&gt;
processをkillした(killされた)後に、&lt;br /&gt;
&lt;code&gt;$ adb shell dumpsys activity&lt;/code&gt;&lt;br /&gt;
を実行してみると、Activityのスタックが残っている事を確認できる。
&lt;br /&gt;
&lt;br /&gt;
processがkillされた後にそのアプリを起動すると、一番上のActivityのonCreateがsavedInstanceState!=nullで呼ばれる。backボタンを押すと、今度は一つ下のActivityのonCreateがsavedInstanceState!=nullで呼ばれる。

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Activityのスタックの記録は、暫くすると無くなる&lt;/h3&gt;
Activityのスタックの記録は15-30分など、暫くすると無くなるが、Low Memory Killerでプロセスがkillされる事と、Activityスタックの記録が無くなる事は、無関係と考えて良い。&amp;nbsp;
&lt;br /&gt;
&lt;br /&gt;
時間が経ってもActivityのスタックの記録が無くならないようにするには、rootのActivityに
&lt;code&gt;android:alwaysRetainTaskState=&quot;true&quot;&lt;/code&gt;&lt;br /&gt;
を指定すればよい。&amp;nbsp;
&lt;br /&gt;
&lt;br /&gt;
参考:&lt;br /&gt;
&lt;a href=&quot;http://stackoverflow.com/questions/7107614/for-how-long-does-android-save-a-killed-activitys-state&quot;&gt;http://stackoverflow.com/questions/7107614/for-how-long-does-android-save-a-killed-activitys-state&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/1262628139458320276/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/1262628139458320276' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/1262628139458320276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/1262628139458320276'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/11/androidactivity.html' title='AndroidのActivityのライフサイクルに関して多くの人が誤解している点'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-7759148981138050142</id><published>2012-10-11T18:42:00.003+09:00</published><updated>2012-10-11T18:44:13.556+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>AndroidのNotification.BuilderのtitleやtextやcontentInfoはどれがどれなのか</title><content type='html'>AndroidのNotification.Builderには、title, text, contentInfo, numberなどをセットすることができるが、どれがどこに表示されるのかの説明が公式ページには一切無い。
&lt;p/&gt;
仕方ないので、自分でGingerbread(SH-06D)とJelly Bean(Galaxy Nexus)で見え方を調べてみた。
&lt;p/&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEhyp2UfaKb8NbezuLralAwyZbNkzDyUabuLfHFoxWxt32lH01ROg6gybZipTXxFMjXwluVSem0KEGPMM6udlR5JUrySZwNgbTh7__U6otrBqSKZS6S_TOF4rzD240cCz-Gkc3uA/s1600/Untitled3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;178&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEhyp2UfaKb8NbezuLralAwyZbNkzDyUabuLfHFoxWxt32lH01ROg6gybZipTXxFMjXwluVSem0KEGPMM6udlR5JUrySZwNgbTh7__U6otrBqSKZS6S_TOF4rzD240cCz-Gkc3uA/s320/Untitled3.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;

&lt;p/&gt;
上がGingerbreadで表示させた場合。下がJelly Bean。
比べてわかったこと。
&lt;ul&gt;
&lt;li&gt;setContentInfoとsetNumberは、同じ領域に表示される(setContentInfoの方が強い様だ)。&lt;/li&gt;
&lt;li&gt;setContentInfo(とsetNumber)は、Gingerbreadでは表示されない&lt;/li&gt;
&lt;/ul&gt;


</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/7759148981138050142/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/7759148981138050142' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/7759148981138050142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/7759148981138050142'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/10/androidnotificationbuildertitletextcont.html' title='AndroidのNotification.BuilderのtitleやtextやcontentInfoはどれがどれなのか'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEhyp2UfaKb8NbezuLralAwyZbNkzDyUabuLfHFoxWxt32lH01ROg6gybZipTXxFMjXwluVSem0KEGPMM6udlR5JUrySZwNgbTh7__U6otrBqSKZS6S_TOF4rzD240cCz-Gkc3uA/s72-c/Untitled3.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-224888056009940082</id><published>2012-10-05T23:01:00.000+09:00</published><updated>2012-10-05T23:01:08.706+09:00</updated><title type='text'>Goでchannelに入れることができる型を限定する</title><content type='html'>以下のようなstructがあったとする。&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
type Cmd1 struct {
    id int
}
type Cmd2 struct {
    msg string
}&lt;/code&gt;&lt;/pre&gt;
あるchannelにCmd1とCmd2の両方を入れたいとする。その場合&lt;code&gt;var ch chan interface{}&lt;/code&gt;とすればCmd1もCmd2も入れることができるchannelになるが、このchannelにはintもfloat32も他のstructも何でも入ってしまう。
&lt;p/&gt;
コンパイル時にCmd1とCmd2以外を入れていないことをチェックするには、以下のようにすれば良い。&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;type Cmd interface {
    isCmd() bool
}

type CmdBase struct {
}

func (c CmdBase) isCmd() bool {
    return true
}

type Cmd1 struct {
    CmdBase
    id int
}

type Cmd2 struct {
    CmdBase
    msg string
}&lt;/code&gt;&lt;/pre&gt;
これで、&lt;code&gt;var ch chan Cmd&lt;/code&gt;とchannelを作れば、Cmd1とCmd2以外を間違ってchannelに入れてしまう可能性をかなり減らせる。


</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/224888056009940082/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/224888056009940082' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/224888056009940082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/224888056009940082'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/10/gochannel.html' title='Goでchannelに入れることができる型を限定する'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-6344647075506295942</id><published>2012-09-25T09:51:00.001+09:00</published><updated>2012-09-25T09:52:45.422+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><title type='text'>AndroidのUIテストフレームワーク</title><content type='html'>AndroidのUIテストのフレームワークを調べていたのが、現在はほぼ&lt;a href=&quot;https://code.google.com/p/robotium/&quot;&gt;Robotium&lt;/a&gt;一択状態だった。

&lt;br /&gt;
&lt;h2&gt;
Native Driver&lt;/h2&gt;
Google製のツールで有望視されていたようだが、&lt;a href=&quot;https://groups.google.com/forum/?fromgroups=#!topic/nativedriver-devs/WC0GopaDMIo&quot;&gt;開発が止まった&lt;/a&gt;。

&lt;br /&gt;
&lt;h2&gt;
Scirocco&lt;/h2&gt;
開発が止まっているように見える。&lt;a href=&quot;https://code.google.com/p/scirocco/source/list&quot;&gt;最終commitは2011/12/13&lt;/a&gt;。
新バージョンのSciroccoはNative Driverベースらしいが、そのNative Driver自体開発が止まっている。

&lt;br /&gt;
&lt;h2&gt;
monkeyrunner&lt;/h2&gt;
絶対座標でクリック位置を指定するので、使いにくい。
別途&lt;a href=&quot;http://dtmilano.blogspot.ca/2012/05/androidviewclient-q.html&quot;&gt;AndroidViewClient&lt;/a&gt;のような物を使う必要がある。

&lt;br /&gt;
&lt;h2&gt;
Calabash&lt;/h2&gt;
ちょっと特殊すぎるので、パス。</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/6344647075506295942/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/6344647075506295942' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6344647075506295942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6344647075506295942'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/09/androidui.html' title='AndroidのUIテストフレームワーク'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-6947451478793833260</id><published>2012-09-12T09:35:00.000+09:00</published><updated>2012-09-12T09:35:51.561+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Dropbox"/><category scheme="http://www.blogger.com/atom/ns#" term="encfs"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><title type='text'>Dropboxと暗号化ファイルシステムを組み合わせる</title><content type='html'>Dropboxは便利なのだが、やはり人に見られたくないファイルを置くのが少しためらわれる。
そこで、気休めかもしれないが、暗号化ファイルシステムである&lt;a href=&quot;http://www.arg0.net/encfs&quot;&gt;encfs&lt;/a&gt;と組み合わせて使うことにした。
&lt;p/&gt;
Dropboxが同期するディレクトリを~/Dropbox、暗号化したファイルを置くディレクトリを~/Dropbox/enc、アプリから直接読み書きするディレクトリを~/dropとする。
&lt;p/&gt;
マウント方法&lt;pre&gt;&lt;code&gt;$ mkdir ~/Dropbox/enc (暗号化したファイルを置くディレクトリを作成)
$ mkdir ~/drop (マウントポイントを作成)
$ encfs ~/Dropbox/enc ~/drop
&lt;/code&gt;&lt;/pre&gt;
これでOK。Dropboxが~/Dropboxを勝手に同期してくれるので、アプリからは~/dropにあるファイルにアクセスすればよい。
&lt;p&gt;
アンマウントは以下。&lt;pre&gt;&lt;code&gt;$ fusermount -u ~/drop
&lt;/code&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/6947451478793833260/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/6947451478793833260' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6947451478793833260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/6947451478793833260'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/09/dropbox.html' title='Dropboxと暗号化ファイルシステムを組み合わせる'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-8477789955985505458</id><published>2012-08-23T10:08:00.000+09:00</published><updated>2012-08-23T10:08:03.376+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><title type='text'>Goのgoroutineのスケジューリング</title><content type='html'>Go言語のgoroutineのスケジューリングに関して調べた。&lt;br /&gt;
スケジューラーのソースコードは、src/pkg/runtime/proc.c&lt;br /&gt;
&lt;br /&gt;
スケジューラーのルールは以下のとおり(GOMAXPROC=1の場合)&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;goruntineは、non preemptiveマルチタスクのように動作する。ある時点で動作しているgoruntineは1つのみ。&lt;/li&gt;
&lt;li&gt;別のgoroutineが動き出すのは、今動作しているgoroutineが明示的に待ちに入るときのみ。channelのread/write、systemcallの呼び出しなど。&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
goroutineを実行するthreadは、上記のルールに合うように、必要に応じて作成される。あるgoroutineをどのthreadが実行しているか、は、考える必要がない(考えてもあまり意味がない)。&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;goroutineはtimesliceで切り替わりはしない&lt;/h2&gt;
2つのgoroutineがrunning状態だとする。一方が&lt;br /&gt;
&lt;div&gt;
for {&lt;/div&gt;
&lt;div&gt;
}&lt;br /&gt;
のようにbusy loopしていると、もう一方のgoroutineは全く動かないので、プログラムの動作はそこで止まってしまう。&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;goroutineを実行するthreadは切り替わる&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
goroutineがwait状態から解除されたとする。解除前と解除後では、そのgoroutineを実行しているthreadが違うものの可能性がある。(goのプログラムを書く上では、あまり気にしなくて良いが)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;threadは、goroutineを走らせるのに必要な場合だけ作成される&lt;/h2&gt;
threadは、goroutineを走らせるのに必要な場合だけ作成される。&lt;br /&gt;
&lt;br /&gt;
あるgoroutineがsystem callでブロックする場合、そのgoroutineを実行しているthreadもブロックしてしまう。runningなgoroutineが存在するのに、それを実行できる(ブロックしていない)threadが存在しない場合にのみ、threadは作成される。&lt;br /&gt;
&lt;br /&gt;
goroutineがchannelのread/writeでブロックする場合、そのgoroutineを実行中だったthreadは、goroutineのステートをブロック状態にし、別のrunnableなgoroutineの実行を開始する。この場合には、新たなthreadを作る必要は無いので、threadは作成されない。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/8477789955985505458/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/8477789955985505458' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/8477789955985505458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/8477789955985505458'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/08/gogoroutine.html' title='Goのgoroutineのスケジューリング'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-3023360651012271152</id><published>2012-07-25T23:55:00.000+09:00</published><updated>2012-07-25T23:55:25.607+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><title type='text'>複数のAndroid端末使用時に、ANDROID_SERIALを切り替える</title><content type='html'>複数のAndroid端末をPCに接続している場合、環境変数ANDROID_SERIALを切り替えるのが結構めんどくさい。&lt;br /&gt;
そこで、ANDROID_SERIALを簡単に切り替える事ができるプログラムを作成した。&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/anolivetree/adbdevices&quot;&gt;https://github.com/anolivetree/adbdevices&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Go言語で作成しているので、コンパイルにはGoが必要。&lt;br /&gt;
&lt;br /&gt;
後は&lt;br /&gt;
&lt;code&gt;alias ad=&#39;export ANDROID_SERIAL=`adbdevices`&#39;&lt;/code&gt;
&lt;br /&gt;
と.bashrcにでも書いておけばよい。</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/3023360651012271152/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/3023360651012271152' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3023360651012271152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/3023360651012271152'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/07/androidandroidserial.html' title='複数のAndroid端末使用時に、ANDROID_SERIALを切り替える'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-7630004387007610598</id><published>2012-06-06T14:17:00.000+09:00</published><updated>2012-06-06T14:17:43.944+09:00</updated><title type='text'>将来のAndroidの開発環境はDartベースになると予想</title><content type='html'>&lt;br /&gt;
#別SNSにも書いたが、こちらにも。&lt;br /&gt;
&lt;br /&gt;
Androidの現在の開発環境はJavaだが、近い将来Dartに移行するのではないかと予想している。理由は以下の通り。&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;webアプリとローカルアプリをシームレスに開発できる。&lt;/li&gt;
&lt;li&gt;パフォーマンスアップ。DartVMはV8並に速くなると予想される。&lt;/li&gt;
&lt;li&gt;Oracleとの訴訟問題。&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
■1.&amp;nbsp;webアプリとネイティブアプリをシームレスに開発できる。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
この点がDartベースにする一番のメリット。&lt;/div&gt;
&lt;div&gt;
IntentやActivity、XMLでのUIデザインなど、webアプリにはないローカルアプリの概念をどう統一していくかという問題はあるが、まずは言語を統一することで、どちらもシームレスに開発できるようになる第一歩となるだろう。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
■2. パフォーマンスアップ&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
V8はネイティブコード並に速く動作すると言われている一方、DalvikVMは実行速度が遅いと言われている。DartVMはV8並に速くなると予想され、そのVMを使うことで、Androidアプリの実装速度が改善される。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
■3.&amp;nbsp;Oracleとの訴訟問題&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
JavaのAPIをめぐる訴訟の一審ではGoogleが勝利した。が、それは将来にわたってGoogleがJavaを使い続けることができるというわけではない。Oracleが今後Javaやそれにまつわるツール等のライセンスを変えてきて、Javaの最新機能がAndroidでは使えない、という可能性も考えられる。&lt;/div&gt;
&lt;div&gt;
自社開発の言語を採用することで、そのリスクを無くすことができる。&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/7630004387007610598/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/7630004387007610598' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/7630004387007610598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/7630004387007610598'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/06/androiddart.html' title='将来のAndroidの開発環境はDartベースになると予想'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-9131117760082770477</id><published>2012-03-11T20:08:00.000+09:00</published><updated>2012-03-11T20:09:03.205+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="english"/><title type='text'>TOEIC S/Wテストで+20点を取るコツ</title><content type='html'>&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;TOEICのスピーキング/ライティングテストを受けてきた。覚えておけば簡単に+20点くらい取れるコツをまとめておく。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;■最初のマイクテストで話す内容&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;テストが始まる前にマイクのテストを行う。その際、「あなたの街に関して話してください」と質問される。ここでいきなり、何を話せば良いのだろう？とパニックになる必要は無い。何を話しても採点には影響しないので、モニターに表示されているテストの説明文を読めばよい。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;■意見を求められる設問は、自分の意見を言う(書く)必要は無い&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;スピーキング、ライティングともに、自分の意見を求められる設問がある。が、ここで正直に自分の意見を英語で表現しようとする必要はない。自分の英語能力で表現しやすい意見を述べれば良いのだ。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: sans-serif;&quot;&gt;&lt;span style=&quot;font-size: 15px; line-height: 22px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;■キーボードの配列に慣れておく&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: sans-serif;&quot;&gt;&lt;span style=&quot;font-size: 15px; line-height: 22px;&quot;&gt;試験で使用するキーボード自体は日本語キーボードだが、配列が英語配列に設定されている。&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;たとえば、アポストロフィを入力したい場合には、Lの2つ右となりの「:」キーを押す必要がある。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: sans-serif; font-size: 15px; line-height: 22px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: sans-serif;&quot;&gt;&lt;span style=&quot;font-size: 15px; line-height: 22px;&quot;&gt;試験で記号を入力する必要は多くはないが、アポストロフィの入力方法くらいは覚えておいたほうが、落ち着いてテストに臨めるだろう。&lt;/span&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/9131117760082770477/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/9131117760082770477' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/9131117760082770477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/9131117760082770477'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/03/toeic-sw20.html' title='TOEIC S/Wテストで+20点を取るコツ'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-2457269980218894656</id><published>2012-02-29T22:36:00.000+09:00</published><updated>2012-02-29T22:37:56.736+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>Androidアプリのデバッグオプションの意味</title><content type='html'>&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;Androidの各種デバッグオプションの意味が&lt;a href=&quot;http://groups.google.com/group/android-developers/browse_thread/thread/be329298953aa8bd/afc790073195ecc1&quot;&gt;ML&lt;/a&gt;で説明されていたので、簡単にまとめる。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;■debuggable=trueの意味&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;アプリケーションにデバッガをAttachできるかどうか。作成されるapkに違いは無い。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;ただし、エミュレーターで動作している場合は特別で、debuggable=trueではないアプリでもAttachが可能。&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: fixed-width, monospace;&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: fixed-width, monospace;&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;■Eclipseの&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;Run/Debug session&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: fixed-width, monospace; font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: fixed-width, monospace;&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;Debug sessionの場合は、アプリ実行時にデバッガを自動でAttachする。Run sessionの場合はしない。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: fixed-width, monospace;&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: fixed-width, monospace;&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;■Eclipse(ADT)のAndroid toolsでのexport&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: fixed-width, monospace;&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: fixed-width, monospace;&quot;&gt;&lt;span style=&quot;font-size: 12px;&quot;&gt;apkの署名が違う。zipalignが行われるので、多少実行速度は速いはず。&lt;/span&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/2457269980218894656/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/2457269980218894656' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/2457269980218894656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/2457269980218894656'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/02/android.html' title='Androidアプリのデバッグオプションの意味'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28877138.post-5131641484843471017</id><published>2012-02-21T23:05:00.003+09:00</published><updated>2012-02-21T23:14:06.953+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="catch.com"/><category scheme="http://www.blogger.com/atom/ns#" term="golang"/><title type='text'>Catch.comにコマンドラインからノートを追加する</title><content type='html'>私はオンラインノートとして、Evernoteより軽くタグ付けが用意なCatch.comを使用している。&lt;br /&gt;このCatch.comにコマンドラインからテキストノートを追加するプログラムを作成した。&lt;br /&gt;&lt;a href=&quot;https://bitbucket.org/anolivetree/catch-golang&quot;&gt;catch-golang&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Go言語のプログラムなので、コンパイルにはGoが必要。&lt;br /&gt;&lt;br /&gt;事前に、~/.catchpassにユーザー名とパスワードを書いておく。&lt;code&gt;&lt;pre&gt;&lt;br /&gt;$ cat ~/.catchpass&lt;br /&gt;myuser&lt;br /&gt;mypass&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;あとは、&lt;code&gt;&lt;pre&gt;&lt;br /&gt;$ catch&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;と実行すると、テキストエディタが起動する。テキストを保存してエディタを終了すると、テキストの内容が自動でCatch.comにアップロードされる。</content><link rel='replies' type='application/atom+xml' href='http://assam-at-night.blogspot.com/feeds/5131641484843471017/comments/default' title='コメントの投稿'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/28877138/5131641484843471017' title='0 件のコメント'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5131641484843471017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28877138/posts/default/5131641484843471017'/><link rel='alternate' type='text/html' href='http://assam-at-night.blogspot.com/2012/02/catchcom.html' title='Catch.comにコマンドラインからノートを追加する'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/10140029564122291869</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>