tag:blogger.com,1999:blog-39603628254139618382024-02-07T15:24:46.024+09:00DevAchieveプログラミングで世界を開拓して未来を実現するブログwada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comBlogger402125tag:blogger.com,1999:blog-3960362825413961838.post-71319165669162411092015-01-26T08:21:00.001+09:002015-01-26T08:24:58.974+09:00[Android] Support Library に追加された testing-support-lib や Espresso 2.0 で JUnit4 な Android のテストを書くAndroid Support Library に UI テストを行う Espresso 2.0 や<br />
JUnit4 でテストを行うための testing-support-lib が追加されました。<br />
<br />
<h3>前置き</h3><h4>概要とドキュメントなど</h4><p><a href="https://plus.google.com/+AndroidDevelopers/posts/jHXFkebKjEb">Espresso 2.0 is here!</a></p><blockquote><ul><li>Release Notes - <a href="http://goo.gl/oJBysE">http://goo.gl/oJBysE</a></li>
<li>AndoidJUnitRunner Javadoc - <a href="http://goo.gl/Tct8R5">http://goo.gl/Tct8R5</a></li>
<li>AndroidJUnitRunner Docs - <a href="http://goo.gl/pSr8oB">http://goo.gl/pSr8oB</a></li>
<li>Android-Testing Github Samples - <a href="http://goo.gl/zNHuS9">http://goo.gl/zNHuS9</a></li>
<li>Espresso Setup Guide - <a href="http://goo.gl/WR9t36">http://goo.gl/WR9t36</a></li>
<li>Espresso Documentation - <a href="http://goo.gl/jSI0xl">http://goo.gl/jSI0xl</a></li>
<li>Espresso-Core Javadoc - <a href="http://goo.gl/OyaHKn">http://goo.gl/OyaHKn</a></li>
<li>Espresso-Contrib Javadoc - <a href="http://goo.gl/gZgISI">http://goo.gl/gZgISI</a></li>
<li>Espresso-Idling Javadoc - <a href="http://goo.gl/ZwVyn7%EF%BB%BF">http://goo.gl/ZwVyn7</a></li>
</ul></blockquote><p><a href="https://code.google.com/p/android-test-kit/">android-test-kit - Google's Testing Tools For Android - Google Project Hosting</a></p><br />
<h4>サンプルコード</h4><p><a href="https://github.com/googlesamples/android-testing">googlesamples/android-testing</a></p><br />
<h4>関連エントリ</h4><p><a href="http://vividcode.hatenablog.com/entry/android-app/library/espresso-2.0">Espresso 2.0 が Android support library の一部としてリリースされた - ひだまりソケットは壊れない</a><br />
<a href="http://kirimin.hatenablog.com/entry/2014/12/22/214415">Espressoがsupport libraryになってAndroidでJUnit4が使えるようになったと聞いたので試してみた - みんからきりまで</a><br />
<a href="http://qiita.com/AbeHaruhiko/items/91aa8fe0f2299969d0e7">続・AndroidでJUnit4を使う方法(Android SDKで正式サポートされました!) - Qiita</a><br />
<a href="http://sys1yagi.hatenablog.com/entry/2014/12/22/135455">support packageに追加されたtesting-support-libを使ってAndroidのテストをJUnit4で書く - visible true</a></p><br />
<h3>JUnit4 で Activity のテストを書いてみる</h3><pre class="brush: diff; first-line: 1; highlight: [,];" title="app/build.gradle">@@ -10,6 +10,8 @@ android {
targetSdkVersion 21
versionCode 1
versionName "1.0"
+ // testing
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
@@ -17,9 +19,16 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ packagingOptions {
+ exclude 'LICENSE.txt'
+ }
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
+ // testing
+ compile 'com.android.support:support-annotations:21.0.3'
+ androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
+ androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
}
</pre><pre class="brush: java; first-line: 1; highlight: [,];" title="app/src/androidTest/java/com/wada811/android/junit4/MainActivityTest.java">package com.wada811.android.junit4;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.ActivityInstrumentationTestCase2;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;
@RunWith(AndroidJUnit4.class)
public class MainActivityTest extends ActivityInstrumentationTestCase2<mainactivity> {
private MainActivity activity;
public MainActivityTest(){
super(MainActivity.class);
}
@Before
public void setUp() throws Exception{
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
activity = getActivity();
}
@After
public void tearDown() throws Exception{
super.tearDown();
}
@Test
public void checkPrecondition(){
assertThat(activity, notNullValue());
assertThat(getInstrumentation(), notNullValue());
}
}</pre><br />
<h4>参考</h4><a href="https://code.google.com/p/android-test-kit/wiki/EspressoSetupInstructions">Getting Started - EspressoSetupInstructions - android-test-kit</a><br />
<a href="https://code.google.com/p/android-test-kit/wiki/AndroidJUnitRunnerUserGuide#Backwards_compatibility_to_Android_platform_testing_APIs">AndroidJUnitRunnerUserGuide - android-test-kit</a><br />
<br />
<h3>テストを実行する</h3><h4><code>./gradlew connectedAndroidTest</code> コマンドを実行</h4>端末もしくはエミュレータでテストを実行することができます。<br />
しかし、何故か MainActivityTest.java は実行されませんでした。<br />
JUnit3 なテストは実行されていますが、 JUnit4 な テストは実行されないみたいです。<br />
<br />
<h4>プロジェクトエクスプローラで右クリックから Run...</h4>ファイルを指定して実行すれば JUnit4 なテストも実行できます。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoxnWpcHfImOc9TBSPEdNl3JQNEuOPVoKzK0iaoq-VfUsvxQO_KSfgd2xi9KMdoSeBJT0XotSKlgciLW46mGifgt_bifrdLAL6CxTCgZUlj-NduabOB3Y9PSsew5GgSpw8soOZb5-TrY4/s1600/MainActivityTest.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoxnWpcHfImOc9TBSPEdNl3JQNEuOPVoKzK0iaoq-VfUsvxQO_KSfgd2xi9KMdoSeBJT0XotSKlgciLW46mGifgt_bifrdLAL6CxTCgZUlj-NduabOB3Y9PSsew5GgSpw8soOZb5-TrY4/s640/MainActivityTest.png" /></a><br />
<br />
<h4>Edit Configurations... から Android Test を追加してクラスを指定して実行</h4>クラス(ファイル)を指定して実行すれば JUnit4 なテストも実行できます。<br />
All in Module や All in Package では JUnit4 なテストは実行されませんでした。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOVwo0ih2jE222hVj_fc9xcIdEicjeZnew7oxqOXfmmYR6D7hOuvvOkKV90z8KUgpk9tYIq9mtxIfKAUA7FC2JENA6GA1rCoNNX4uCcESX1gafMHNIAIdPEsaAEvbh3futf9W2mfM0geQ/s1600/RunConfigurations.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOVwo0ih2jE222hVj_fc9xcIdEicjeZnew7oxqOXfmmYR6D7hOuvvOkKV90z8KUgpk9tYIq9mtxIfKAUA7FC2JENA6GA1rCoNNX4uCcESX1gafMHNIAIdPEsaAEvbh3futf9W2mfM0geQ/s640/RunConfigurations.png" /></a><br />
<br />
<h3>クラスを指定しなくても JUnit4 なテストを実行したい</h3>これは偶然なのか考えられているのかわからないけど Jake 神の ActivityRule を使うと<br />
直接クラスを指定しなくてもテストを実行できるようになります。<br />
<pre class="brush: java; first-line: 1; highlight: [4,16,17];" title="com.wada811.android.junit4.MainActivityTestWithRule.java">package com.wada811.android.junit4;
import android.support.test.runner.AndroidJUnit4;
import com.jakewharton.test.ActivityRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.Espresso.*;
import static android.support.test.espresso.assertion.ViewAssertions.*;
import static android.support.test.espresso.matcher.ViewMatchers.*;
import static org.hamcrest.Matchers.*;
@RunWith(AndroidJUnit4.class)
public class MainActivityTestWithRule {
@Rule
public final ActivityRule<mainactivity> activityRule = new ActivityRule<>(MainActivity.class);
@Test
public void checkPrecondition(){
// MatcherAssert.assertThat(activityRule.instrumentation(), Matchers.notNullValue());
assertThat(activityRule.instrumentation(), notNullValue());
}
@Test
public void showHelloWorld(){
// Espresso.onView(ViewMatchers.withId(R.id.textView)).check(ViewAssertions.matches(ViewMatchers.withText(R.string.hello_world)));
onView(withId(R.id.textView)).check(matches(withText(R.string.hello_world)));
}
}</pre>Espresso 2.0 でテストを書いてみました。<br />
クラス名を覚えるのは辛い感じなので static import でメソッド書くだけにしたい感じがあります。<br />
<br />
ソースコードは <a href="https://github.com/wada811/Android-JUnit4" target="_blank">wada811/Android-JUnit4</a> にあります。<br />
Activity だけじゃなく他のテストについても増やしていきたいです。<br />
<br />
<h4>参考</h4><a href="https://gist.github.com/JakeWharton/1c2f2cadab2ddd97f9fb" target="_blank">A JUnit @Rule which launches an activity when your test starts. Stop extending gross ActivityInstrumentationBarfCase2!</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-77476363543430342042015-01-08T15:42:00.000+09:002015-01-08T15:42:00.483+09:002014年の反省と2015年の目標<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYel0tEnsp6NJQcikbNoGn6Qy3ZwkN-8GcWb_GHfHp8144iXgdWbU9mv6j81XaykuRPgu0buiNeHa-_Ha9r4QGUqVjBapbDs1Gq6qCBlcBC16Nll3BdLycHqXOCAkTHZZKz1VXvsdezxI/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2015-01-04+10.46.20.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYel0tEnsp6NJQcikbNoGn6Qy3ZwkN-8GcWb_GHfHp8144iXgdWbU9mv6j81XaykuRPgu0buiNeHa-_Ha9r4QGUqVjBapbDs1Gq6qCBlcBC16Nll3BdLycHqXOCAkTHZZKz1VXvsdezxI/s640/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2015-01-04+10.46.20.png" /></a>あけましておめでとうございます。<br />
<a href="http://wada811.blogspot.com/2012/01/devachieve.html" target="_blank">2012/01/08</a>に始まったこのブログも<br />
3周年を迎えました。<br />
2013年は117記事でしたが、<br />
2014年は72記事となって減少傾向です。<br />
細かい Tips などは <a href="http://qiita.com/search?q=+user%3Awada811+&sort=created&utf8=%E2%9C%93" target="_blank">Qiita</a> に<br />
書くようになったので<br />
<a href="http://qiita.com/wada811" target="_blank">wada811(Qiita)</a> もよろしくお願いします。<br />
昔からの人も最近からの人も<br />
2014年、お世話になりました!<br />
2014年のエンジニア人生を振り返って<br />
2015年の目標を立ててみようと思います。<br />
<h3>2014年</h3><h4>結婚した</h4>撮った写真を披露宴会場のスクリーンに表示するシステムが3万円くらい、と<br />
結婚式の2週間前に TV でやっているのを見て<br />
こんなのすぐできる!1人日程度だろ?と思って写真アップロードシステム作ったのは良い思い出でした。<br />
実際は細切れにしか作業できなかったので総日数としては3日くらいかかりましたが。<br />
借りてたさくらのVPSにPHPをインストールしてなかったとか<br />
ドメインを取ってなかったので契約からスタートとか色々ありましたが、<br />
開発だけなら1人日程度でできたと思います。<br />
<a href="https://github.com/wada811/wedding.wada811.com" target="_blank">wada811/wedding.wada811.com</a><br />
とにかく時間がなくて画面も3枚だけだったので手っ取り早く素の PHP で作りました。<br />
脆弱性とかはないと信じたい。。。<br />
開発で一番時間がかかったのは PDO の薄いラッパーを探すことで、<br />
プリペアドステートメントでクエリ発行できるやつが見つからなかったので仕方ないから自分で作りました。<br />
あとは、CSS3 の transform をアニメーションの調整くらい。<br />
<h5>関連記事</h5><a href="http://wada811.blogspot.com/2014/11/sakura-vps-domain-settings.html" target="_blank">さくらのVPSにスタードメインで取得した独自ドメインを設定してみた</a><br />
<a href="http://wada811.blogspot.com/2014/11/jquery0transform-js-css3-transform.html" target="_blank">jquery.transform.js で CSS3 の transform をアニメーションさせる</a><br />
<a href="http://wada811.blogspot.com/2014/11/image-upload--preview.html" target="_blank">exif-js と ios-imagefile-megapixel でスマホからの画像アップロードのプレビュー表示に対応する</a><br />
<br />
<h4>Androider としての技術力を更に高める</h4>どちらかというとライブラリ作ってた感じ。<br />
<a href="https://github.com/wada811/Android-DialogFragments" target="_blank">wada811/Android-DialogFragments</a><br />
<a href="https://github.com/wada811/Android-Material-Design-Colors" target="_blank">wada811/Android-Material-Design-Colors</a><br />
カメラのライブラリも作ってほぼほぼできていたけど放置していて完成したのかどうかも忘れている現状…。<br />
カメラのライブラリは設計がいいのかどうかもわからなくて、<br />
他の人がカメラアプリ作るときどんな感じに作っているのか知りたい。<br />
<a href="https://android-arsenal.com/details/1/1209" target="_blank">The Android Arsenal - LandscapeVideoCamera</a>とか、<br />
そこの See Also とか見ればわかるかな。<br />
<br />
<h4>新しい言語を学ぶ</h4>Ruby on Rails 始めました。<br />
<a href="http://qiita.com/search?q=+user%3Awada811+&sort=created&utf8=%E2%9C%93" target="_blank">Qiita</a>で Ruby とか Rails の知見を共有しています。<br />
View は Slim で書いていて、もう PHP で、HTML で、というのには戻れない感じです。<br />
そういう感じなのでブログも生の HTML を書くのが面倒になってきて Markdown で書きたいなぁという感じです。<br />
<br />
<h4>OpenGL を学ぶ</h4>やりませんでした。たぶん来年もやりませんね。<br />
<br />
<h4>UnitTest / CI を学ぶ</h4>Rails で Rspec を使ってテスト書いたり、 Guard でファイル変更を監視して自動的に Rspec を実行とかやった。<br />
Rails はとにかくすぐ壊れる印象なのでテストがないとリファクタリングできないという感覚になっている。<br />
テストを書く習慣が定着してるのはそういうことか〜という感じです。<br />
<br />
<h4>個人でのプロダクトを出す</h4>ライブラリをプロダクトと呼ぶかは微妙だけど、それ以外で言うと何もないなぁという感じです。<br />
ひたすら GitHub Star を集めたり Qiita Stock を集めたりしてモチベーションを保っていた。<br />
<br />
<h4>収入を増やす</h4>一応増えたけどコスパ良くない。税金が重い。社会は厳しいという感じ。<br />
<br />
<h3>2015年</h3><h4>もっと Android</h4>あんまり Android で DB を使ったアプリを作ってないので作りたい。<br />
RxJava, RxAndroid, Lombok あたりを使ってモダンな感じで作りたい。<br />
Material Design に対応したい。<br />
この3本で頑張っていこうと思います。<br />
<br />
<h4>もっと Ruby on Rails</h4>まだ1ヶ月やっただけなので、もっと経験を積みたいです。<br />
アプリのバックエンドで使ってみる。<br />
<br />
<h4>もっと UnitTest / CI</h4>コミットしたらテスト実行されて…という環境を作る。<br />
<br />
<h4>個人でのプロダクトを出す</h4>新しいものを考えてはある。あとは作るだけ。<br />
<br />
<h4>収入を増やす</h4>コスパあげたい。<br />
<br />
<h4>ブログを移行する</h4>GitHub Pages に移行して Markdown で記事書きたい。<br />
でも GitHub Pages をやめちゃった人がいて、面倒なのかとか気になっているところ。<br />
ブログのカスタマイズにはあまり時間を掛けたくないので悩んでいる。<br />
<br />
<h3>2015年もよろしくお願いします!</h3>さらなる飛躍の年にするべく頑張ります!wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-67864767949952129072014-12-30T21:16:00.000+09:002014-12-30T21:16:14.964+09:00[Android]テキストをクリップボードにコピーする<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s1600/android.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s320/android.png" /></a><a href="https://github.com/wada811/Android-Material-Design-Colors" target="_blank">wada811/Android-Material-Design-Colors</a> の<a href="https://play.google.com/store/apps/details?id=at.wada811.android.material.design.colors.sample" target="_blank">サンプルアプリ</a>を作ったら<br />
カラーコードをコピーしたいという要望があったので実装しました。<br />
<br />
Honeycomb 未満と以上で方法が変わっていました。<br />
クラス名は同じでパッケージが異なるだけだったので長ったらしくてちょっとアレです。<br />
<br />
<pre class="brush: java; first-line: 1; highlight: [,];" title="">@SuppressWarnings("deprecation")
public void copyText(Context context, String text){
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB){
android.text.ClipboardManager clipboard = (android.text.ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}else{
android.content.ClipboardManager clipboard = (android.content.ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Copied Text", text);
clipboard.setPrimaryClip(clip);
}
}</pre>
<a href="http://stackoverflow.com/questions/6624763/android-copy-to-clipboard-selected-text-from-a-textview" target="_blank">Android: Copy to clipboard selected text from a TextView - Stack Overflow</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-65786256311001468732014-12-30T20:54:00.002+09:002014-12-30T20:54:33.168+09:00[Android]タブレット対応 〜 Master / Detail パターンを実装する<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s1600/android.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s200/android.png" /></a>みなさん、タブレット対応してますか?<br />
僕はまだあんまりなので<br />
とりあえず一番有名な Master / Detail パターンを実装してみることにしました。<br />
Android Studio の Wizard に Master Detail パターンがあるので<br />
コイツを見ておきたいと思います。<br />
<br />
ということで Android Studio の Wizard で Master Detail パターンを生成してみると<br />
結構わかりにくいことをしていて、<br />
values-sw600dp/refs.xml で @layout/activity_item_list を参照すると<br />
タブレットでは @layout/activity_item_twopane を参照されるように設定しています。<br />
<pre class="brush: xml; first-line: 1; highlight: [,];" title="values-sw600dp/refs.xml"><item type="layout" name="activity_item_list">@layout/activity_item_twopane</item></pre>しかも、スマートフォンとタブレットの判別の仕方が微妙で<br />
ItemListActivity.java で setContentView(R.layout.activity_item_list) すると<br />
タブレットでは R.layout.activity_item_twopane が読み込まれて<br />
そのレイアウトの中に R.id.item_detail_container な View があるかで<br />
スマートフォンとタブレットのレイアウトを振り分けています。<br />
<pre class="brush: java; first-line: 1; highlight: [,];" title="ItemListActivity.java">setContentView(R.layout.activity_item_list);
if(findViewById(R.id.item_detail_container) != null){
mTwoPane = true;
}</pre><br />
タブレットかどうかの判定と View の実装は分離しておきたいので<br />
タブレットかどうかのフラグをリソースに定義することにします。<br />
<a href="http://yuki312.blogspot.jp/2012/03/androidor.html" target="_blank">Yukiの枝折: Android:タブレットorスマートフォンのフラグをリソースに定義する</a><br />
<pre class="brush: xml; first-line: 1; highlight: [,];" title="res/values/bool.xml"><resources>
<bool name="isTablet">false</bool>
</resources></pre><pre class="brush: xml; first-line: 1; highlight: [,];" title="res/values-sw600dp/bool.xml"><resources>
<bool name="isTablet">true</bool>
</resources></pre><br />
ItemListActivity.java ではこのフラグを参照して処理をわけます。<br />
レイアウトもこのフラグで振り分けます。<br />
<br />
<pre class="brush: java; first-line: 1; highlight: [,];" title="ItemListActivity.java">public class ItemListActivity extends ActionBarActivity implements ItemListFragment.Callbacks{
private boolean isTablet;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
isTablet = getResources().getBoolean(R.bool.isTablet);
setContentView(isTablet ? R.layout.activity_item_twopane : R.layout.activity_item_list);
if(isTablet){
getSupportActionBar().setDisplayShowHomeEnabled(false);
getSupportActionBar().setDisplayUseLogoEnabled(false);
ItemListFragment itemListFragment = (ItemListFragment)getSupportFragmentManager().findFragmentById(R.id.item_list);
itemListFragment.setActivateOnItemClick(true);
onItemSelected(0);
}
}
@Override
public void onItemSelected(int position){
if(isTablet){
Bundle arguments = new Bundle();
arguments.putInt(ItemDetailFragment.ARG_ITEM_ID, position);
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment)
.commit();
}else{
Intent detailIntent = new Intent(this, ItemDetailActivity.class);
detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, position);
startActivity(detailIntent);
}
}
}</pre><a href="https://github.com/wada811/Android-Material-Design-Colors" target="_blank">wada811/Android-Material-Design-Colors</a> の <a href="https://play.google.com/store/apps/details?id=at.wada811.android.material.design.colors.sample" target="_blank">サンプルアプリ</a> は<br />
Android Studio の Wizard の Master Detail パターンを元に<br />
上記の変更を加えたアプリになっているので参考になるかもしれません。<br />
ソースコードはこちら↓<br />
<a href="https://github.com/wada811/Android-Material-Design-Colors/tree/master/sample" target="_blank">Android-Material-Design-Colors/sample at master · wada811/Android-Material-Design-Colors</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-85955736715296014682014-12-30T13:39:00.000+09:002014-12-30T13:40:31.205+09:002014年に @wada811 が読んだ技術書まとめ2014年も終わりに近づいているので<a href="https://twitter.com/wada811">@wada811</a>が読んだ技術書を振り返ってみようかと思います。<br />
2013年はこちら→<a href="http://wada811.blogspot.com/2013/12/technical-books-wada811-read-in-2013.html">2013年に @wada811 が読んだ技術書まとめ | DevAchieve</a>(11冊)<br />
2012年はこちら→<a href="http://wada811.blogspot.com/2012/12/technical-books-wada811-read-in-2012.html">2012年に @wada811 が読んだ技術書まとめ | DevAchieve</a>(約40冊)<br />
<br />
<h3>2014/05/07 <a href="http://wada811.blogspot.com/2014/05/the-non-designers-design-book.html" target="_blank">[書評]ノンデザイナーズ・デザインブック | DevAchieve</a></h3>色々な所で読んでおくべきデザイン本として紹介されている本です。<br />
4つの基本原則も良いけど、個人的にはジョシュア・ツリーの悟りの話が好きです。<br />
<blockquote>一度名前を呼ぶことができれば、<br />
あなたはそれを意識し、それを支配し、それを所有し、<br />
それをコントロールできるようになる。</blockquote>名前大事ですね。<br />
<br />
<h3>1年で書籍1冊の書評を書いた!</h3>全然読んでないけど大丈夫か、という感じだ…。<br />
<a href="http://www.amazon.co.jp/o/ASIN/4774146013/wada811-22/ref=nosim/" target="_blank">Linuxエンジニア養成読本</a>は職場にあったので読んだけど<br />
<a href="http://www.amazon.co.jp/o/ASIN/4774163775/wada811-22/ref=nosim/" target="_blank">【改訂新版】Linuxエンジニア養成読本</a>が出ていた。<br />
他の事に時間使っていて本読んでない…。<br />
<br />
<h4>2014年に @wada811 が積んだ技術書まとめ</h4><h5><a href="http://www.amazon.co.jp/o/ASIN/4797327030/wada811-22/ref=nosim/" target="_blank">増補改訂版Java言語で学ぶデザインパターン入門</a></h5><h5><a href="http://www.amazon.co.jp/o/ASIN/4797331623/wada811-22/ref=nosim/" target="_blank">増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編</a></h5><h5><a href="http://www.amazon.co.jp/o/ASIN/477415377X/wada811-22/ref=nosim/" target="_blank">JUnit実践入門 体系的に学ぶユニットテストの技法</a></h5><h5><a href="http://www.amazon.co.jp/o/ASIN/4798116831/wada811-22/ref=nosim/" target="_blank">レガシーコード改善ガイド</a></h5><h5><a href="http://www.amazon.co.jp/o/ASIN/4798136433/wada811-22/ref=nosim/" target="_blank">Gradle徹底入門 次世代ビルドツールによる自動化基盤の構築</a></h5><br />
重い本ばっかり積んでる…。<br />
手を動かしつつ、ちゃんと本も読んでいきたい。<br />
wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-73703378914092759012014-12-09T09:25:00.000+09:002014-12-09T09:25:48.554+09:00Scala + sbt + Sublime Text で 始める Play2<h3><span id="インストール" class="fragment"></span><a href="#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB"></a>インストール</h3><h4><span id="homebrew-で-scala-sbt-play-をインストール" class="fragment"></span><a href="#homebrew-%E3%81%A7-scala-sbt-play-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB"></a>Homebrew で scala, sbt, play をインストール</h4><pre class="cmd mono">$ brew install scala
$ brew install sbt
$ brew install play
$ scala -version
Scala code runner version 2.11.1 -- Copyright 2002-2013, LAMP/EPFL
$ sbt --version
sbt launcher version 0.13.5
$ play
[info] Loading global plugins from /Users/ssl001/.sbt/0.13/plugins
[info] Loading project definition from /Users/ssl001/Documents/workspace_play/hello-play/project
[info] Set current project to hello-play (in build file:/Users/ssl001/Documents/workspace_play/hello-play/)
_
_ __ | | __ _ _ _
| '_ \| |/ _' | || |
| __/|_|\____|\__ /
|_| |__/
play 2.2.3 built with Scala 2.10.3 (running Java 1.6.0_65), http://www.playframework.com
</pre><br />
<h4><span id="sublime-text-3-で-sublimescalasublime-ensime-をインストール" class="fragment"></span><a href="#sublime-text-3-%E3%81%A7-sublimescalasublime-ensime-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB"></a>Sublime Text 3 で <a href="https://github.com/sublimescala/sublime-ensime">sublimescala/sublime-ensime</a> をインストール</h4><p>Cmd+Shift+P -> Package Control: Install Package<br />
<br />
Ensime</p><h4><span id="ensime-server-ensimeensime-srcをインストール" class="fragment"></span><a href="#ensime-server-ensimeensime-src%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB"></a>ENSIME Server (<a href="https://github.com/ensime/ensime-src">ensime/ensime-src</a>)をインストール</h4><p><a href="https://www.dropbox.com/sh/ryd981hq08swyqr/V9o9rDvxkS/ENSIME%20Releases">Download releases</a></p><pre class="cmd">$ cd ~/Library/Application Support/Sublime Text 3/Packages/Ensime
$ mkdir Server
$ mv ~/Downloads/ensime_2.10.0-0.9.8.9/* Server
</pre><br />
<h4><span id="sbt-に-ensime-プラグインensimeensime-sbt-cmdを追加" class="fragment"></span><a href="#sbt-%E3%81%AB-ensime-%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3ensimeensime-sbt-cmd%E3%82%92%E8%BF%BD%E5%8A%A0"></a>sbt に Ensime プラグイン(<a href="https://github.com/ensime/ensime-sbt-cmd">ensime/ensime-sbt-cmd</a>)を追加</h4><p>~/.sbt/0.13/plugins/plugin.sbt に以下を追加(ファイルがなければ作成)</p><pre class="cmd">addSbtPlugin("org.ensime" % "ensime-sbt-cmd" % "0.1.2")
</pre><br />
<h4><span id="sbtコマンドによるensimeファイルの作成" class="fragment"></span><a href="#sbt%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%82%88%E3%82%8Bensime%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90"></a>sbtコマンドによる.ensimeファイルの作成</h4><pre class="cmd">$ play new hello-play
$ cd hello-play
$ sbt
> ensime generate
</pre><p>以降、Sublime Text で Cmd+Shift+P -> Ensime: startup で補完が効くようになる</p><br />
<h4><span id="sublime-text-3-で-guillaumebortplay2-sublimetext2-をインストール" class="fragment"></span><a href="#sublime-text-3-%E3%81%A7-guillaumebortplay2-sublimetext2-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB"></a>Sublime Text 3 で <a href="https://github.com/guillaumebort/play2-sublimetext2">guillaumebort/play2-sublimetext2</a> をインストール</h4><p>Cmd+Shift+P -> Package Control: Install Package<br />
<br />
Play 2.0</p><br />
<h4><span id="sublime-text-3-で-jarhartsublimesbt-をインストール" class="fragment"></span><a href="#sublime-text-3-%E3%81%A7-jarhartsublimesbt-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB"></a>Sublime Text 3 で <a href="https://github.com/jarhart/SublimeSBT">jarhart/SublimeSBT</a> をインストール</h4><p>Cmd+Shift+P -> Package Control: Install Package<br />
<br />
SublimeSBT</p><br />
<h3><span id="実行" class="fragment"></span><a href="#%E5%AE%9F%E8%A1%8C"></a>実行</h3><p>Cmd+Shift+P -> SBT: Run</p><br />
<h3><span id="参考" class="fragment"></span><a href="#%E5%8F%82%E8%80%83"></a>参考</h3><p><a href="http://qiita.com/f81@github/items/d2bd694babc132f44416">最強!?Ensimeを利用したSublime Text3のScala開発環境(playでもliftでも) - Qiita</a><br />
<a href="http://engineering.panaxiom.co.uk/post/34631917299/sublime-text-2-with-sbt-and-play-2">PANAXIOM — Sublime Text 2 with SBT and Play 2</a></p><br />
<h3>感想</h3>sublime-ensime と SublimeSBT の開発が止まっていてな…<br />
快適とは言い難いので他の IDE を使った方が良いと思うんだ。wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-38798915647275269682014-12-09T08:56:00.001+09:002014-12-09T08:58:35.538+09:00Ruby on Rails 開発環境構築 in Mac OS X Mavericks<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4ujGf9OhKWafKjwWMQ1ULCXLCdojdHA7cGOiX0gm6zK5wtIzQ941dXKw3JLh75p-E7I8CgKAQWQO-mtJOxlCX1qc0X_nkZ9MilFdqIJ8CYKeNB9L_dqmfwAbOYr7-uBPdQ-9L4NbbTrw/s1600/Ruby_on_Rails.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4ujGf9OhKWafKjwWMQ1ULCXLCdojdHA7cGOiX0gm6zK5wtIzQ941dXKw3JLh75p-E7I8CgKAQWQO-mtJOxlCX1qc0X_nkZ9MilFdqIJ8CYKeNB9L_dqmfwAbOYr7-uBPdQ-9L4NbbTrw/s320/Ruby_on_Rails.png" /></a>久しぶりに Ruby on Rails で開発することになり、開発環境を再構築しました。<br />
関連: <a href="http://wada811.blogspot.com/2013/07/construction-of-ruby-on-rails-development-environment.html" target="_blank">Mac OSX10.8でrbenvを使ってRuby1.9とRails4.0をインストールする</a><br />
<br />
HomeBrew を使用するので MacPorts の人は読み替えてください。<br />
また、僕は zsh を使っているので bash の人も読み替えてください。<br />
HomeBrew や zsh をインストールしようという人は以下の事が参考になるかと思います。<br />
<a href="http://wada811.blogspot.com/2014/12/build-development-environment-with-homebrew-and-hmebrew-cask-in-mac.html" target="_blank">Homebrew + Homebrew-caskで Mac の開発環境を構築する | DevAchieve</a><br />
<a href="http://wada811.blogspot.com/2012/09/mac-homebrew-install-zsh.html" target="_blank">MacにHomeBrewとzshを導入してみた | DevAchieve</a><br />
<br />
<h3 id="install-rbenv-and-ruby-build">rbenv と ruby-build のインストール</h3><span class="cmd terminal">brew install rbenv</span><br />
<span class="cmd terminal">brew install ruby-build</span><br />
<pre class="brush: plain; first-line: 1; highlight: [,];" title=""># rbenv の初期化
eval "$(rbenv init -)"</pre><span class="cmd terminal">source .zshrc</span><br />
eval "$(rbenv init -)" で rbenv へのパスを通すのとコマンドの補完や引数の処理、rehash をしています。<br />
echo "$(rbenv init -)" で処理内容を確認できます。<br />
<br />
rehashとは、<br />
rbenv -h で確認すると以下のように書かれています。<br />
<b class="mono">rehash: Rehash rbenv shims (run this after installing binaries)</b><br />
gem とか入れたらやれってことでいいのだと思います。<br />
gem を入れまくると重くなる?のか rehash が重くなることがあるらしいです。<br />
<a href="http://mobileapplication.blog.fc2.com/blog-entry-21.html" target="_blank">猫好きモバイルアプリケーション開発者記録 rbenv init が重い問題に対する対処法</a><br />
gem を(アン)インストールしたら自動で rehash してくれる gem があるのでこれを入れておくと良いかも。<br />
<a href="https://github.com/ryansouza/rbenv-rehash" target="_blank">ryansouza/rbenv-rehash - github</a><br />
<br />
<h3 id="install-readline-and-openssl">依存パッケージのインストール</h3><span class="cmd terminal">brew install readline</span><br />
<span class="cmd terminal">brew link readline</span><br />
<span class="cmd terminal">brew install openssl</span><br />
<span class="cmd terminal">brew link openssl</span><br />
<br />
<h3 id="install-ruby">Ruby をインストールする</h3><span class="cmd terminal">CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-openssl-dir=/usr/local" rbenv install 2.1.5</span><br />
CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-openssl-dir=/usr/local" rbenv install まで<br />
入力して Tab で補完すればバージョンを指定できます。<br />
<br />
<h4>rehash して使用するバージョンを指定する</h4><span class="cmd terminal">rbenv rehash</span><br />
<span class="cmd terminal">rbenv global 2.1.5</span><br />
<br />
<h4>バージョンを確認する</h4><span class="cmd terminal">rbenv version</span><br />
<pre class="brush: plain; first-line: 1; highlight: [,];" title="">2.1.5 (set by /Users/wada/.rbenv/version)</pre><span class="cmd terminal">ruby -v</span><br />
<pre class="brush: plain; first-line: 1; highlight: [,];" title="">ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin13.0]</pre><br />
<h3 id="install-bundler">gem 管理システム bundler のインストール</h3>Ruby のライブラリである gem をパッケージ管理できる <a href="http://bundler.io/" target="_blank">Bundler</a> をインストールします。<br />
<span class="cmd terminal">gem install bundler</span><br />
基本的にシステムにgemをインストールせず、<br />
bundler でプロジェクトごとに gem をインストールするのが環境をクリーンに保てて良いとされています。<br />
Rails も bundler でインストールしたいと思います。<br />
<br />
<h3 id="install-rails">Rails をインストールする</h3><pre class="cmd terminal">% mkdir project
% cd project
% bundle init
Writing new Gemfile to /path/to/project/Gemfile</pre>Rails プロジェクト作成する際に<span class="cmd terminal">bundle init</span>して Gemfile を作成します。<br />
<pre class="brush: ruby; first-line: 1; highlight: [4];" title="/path/to/project/Gemfile"># A sample Gemfile
source "https://rubygems.org"
# gem "rails"
</pre>4行目のコメントアウトを外して以下のコマンドを実行すれば rails をインストールできます。<br />
<span class="cmd terminal">bundle install --path vendor/bundle</span><br />
他の gem を追加するときも上のコマンドでプロジェクト内にインストールします。<br />
<br />
<span class="cmd terminal">bundle exec rails new .</span><br />
bundler でインストールした gem は<br />
プロジェクトのディレクトリで bundle exec を付けてコマンドを実行する必要があります。<br />
<br />
<h5>参考</h5><a href="http://qiita.com/youcune/items/222777415f00d19cccb4" target="_blank">Ruby - システムのgemにrailsをインストールせずrails newする - Qiita</a><br />
<br />
<h3 id="install-nokogiri">libiconv is missing. で gem install nokogiri が失敗する場合</h3>Homebrew で libiconv とその依存パッケージをインストールします。<br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="">### For nokogiri
brew tap homebrew/dupes
brew install libiconv
brew install libxml2
brew install libxslt
brew link --force libxml2
brew link --force libxslt</pre><br />
nokogiri をインストールします。<br />
<span class="cmd terminal">gem install nokogiri -- --use-system-libraries</span><br />
Bundler を使用している場合は以下のコマンドを実行します。<br />
<span class="cmd terminal">bundle config build.nokogiri --use-system-libraries</span><br />
<span class="cmd terminal">bundle install</span><br />
<br />
<h5>参考</h5><a href="http://qiita.com/pugiemonn/items/4b23a709ed194b02be6d" target="_blank">Ruby - bundle install でnokogiriをインストールしろと言われる - Qiita</a><br />
<a href="http://qiita.com/t_732_twit/items/a7956a170b1694f7ffc2" target="_blank">OSX - Mac OS X Mavericksで”gem i nokogiri”失敗の解決方法 - Qiita</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-6275321118090940232014-12-05T09:11:00.002+09:002014-12-05T09:14:08.205+09:00Homebrew + Homebrew-caskで Mac の開発環境を構築する<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXtvzwlW-5CYifE5_S3RYDoWK-JzLh-BCh0f7XEnRCDicO7LVIGIx3g4lkMkKmptK18rfeNKOVZRrVUTAmZZB0IzJf2KQ7hdDoJHFztkjHjBd9wiQWy_Qm6KP1REOUlz5XQ9TNUd2Qoak/s1600/Terminal.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXtvzwlW-5CYifE5_S3RYDoWK-JzLh-BCh0f7XEnRCDicO7LVIGIx3g4lkMkKmptK18rfeNKOVZRrVUTAmZZB0IzJf2KQ7hdDoJHFztkjHjBd9wiQWy_Qm6KP1REOUlz5XQ9TNUd2Qoak/s320/Terminal.png" /></a><a href="http://wada811.blogspot.com/2014/05/brewfile-homebrew-cask.html" target="_blank">Brewfile + Homebrew + Homebrew-caskで Mac の環境構築をする</a>の更新版です。<br />
<br />
パッケージ管理システム「<a href="http://brew.sh/" target="_blank">Homebrew</a>」とその拡張版「<a href="about:blank" target="_blank">Homebrew Cask</a>」を使って<br />
Mac の開発環境を構築します。<br />
Brewfile と brew bundle コマンドはサポートされなくなったので<br />
brew-update コマンドを作成して、brew-update でインストール/アップデートを行うようにします。<br />
<br />
<h3>Homebrew を導入する</h3><h4>Command Line Tools for Xcode をインストールする</h4><h5>Xcode をインストールする</h5>まずは AppStore から Xcode をインストールして下さい。<br />
<h5>Command Line Tools for Xcode をインストールする</h5>[ Xcode > Open Developer Tool > More Developer Tools... ] をクリックすると<br />
Downloads for Apple Developer ページが開くので<br />
Command Line Tools for Xcode をダウンロードしてインストールします。<br />
参考: <a href="http://qiita.com/3yatsu/items/47470091277d46f3fde2" target="_blank">MavericksでCommand Line Tools for Xcodeをインストールする - Qiita</a><br />
<h4>Homebrew をインストールする</h4>Terminal で以下のコマンドを実行します。<br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="">ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"</pre>参考: <a href="http://brew.sh/#install" target="_blank">Homebrew — The missing package manager for OS X</a><br />
<h5>Homebrew が正常にインストールできたか確認する</h5>以下のコマンドを実行してエラーがあれば対処、再度実行します。<br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="">brew doctor</pre><h3>Homebrew-cask を導入する</h3><h4>Homebrew-cask をフォーミュラに追加する</h4>Formula(フォーミュラ)は Homebrew で管理されているパッケージのことです。<br />
Homebrew-cask は Homebrew では管理されていないので自分で追加する必要があります。<br />
以下のコマンドで Homebrew-cask を Formula に追加することができます。<br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="">brew tap caskroom/cask</pre>参考: <a href="http://tukaikta.blog135.fc2.com/blog-entry-204.html" target="_blank">これは便利!Homebrewに追加されたtapコマンドはリポジトリを追加して簡単にフォーミュラを増やせる | Macとかの雑記帳</a><br />
<h4>Homebrew-cask をインストールする</h4>Homebrew-cask を追加したら Homebrew の以下のコマンドでインストールします。<br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="">brew install brew-cask</pre><h4>おまけ: Homebrew-cask の使い方</h4><h5>アプリケーションを検索する</h5><span class="cmd terminal">brew cask search chrome</span><br />
<span class="cmd">google-chrome</span><br />
<h5>アプリケーションをインストールする</h5><span class="cmd terminal">brew cask install google-chrome</span><br />
アプリケーションの実体は <span class="code">/opt/homebrew-cask/Caskroom</span> に入り、<br />
<span class="code">~/Applications</span> にシンボリックリンクが作成されます。<br />
それぞれのパスは以下のコマンドオプションで変更することができます。<br />
<span class="code">--caskroom=/my/path</span>, <span class="code">--appdir=/my/path</span><br />
参考: <a href="http://blog.digital-bot.com/blog/2013/09/08/homebrew-cask/" target="_blank">homebrew-caskが良さそうなので導入してみた - About Digital</a><br />
<h5>アプリケーションをアンインストールする</h5><span class="cmd terminal">brew cask uninstall google-chrome</span><br />
<h5>アプリケーションを更新する</h5><span class="cmd terminal">brew cask update</span><br />
<h5>古いアプリケーションを削除する</h5><span class="cmd terminal">brew cask cleanup</span><br />
<h5>その他の使い方</h5><a href="https://github.com/caskroom/homebrew-cask/blob/master/USAGE.md" target="_blank">homebrew-cask/USAGE.md at master · caskroom/homebrew-cask</a><br />
<br />
<h3>brew-update コマンドを作成して Homebrew パッケージを管理する</h3><h4>Brewfile を作成する</h4>以下のようなファイルを作成します。<br />
Install Packages と Install Applications の欄は自由にインストールしたいものを記述して下さい。<br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="brew-update">#!
# Update Homebrew
brew update
# Upgrade Formulas
brew upgrade
# Install HomebrewCask
brew tap caskroom/cask
brew install brew-cask
####################
# Install Packages #
####################
brew install zsh
########################
# Install Applications #
########################
brew cask install google-chrome
# Remove outdated versions
brew cleanup
brew cask cleanup</pre>参考までに僕の brew-update にリンクをはっておきます。<br />
<a href="https://github.com/wada811/dotfiles/blob/master/bin/brew-update" target="_blank">dotfiles/brew-update at master · wada811/dotfiles</a><br />
<br />
<h4>brew-update でインストール/アップデートする</h4>パスの通った場所に brew-update を置いて、実行します。<br />
<span class="cmd terminal">brew bundle</span><br />
<br />
<h3>さいごに</h3>これで brew-update コマンドで Homebrew パッケージをインストール/アップデートできるようになりました。wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-53790732112476275752014-11-28T12:00:00.000+09:002014-11-28T12:00:01.039+09:00exif-js と ios-imagefile-megapixel でスマホからの画像アップロードのプレビュー表示に対応する<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaKfssvORg1-pT8vnH-HJbDLfdU6DZKY0KaBL6Rcse441z19jZAAUZ951889XAeS4NdLCQGXxEo9oRASWStyeyM2j1GRl9qpwmJNFA1QA78R5kFGWj8ZJcBQB9JeyYPriMZ8IaUV0h13I/s1600/JavaScript.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaKfssvORg1-pT8vnH-HJbDLfdU6DZKY0KaBL6Rcse441z19jZAAUZ951889XAeS4NdLCQGXxEo9oRASWStyeyM2j1GRl9qpwmJNFA1QA78R5kFGWj8ZJcBQB9JeyYPriMZ8IaUV0h13I/s320/JavaScript.png" /></a>画像アップロードするときにプレビュー欲しいよね〜<br />
プレビューするとたまに画像が回転されてるよね〜<br />
スマホだと画像選択するアプリで EXIF 情報を見て回転させて表示しているから<br />
プレビューが横向きとかになってておかしいと思われがちだよね〜<br />
<br />
そんな問題を解決するのが exif-js です。<br />
<br />
<h4>exif-js</h4><a href="https://github.com/jseidelin/exif-js" target="_blank">jseidelin/exif-js</a><br />
<br />
使い方は <a href="https://github.com/jseidelin/exif-js/blob/master/example/index.html">https://github.com/jseidelin/exif-js/blob/master/example/index.html</a> を見てください。<br />
例えば、アップロードされたファイルに対して Orientation を取得する場合は以下のように記述します。<br />
<pre class="brush: js; first-line: 1; highlight: [,];" title="">$('#jsFileInput').on("change",function(){
var file = $(this).prop("files")[0];
EXIF.getData(file, function(){
var orientation = file.exifdata.Orientation;
});
});</pre>EXIF 情報を取得するメソッドが提供されていて、<br />
EXIF.getTag(file, "Orientation") で Orientation を取得できるようだけど<br />
取得できないこともあるみたい?で file.exifdata.Orientation で直接取得してしまっています。<br />
よくわからないので動作確認してもらえればと思います。<br />
<br />
さて Orientation は取れましたが、どうやって画像を回転しましょう。<br />
そんな時は megapix-image.js が便利でした。<br />
<br />
<h4>megapix-image.js</h4><a href="https://github.com/stomita/ios-imagefile-megapixel" target="_blank">stomita/ios-imagefile-megapixel</a><br />
<br />
iOS とか入っていますが気にしなくても大丈夫です。<br />
megapix-image.js は大きな画像を表示する際に便利なライブラリですが、<br />
回転もやってくれるので表示は全部任せてしまいましょう。<br />
スマホからだと数 MB 〜 十数 MB の画像が平気でアップロードされるので<br />
普通にプレビューさせようとするとブラウザごとメモリ不足で落ちることがあるのでが<br />
megapix-image.js を使えば、そういったことが少なくなります。<br />
(※直接は見たことないが、画面が真っ暗になるなどの報告を受けたことがあるので銀の弾丸ではない?)<br />
<br />
さきほどの exif-js と組み合わせて使うには以下のようにします。<br />
<pre class="brush: js; first-line: 1; highlight: [,];" title="">$('#jsFileInput').on("change",function(){
var file = $(this).prop("files")[0];
EXIF.getData(file, function(){
var orientation = file.exifdata.Orientation;
var mpImg = new MegaPixImage(file);
mpImg.render($("#jsPreviewImage")[0], { orientation: orientation });
});
});</pre><br />
<h4>まとめ</h4>これで回転している大きな画像をプレビュー表示することができるようになったと思います。<br />
まれに表示できないこともあるらしいので、もっと良い方法があれば教えて下さい。wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-87966428713832942842014-11-27T09:08:00.002+09:002014-11-27T09:08:39.716+09:00jquery.transform.js で CSS3 の transform をアニメーションさせる<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtyKBHGkiwfCWqtmhpwWbcKUQxzu66QEO8Cewga6RWuhabsLNUKcJ1cWoE2eN3-N67EsZXg5JueLhCX-CrXyKv_YnegJlnGuYAs5EcHdqNyXpP0vjOLwRAUF20nuUmeC7gExebOxID4pY/s1600/jQuery.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtyKBHGkiwfCWqtmhpwWbcKUQxzu66QEO8Cewga6RWuhabsLNUKcJ1cWoE2eN3-N67EsZXg5JueLhCX-CrXyKv_YnegJlnGuYAs5EcHdqNyXpP0vjOLwRAUF20nuUmeC7gExebOxID4pY/s320/jQuery.png" /></a>要素を CSS3 の transform で移動・回転・拡大縮小などさせつつ、<br />
アニメーションもさせたい場合に便利な jQuery プラグインを紹介します。<br />
<br />
<h4>jquery.transform.js</h4><a href="https://github.com/eenox/jQuery-3D-transform" target="_blank">eenox/jQuery-3D-transform</a><br />
<br />
このプラグインは指定の面倒な transform 属性を簡単に指定できるようにします。<br />
transform 属性については <a href="http://www.htmq.com/css3/transform.shtml" target="_blank">transform-CSS3リファレンス</a> を参照して下さい。<br />
transform 属性は各種変換関数をスペース区切りで指定しなくてはならないので面倒でしたが、<br />
普通の CSS の属性を扱うように transform 属性の関数を扱うことができます。<br />
<pre class="brush: js; first-line: 1; highlight: [,];" title="例: 移動させつつ、回転しつつ、縮小しつつ、じわっと現れるアニメーション">$(".transform").css({
"top": top1,
"left": left1,
"opacity": "0",
"rotate": rotate1 + "deg",
"scale": "2, 2"
}).animate({
"top": top2,
"left": left2,
"opacity": "1",
"rotate": rotate2 + "deg",
"scale": "1, 1"
}, 2000, 'swing');</pre><br />
transform 属性を上記のように簡単に扱えるというだけで<br />
アニメーションさせなくても使いたい jQuery プラグインです。<br />
<br />
<h4>参考</h4><a href="http://black-flag.net/jquery/20121024-4259.html" target="_blank">jQueryアニメーションでCSS3のTransformを操作して拡大縮小/回転などを実装させるいろいろ | BlackFlag</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-86198245594137675742014-11-19T12:00:00.000+09:002014-11-19T12:00:03.613+09:00さくらのVPSにスタードメインで取得した独自ドメインを設定してみたさくらののVPSにスタードメインで取得した独自ドメインの設定してみました。<br />
個人でVPSを借りて遊ぶのには hosts ファイル書き換えで十分でしたが、<br />
サイトを他の人にも見せることになったので<br />
IP でアクセスしてもらうのもカッコがつかないなぁ、ということでドメインを取得しました。<br />
安くて Twitter などでも評判が良く、Whois情報公開代行も無料で行ってくれる<a href="http://www.star-domain.jp/" target="_blank">スタードメイン</a>にしました。<br />
<br />
<h3>さくらのVPS</h3><h4>コントロールパネルにログイン</h4>さくらのVPSコントロールパネルにログインし、左メニューにある「ネームサーバ登録」をクリックします。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgORLHrAzOsbzoUEKoyHI1EOmOCVi29esD8BP7LTKL_z_UWb0IdI55k7PFb3UXOfbb_FlhbQCtX_PYltZtQLSOTEEt9TsywNVpeETs4n5Q4iUYAA5PQZdtLVy9h2PJLZte-XHQr_NXlTzA/s1600/01_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgORLHrAzOsbzoUEKoyHI1EOmOCVi29esD8BP7LTKL_z_UWb0IdI55k7PFb3UXOfbb_FlhbQCtX_PYltZtQLSOTEEt9TsywNVpeETs4n5Q4iUYAA5PQZdtLVy9h2PJLZte-XHQr_NXlTzA/s720/01_sakura-vps-domain.png" /></a><br />
「さくらインターネットの会員メニュー」ログインページに移動します。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM4oO-acKJc7KK0_z6E2gJlvXQOk47T1f5a6o4WqSkX2qHikszIJA5RYSIjjgSYz3RX40BbQidCg_6dYslhTETaxboo4KD_xJtn9kl5lGAdMxivhzT4BfqpjYFgsKq3mJYa-1Fnffe-xQ/s1600/02_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM4oO-acKJc7KK0_z6E2gJlvXQOk47T1f5a6o4WqSkX2qHikszIJA5RYSIjjgSYz3RX40BbQidCg_6dYslhTETaxboo4KD_xJtn9kl5lGAdMxivhzT4BfqpjYFgsKq3mJYa-1Fnffe-xQ/s1600/02_sakura-vps-domain.png" /></a><br />
「会員ID」「パスワード」を入力し、「ログイン(認証)」をクリックします。<br />
<br />
<h4>新しいネームサーバの登録</h4>ページの下の方に「新しいネームサーバの登録」があります。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBvw-GwIElhQbHhfYHTw_Py3pZVOlJMSnh7vEwwVNQBrrMxfRGWuS4MPNQAP_s3B4HtQ-bQlBpyTLajrnMJBvIhxlxtiymPu-OXBTF5nBrEUbLPdCZdzrGwoLNCYBgqkA8NdTTBUi-gUg/s1600/03_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBvw-GwIElhQbHhfYHTw_Py3pZVOlJMSnh7vEwwVNQBrrMxfRGWuS4MPNQAP_s3B4HtQ-bQlBpyTLajrnMJBvIhxlxtiymPu-OXBTF5nBrEUbLPdCZdzrGwoLNCYBgqkA8NdTTBUi-gUg/s1600/03_sakura-vps-domain.png" /></a><br />
設定する「ドメイン名」を入力し、「送信する」をクリックします。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijBocXa5PMPAKF1El7G-ufJhtEbqMmFnimVTr7_fltpTKBl5Tb8ZmOgwOubEeRlbFjiG8fgxDZiJ6H-0AYgpntjLpnARHSiZ4ROCsie-xyZs6WhNUszz0f-rG99K5upSHLbdOi2JvK4qE/s1600/05_sakura-vps-domain_.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijBocXa5PMPAKF1El7G-ufJhtEbqMmFnimVTr7_fltpTKBl5Tb8ZmOgwOubEeRlbFjiG8fgxDZiJ6H-0AYgpntjLpnARHSiZ4ROCsie-xyZs6WhNUszz0f-rG99K5upSHLbdOi2JvK4qE/s1600/05_sakura-vps-domain_.png" /></a><br />
ゾーンの追加が実施されるので、ゾーンの初期設定をするために「ドメインメニューへ」をクリックします。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPaPGHNsF9zKv_5MCB2rDsQWtf3YiuxVm0CwT6F0ZCgKBhswqEqKlG8mR_M-O6H9KdIG0fVFF_9FFQbFsximVclqIIarQDkO77PntEpCWn-zcJpzVFVx-5VB0NWwavGUG_5dJGWAvM3d8/s1600/04_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPaPGHNsF9zKv_5MCB2rDsQWtf3YiuxVm0CwT6F0ZCgKBhswqEqKlG8mR_M-O6H9KdIG0fVFF_9FFQbFsximVclqIIarQDkO77PntEpCWn-zcJpzVFVx-5VB0NWwavGUG_5dJGWAvM3d8/s700/04_sakura-vps-domain.png" /></a><br />
ドメイン名の一覧が表示されるので、設定するドメインの「ゾーン編集」をクリックします。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMzj1ElzxNGTzLFNLoEE2yyJ6nK074vVMS-4jAuWEwmX9av2je8fcKg2_zClJwWpvDM3cc38RK-nQjgbG0UtPHFvSxysJNE3tvX57FMvD_duivfJElL535P54tFQupwz7zkSYbaoPkTg4/s1600/05_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMzj1ElzxNGTzLFNLoEE2yyJ6nK074vVMS-4jAuWEwmX9av2je8fcKg2_zClJwWpvDM3cc38RK-nQjgbG0UtPHFvSxysJNE3tvX57FMvD_duivfJElL535P54tFQupwz7zkSYbaoPkTg4/s1600/05_sakura-vps-domain.png" /></a><br />
簡単設定の項目の「サーバのIPアドレス」にVPSのIPアドレスを入力し、「送信する」をクリックします。<br />
<br />
<h4>さくらインターネットのネームサーバ</h4>設定したドメインの情報が表示されます。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeGqD8sUvik2Wf_NvPaifRa4qWccuow_Vwx-dTwNzf8B6Uj_zuSUs19V5DtAgP0EAFnBep761Td0GDO5PGhpfJUY-h7y4i7nJP9jZx-5KCq8POe48gVhwh_wFWLbRJKKr6eY8DQLRCpL4/s1600/06_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeGqD8sUvik2Wf_NvPaifRa4qWccuow_Vwx-dTwNzf8B6Uj_zuSUs19V5DtAgP0EAFnBep761Td0GDO5PGhpfJUY-h7y4i7nJP9jZx-5KCq8POe48gVhwh_wFWLbRJKKr6eY8DQLRCpL4/s1600/06_sakura-vps-domain.png" /></a><br />
先ほど入力したIPアドレスは、「Aレコード」に追加されています。<br />
ネームサーバーの情報(タイプが NS のもの)は、<br />
スタードメイン側に登録するのでページは閉じないでおきましょう。<br />
<br />
<h3>スタードメイン</h3>「さくらのネームサーバ」を利用するように設定したので、<br />
<a href="http://www.star-domain.jp/" target="_blank">スタードメイン</a>側から「さくらのネームサーバ」を参照するように設定します。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXB_gmUmd6jI_5S0Fp9SZlNlQWBP_EKzi-hEYW5cHJ4cz5K62X2fgg7EUynBDcmCS95RSBYlXyyp1dm-xCSg-d4pR-R4lGn7b1svkWnswLA09IlDu0a6WEGXVJLHubZQam9XIwfaQF8XA/s1600/07_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXB_gmUmd6jI_5S0Fp9SZlNlQWBP_EKzi-hEYW5cHJ4cz5K62X2fgg7EUynBDcmCS95RSBYlXyyp1dm-xCSg-d4pR-R4lGn7b1svkWnswLA09IlDu0a6WEGXVJLHubZQam9XIwfaQF8XA/s700/07_sakura-vps-domain.png" /></a><br />
スタードメインを運営している NetOwl の管理ページから<br />
「スタードメイン管理」の「管理ドメイン一覧」を開いて「ドメイン管理ツール」をクリックします。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5_HWngFmbeYelCEE1SPQaVxAZI_H1EWw4oFiaXpUCeHYSNact0JvLirazXee-er0IHJtqzKa89KDKgQLFYiyfCm0wP6xbX_gCk-PnIJt8gmB_ySqR1L-jYWJ_R8J2uG5fwTmShkvXS_s/s1600/08_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5_HWngFmbeYelCEE1SPQaVxAZI_H1EWw4oFiaXpUCeHYSNact0JvLirazXee-er0IHJtqzKa89KDKgQLFYiyfCm0wP6xbX_gCk-PnIJt8gmB_ySqR1L-jYWJ_R8J2uG5fwTmShkvXS_s/s700/08_sakura-vps-domain.png" /></a><br />
「ネームサーバの確認・変更」をクリックします。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijWMkQhPO0Mbgw-B70sOCBl6xT8X7iC_V1QeqImFRa3uQuoMm_reQV24vWqLnTgRFtji8zMTNKzgdVpVSW1RGc6O9WpsqYekIVwZvltyLu17swMq987ts_Z1_PNwiJEN8Lasies6H5GVo/s1600/09_sakura-vps-domain.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijWMkQhPO0Mbgw-B70sOCBl6xT8X7iC_V1QeqImFRa3uQuoMm_reQV24vWqLnTgRFtji8zMTNKzgdVpVSW1RGc6O9WpsqYekIVwZvltyLu17swMq987ts_Z1_PNwiJEN8Lasies6H5GVo/s700/09_sakura-vps-domain.png" /></a><br />
ネームサーバにさくらのVPSのネームサーバーの情報を入力して保存します。<br />
<br />
<h3>ドメイン設定完了</h3>数時間くらいすれば名前解決されてドメインでアクセスすれば<br />
さくらのVPS側にアクセスできるようになります。<br />
<br />
<h3>DNS逆引きレコード変更</h3>DNS逆引きは IP アドレスからドメイン名を取得することで、<br />
DNS逆引きレコードが設定してあれば取得できる。<br />
DNS逆引きレコードが設定してあると<br />
どこの馬の骨かもわからないサーバではない(※自称)と宣言できるので<br />
設定しておくといいかもね(※ただし必須ではない)というくらいのノリっぽいです。<br />
<br />
以下を参考に設定しました。<br />
<a href="http://support.sakura.ad.jp/manual/vps/domain/rdns_record.html" target="_blank">DNS逆引きレコードを変更する|さくらのVPS|さくらインターネット公式サポートサイト</a><br />
<br />
設定すると <span class="cmd terminal">nslookup IP.ADD.RE.SS</span> で設定したドメイン名が取得できます。<br />
<br />
<h3>参考</h3><a href="http://webkaru.net/vps/sakura-domain-setting/" target="_blank">さくらのVPSに独自ドメインを設定してみた - VPS比較 - Webkaru</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-23297887527720363622014-10-29T14:55:00.000+09:002014-10-30T00:34:07.904+09:00[SublimeText] Sublime Text 3 の検索で日本語をエンターすると文字が消えるのを防ぐ<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiay9AYdqEW007CwxeX7uQwjLzTViTuEj3r8jPyTRYkZaxWKm9g9SJ34caSynSaZQNWuar7nMqR9zL08Qc48KfsIQyCEJ4Y4FoVDoLZhI0c-10OWQCFDq3GtFvkbCA1x8XyZn_10sWRWJQ/s1600/SublimeText.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiay9AYdqEW007CwxeX7uQwjLzTViTuEj3r8jPyTRYkZaxWKm9g9SJ34caSynSaZQNWuar7nMqR9zL08Qc48KfsIQyCEJ4Y4FoVDoLZhI0c-10OWQCFDq3GtFvkbCA1x8XyZn_10sWRWJQ/s320/SublimeText.png" /></a>Sublime Text で地味に困るのが検索窓に日本語を入力した時。<br />
エンターを押した瞬間、入力した文字が消えるので全然検索ができない。<br />
ずっと困ったまま放置していたんだけど<br />
たまたま Twitter で解決方法が流れてきたのでメモ。<br />
<br />
<h4>参考</h4><a href="https://gist.github.com/chibicode/ad1f50b3b191ee694556">Sublime Textの検索窓に日本語を入力する方法</a><br />
<a href="http://memo.sanographix.net/post/101061111635">Sublime Text 3 で日本語を検索したとき文字が消える不具合を直す - MEMOGRAPHIX</a><br />
<br />
<h3>キーマップを変更してエンターで動作しないようにする</h3>参考元ではコメントアウトされていましたが使えないのは面倒なので<br />
<span class="key">ctrl</span> + <span class="key">enter</span> に全て置き換えました。<br />
<pre class="brush: js; first-line: 1; highlight: [2, 13, 27];" title="Default (OSX).sublime-keymap">// Find panel key bindings
{ "keys": ["ctrl+enter"], "command": "find_next", "context":
[{"key": "panel", "operand": "find"}, {"key": "panel_has_focus"}]
},
{ "keys": ["shift+enter"], "command": "find_prev", "context":
[{"key": "panel", "operand": "find"}, {"key": "panel_has_focus"}]
},
{ "keys": ["alt+enter"], "command": "find_all", "args": {"close_panel": true},
"context": [{"key": "panel", "operand": "find"}, {"key": "panel_has_focus"}]
},
// Replace panel key bindings
{ "keys": ["ctrl+enter"], "command": "find_next", "context":
[{"key": "panel", "operand": "replace"}, {"key": "panel_has_focus"}]
},
{ "keys": ["shift+enter"], "command": "find_prev", "context":
[{"key": "panel", "operand": "replace"}, {"key": "panel_has_focus"}]
},
{ "keys": ["alt+enter"], "command": "find_all", "args": {"close_panel": true},
"context": [{"key": "panel", "operand": "replace"}, {"key": "panel_has_focus"}]
},
{ "keys": ["ctrl+alt+enter"], "command": "replace_all", "args": {"close_panel": true},
"context": [{"key": "panel", "operand": "replace"}, {"key": "panel_has_focus"}]
},
// Incremental find panel key bindings
{ "keys": ["ctrl+enter"], "command": "hide_panel", "context":
[{"key": "panel", "operand": "incremental_find"}, {"key": "panel_has_focus"}]
},
{ "keys": ["shift+enter"], "command": "find_prev", "context":
[{"key": "panel", "operand": "incremental_find"}, {"key": "panel_has_focus"}]
},
{ "keys": ["alt+enter"], "command": "find_all", "args": {"close_panel": true},
"context": [{"key": "panel", "operand": "incremental_find"}, {"key": "panel_has_focus"}]
},
</pre>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-8351041484561707072014-10-24T10:01:00.002+09:002014-10-24T10:04:19.155+09:00AndroidStudio で APK を特定のフォルダにコピーする Gradle の設定<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl35xoEn47flwoSBBhJeXXxveVCLNoIf73Qx71UTWAoup4ccBusf6kTMPccMIcCVZwbEgISoiXYoDgdWZTg7YC0tOR_xbkiDjKMP-9f24HcNeIH4r4sZTD3tX37SuLM0F4m-P_RMBPxpI/s1600/AndroidStudio.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl35xoEn47flwoSBBhJeXXxveVCLNoIf73Qx71UTWAoup4ccBusf6kTMPccMIcCVZwbEgISoiXYoDgdWZTg7YC0tOR_xbkiDjKMP-9f24HcNeIH4r4sZTD3tX37SuLM0F4m-P_RMBPxpI/s128/AndroidStudio.png" /></a><a href="http://wada811.blogspot.com/2014/10/generate-signed-APK-has-been-named-by-gradle.html" target="_blank">AndroidStudio で APK のファイル名を変更する Gradle の設定 | DevAchieve</a>で<br />
APK をリネームしましたが、<br />
出力されるフォルダが build/outputs/apk/ なので<br />
変更したいことがあるかと思います。<br />
Gradle の Task を定義してあげれば<br />
任意のフォルダにコピーする処理を実行することができます。<br />
<br />
<h4>Gradle で Signed APK とProGuard 関連ファイルをコピーするタスクを設定する</h4><br />
<a href="https://github.com/wada811/Android-Material-Design-Colors/commit/c7cdd9059647b2aaec74c4a38a80c58c584160b0" target="_blank">Add move apk task and move proguard task · c7cdd90 · wada811/Android-Material-Design-Colors</a><br />
<br />
<pre class="brush: groovy; first-line: 1; highlight: [12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,];" title="app/build.gradle">applicationVariants.all { variant ->
if (variant.buildType.name.equals("release")) {
variant.outputs.each { output ->
if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {
// Rename APK
def applicationId = defaultConfig.applicationId
def versionCode = defaultConfig.versionCode
def versionName = defaultConfig.versionName
def date = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
def newName = "${applicationId}_r${versionCode}_v${versionName}_${date}.apk"
def publish = project.tasks.create("publishAll")
// Move and Rename APK
def task = project.tasks.create("publish${variant.name.capitalize()}Apk", Copy)
task.from(output.outputFile)
task.rename(output.outputFile.name, newName)
task.into(file("${variant.name}/apk").getAbsolutePath())
task.dependsOn variant.assemble
publish.dependsOn task
// Move ProGuard
if (variant.buildType.runProguard) {
def copyTask = project.tasks.create("copy${variant.name.capitalize()}MappingText", Copy)
def buildTypeName = variant.buildType.name
copyTask.from(file("build/outputs/proguard/${buildTypeName}").path)
copyTask.into(file("${variant.name}/proguard").getAbsolutePath())
copyTask.dependsOn variant.assemble
task.dependsOn copyTask
}
}
}
}
}</pre><br />
<h4>実行</h4><span class="cmd terminal">./gradlew publishAll</span> で<br />
app/release/apk/ に Signed APK が、<br />
app/release/proguard/ に ProGuard 関連ファイルがコピーされます。<br />
<br />
<h4>参考</h4><a href="http://qiita.com/takke/items/015c79f8be67f5d72ed6" target="_blank">AndroidStudioでAPKを作ったあとに特定のディレクトリにAPKをコピーする - Qiita</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-41961409638941793862014-10-23T08:13:00.003+09:002014-10-23T12:47:48.293+09:00AndroidStudio で APK のファイル名を変更する Gradle の設定<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl35xoEn47flwoSBBhJeXXxveVCLNoIf73Qx71UTWAoup4ccBusf6kTMPccMIcCVZwbEgISoiXYoDgdWZTg7YC0tOR_xbkiDjKMP-9f24HcNeIH4r4sZTD3tX37SuLM0F4m-P_RMBPxpI/s1600/AndroidStudio.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl35xoEn47flwoSBBhJeXXxveVCLNoIf73Qx71UTWAoup4ccBusf6kTMPccMIcCVZwbEgISoiXYoDgdWZTg7YC0tOR_xbkiDjKMP-9f24HcNeIH4r4sZTD3tX37SuLM0F4m-P_RMBPxpI/s128/AndroidStudio.png" /></a>Android Studio で Sigined APK を生成するには<br />
ツールバーの [ Build > Generate Signed APK... ] から<br />
ガイダンスに従えば生成できます。<br />
しかし、GUI からではファイル名は app-release.apk などになるので<br />
変更したい場合などは Gradle の設定が必要になります。<br />
<br />
<h4>Gradle で Signed APK のファイル名を設定する</h4><a href="https://github.com/wada811/Android-Material-Design-Colors/commit/bc415512a60dee143ae9d45a726fa92ad236b2d8" target="_blank">Generate signed APK has been named by program · bc41551 · wada811/Android-Material-Design-Colors</a><br />
<br />
<pre class="brush: groovy; first-line: 1; highlight: [25,26,27,28,29,30,31,32,33,34,35,];" title="app/build.gradle">apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.0.1"
defaultConfig {
applicationId "at.wada811.android.material.design.colors.sample"
minSdkVersion 8
targetSdkVersion 21
versionCode 2
versionName "1.1.0"
}
signingConfigs {
release
}
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
applicationVariants.all { variant ->
if (variant.buildType.name.equals("release")) {
def file = variant.outputFile
def applicationId = defaultConfig.applicationId
def versionCode = defaultConfig.versionCode
def versionName = defaultConfig.versionName
def date = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
def newName = "${applicationId}_r${versionCode}_v${versionName}_${date}.apk"
variant.outputFile = new File(file.parent, newName)
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21+'
compile project(':library')
}</pre><br />
<span class="cmd">./gradlew assembleRelease</span>すると<br />
<b>at.wada811.android.material.design.colors.sample_r2_v1.1.0_20141022_173737.apk</b><br />
のようなファイル名で app/build/outputs に生成されます。<br />
<br />
<h4>参考</h4><a href="http://qiita.com/takke/items/c6c774807f064500aca4" target="_blank">gradle - AndroidStudioでAPKのファイル名にバージョン番号などを入れる設定 - Qiita</a><br />
<br />
<h3>追記: Android Gradle Plugin 0.13, Gradle 2.1 で outputFile が deprecated になっている</h3><b>WARNING [Project: :sample] variant.getOutputFile() is deprecated. Call it on one of variant.getOutputs() instead.</b> が表示されるので書き直しました。<br />
<br />
<pre class="brush: groovy; first-line: 1; highlight: [,];" title="">applicationVariants.all { variant ->
if (variant.buildType.name.equals("release")) {
variant.outputs.each { output ->
System.println("* output.outputFile.name : ${output.outputFile.name}")
if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {
// Rename APK
def applicationId = defaultConfig.applicationId
def versionCode = defaultConfig.versionCode
def versionName = defaultConfig.versionName
def date = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
def newName = "${applicationId}_r${versionCode}_v${versionName}_${date}.apk"
output.outputFile = new File(output.outputFile.parent, newName)
}
}
}
}</pre><br />
outputs というから複数あるのかとおもいきや apk しかありませんでした。<br />
無駄にネストが深くなる…。<br />
<br />
<h4>参考</h4><a href="http://stackoverflow.com/questions/25997866/gradle-warning-variant-getoutputfile-and-variant-setoutputfile-are-deprecat" target="_blank">android - Gradle warning: variant.getOutputFile() and variant.setOutputFile() are deprecated - Stack Overflow</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-44866533733744339802014-10-22T08:52:00.003+09:002014-10-22T09:31:00.473+09:00AndroidStudio で APK の署名の設定を gradle.properties に記述する<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl35xoEn47flwoSBBhJeXXxveVCLNoIf73Qx71UTWAoup4ccBusf6kTMPccMIcCVZwbEgISoiXYoDgdWZTg7YC0tOR_xbkiDjKMP-9f24HcNeIH4r4sZTD3tX37SuLM0F4m-P_RMBPxpI/s1600/AndroidStudio.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl35xoEn47flwoSBBhJeXXxveVCLNoIf73Qx71UTWAoup4ccBusf6kTMPccMIcCVZwbEgISoiXYoDgdWZTg7YC0tOR_xbkiDjKMP-9f24HcNeIH4r4sZTD3tX37SuLM0F4m-P_RMBPxpI/s128/AndroidStudio.png" /></a>Android Studio で Sigined APK を生成するには<br />
ツールバーの [ Build > Generate Signed APK... ] から<br />
ウィザードに従えば生成できます。<br />
しかし、CUI から Signed APK を生成したいことがあるかと思います。<br />
また、そのプロジェクトを public リポジトリで管理している場合に<br />
署名に関する設定を公開しないようにするにはどうすればいいのかという問題もあります。<br />
<br />
以下に示す方法では、証明に関する設定を gradle.properties に記述し、<br />
.gitignore で gradle.properties を公開しないようにすることで<br />
署名に関する情報を秘密にしておくおことが可能です。<br />
<br />
<a href="https://github.com/wada811/Android-Material-Design-Colors/commit/bc415512a60dee143ae9d45a726fa92ad236b2d8" target="_blank">Generate signed APK has been named by program · bc41551 · wada811/Android-Material-Design-Colors</a><br />
<br />
<pre class="brush: groovy; first-line: 1; highlight: [14,15,16,21,28,29,30,31,32,33,34,35,36,37,38,39,];" title="sample/build.gradle">apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.0.1"
defaultConfig {
applicationId "at.wada811.android.material.design.colors.sample"
minSdkVersion 8
targetSdkVersion 21
versionCode 2
versionName "1.1.0"
}
signingConfigs {
release
}
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
}
...
if (project.hasProperty('storeFile')) {
android.signingConfigs.release.storeFile = new File(System.getenv('HOME'), storeFile)
}
if (project.hasProperty('storePassword')) {
android.signingConfigs.release.storePassword = storePassword
}
if (project.hasProperty('keyAlias')) {
android.signingConfigs.release.keyAlias = keyAlias
}
if (project.hasProperty('keyPassword')) {
android.signingConfigs.release.keyPassword = keyPassword
}</pre><br />
<pre class="brush: plain; first-line: 1; highlight: [,];" title="sample/gradle.properties">storeFile=/path/to/your.keystore
storePassword=keystorePass
keyAlias=appAlias
keyPassword=appPass</pre><br />
<pre class="brush: plain; first-line: 1; highlight: [,];" title="sample/.gitignore">gradle.properties</pre><br />
new File(System.getenv('HOME'), storeFile) がキモで、<br />
file(storeFile) にするとプロジェクトの相対パスで認識されるから<br />
プロジェクトに keystore を含めるか、無理やり相対パスからたどるかになるんだけど<br />
前者はプロジェクトごとに keystore を入れなければならなくて一元管理できないし、<br />
後者は環境によってパスが変わりうるから微妙になります。<br />
その点、new File(System.getenv('HOME'), storeFile) は $HOME からの絶対パスになるので統一しやすいです。<br />
<br />
<h4>参考</h4><a href="http://qiita.com/shiraji/items/8f55b5295094487ce71a" target="_blank">AndroidStudio - Android Studio(Gradle)でapkファイルを作成する時にstorePassword/keyAlias/keyPasswordの指定方法をいくつか検証してみた。 - Qiita</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-16902026024646181832014-10-15T23:30:00.000+09:002014-10-16T08:51:08.886+09:00[Android]ActionBar のタイトルの文字色を変更する<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s1600/android.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s1600/android.png" /></a>ActionBar のタイトルの文字色を変えるメソッドはないので<br />
あまり変えてやろうと思うこともないかと思いますが<br />
気まぐれに文字色を変えたくなった時のためにメモしておきます。<br />
<br />
<h4>Theme でActionBar のタイトルの文字色を変更する</h4>普通の方法ですが、動的に変更することができません。<br />
<pre class="brush: xml; first-line: 1; highlight: [,];" title="res/values/styles.xml"><resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="actionBarStyle">@style/AppTheme.ActionBarStyle</item>
</style>
<style name="AppTheme.ActionBarStyle" parent="Widget.AppCompat.Light.ActionBar">
<item name="titleTextStyle">@style/AppTheme.ActionBar.TitleTextStyle</item>
</style>
<style name="AppTheme.ActionBar.TitleTextStyle" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
<item name="android:textColor">@color/red</item>
</style>
</resources>
</pre><pre class="brush: xml; first-line: 1; highlight: [,];" title="res/values-v14/styles.xml"><resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/AppTheme.ActionBarStyle</item>
</style>
<style name="AppTheme.ActionBarStyle" parent="Widget.AppCompat.ActionBar">
<item name="android:titleTextStyle">@style/AppTheme.ActionBar.TitleTextStyle</item>
</style>
</resources>
</pre><br />
<h4>Programmatically</h4><pre class="brush: java; first-line: 1; highlight: [,];" title="ActionBarActivity#onCreate などで">String title = getResources().getString(R.string.title);
int titleColor = getResources().getColor(R.color.titleColor);
String htmlColor = String.format(Locale.US, "#%06X", (0xFFFFFF & Color.argb(0, Color.red(titleColor), Color.green(titleColor), Color.blue(titleColor))));
String titleHtml = "<font color=\"" + htmlColor + "\">" + title + "</font>";
getSupportActionBar().setTitle(Html.fromHtml(titleHtml));</pre><br />
Html とかウケる。こんな方法があったとは。<br />
<br />
<h5>参考</h5><a href="http://stackoverflow.com/questions/5861661/actionbar-text-color" target="_blank">android - ActionBar text color - Stack Overflow</a><br />
wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-83803913597839375002014-10-05T23:49:00.000+09:002014-10-05T23:49:08.920+09:00git diff で JSON を整形して比較する<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj36fShdxLJUhp29QTRBn-3j4XRvirOE8EqlWbmQzceN3tbhaaLyXJuEVTO4s0vbJieVJ0HNQ6AmI4ov5lt7LW21BUxD5AU-jIMWZZ1Zuh4pKhRQV9OYUO9drTXoYC6zZW_VDYZ2hT8blg/s1600/git.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj36fShdxLJUhp29QTRBn-3j4XRvirOE8EqlWbmQzceN3tbhaaLyXJuEVTO4s0vbJieVJ0HNQ6AmI4ov5lt7LW21BUxD5AU-jIMWZZ1Zuh4pKhRQV9OYUO9drTXoYC6zZW_VDYZ2hT8blg/s320/git.png" /></a>Git でJSON を整形して比較できるらしいのでメモ。<br />
JSON だけでなく Word や ODT、 Jpeg や PNG なども<br />
実ファイルを比較時に変換させることができるみたいです。<br />
<br />
<h5>参考</h5><a href="http://git-scm.com/book/en/Customizing-Git-Git-Attributes" target="_blank">Git - Git Attributes</a><br />
<a href="http://git-scm.com/docs/gitattributes" target="_blank">Git - gitattributes Documentation</a><br />
<br />
<h3>設定</h3><pre class="brush: plain; first-line: 1; highlight: [,];" title=".gitattributes">*.json diff=json</pre><pre class="brush: plain; first-line: 1; highlight: [,];" title=".gitconfig">[diff "json"]
textconv = "jq ."</pre>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-57167329351462738522014-09-22T12:10:00.001+09:002014-09-22T12:10:35.329+09:00[zsh]peco で git をもっと便利にする<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7QiUm0IRncjsFY4zE-fTqaqNGuKjlCMfdgbw_j0GoqbJMBi7ZtcROIFfkEWVSkkcqiarafliH4O9r5uaWqhUk6V8JhpwB8jspyUVDXCY2tjfp4ArypjsyWFvHkswqXlrgUmgogvYydR4/s1600/iTerm.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7QiUm0IRncjsFY4zE-fTqaqNGuKjlCMfdgbw_j0GoqbJMBi7ZtcROIFfkEWVSkkcqiarafliH4O9r5uaWqhUk6V8JhpwB8jspyUVDXCY2tjfp4ArypjsyWFvHkswqXlrgUmgogvYydR4/s320/iTerm.png" /></a>peco を導入しました。すごく便利です。<br />
導入についてはコチラ↓<br />
<a href="http://wada811.blogspot.com/2014/09/peco.html" target="_blank">peco を導入した | DevAchieve</a><br />
<br />
peco で色々フィルタリングして選択できるのは<br />
ファイル、ハッシュ、ブランチを選択する事が多い Git と相性が良さそうです。<br />
<br />
peco script を色々作るとエイリアスとか大変っぽいので<br />
zsh のグローバルエイリアスを使ってみました。<br />
<br />
<h3>編集されたファイルをフィルタリングする</h3><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zsh/peco-scripts/peco-git-changed-files.zsh">function peco-git-changed-files(){
git status --short | peco | awk '{print $2}'
}</pre><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zshrc">alias -g F='$(peco-git-changed-files)'</pre><h4>使い方</h4><span class="cmd terminal">git add F</span><br />
<span class="key">Ctrl</span> + <span class="key">Space</span> で複数ファイル選択して add も可能です。<br />
<br />
<h3>コミットのハッシュをフィルタリングする</h3><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zsh/peco-scripts/peco-git-hash.zsh">function peco-git-hash(){
# git log --oneline --branches | peco | awk '{print $1}'
git lg | peco | sed -e "s/^[\*\|][ |\\\/\*]*//g" | awk '{ print $1 }'
}</pre><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zshrc">alias -g F='$(peco-git-hash)'</pre><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.gitconfig">[alias]
lg = log --all --graph --decorate --oneline</pre>git lg (log graph) は僕の git log を置き換えるコマンドです。<br />
以下のようにコミットが確認できるので履歴確認、ブランチ確認、マージする際に便利なコマンドです。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB6a4AVj91cBj1QhJ4hn0oPFQc7mH2th4a0yyCcSfBB0MHGxS3Aoj9fSzHwQkndUt4rJ73WUv_NLHLWQKWo4U7pn4s2Ma60_7IwOQ4WQElen_SXqh1ZalarVPm7yot9eCbaiixbFAe-nk/s1600/git-lg.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB6a4AVj91cBj1QhJ4hn0oPFQc7mH2th4a0yyCcSfBB0MHGxS3Aoj9fSzHwQkndUt4rJ73WUv_NLHLWQKWo4U7pn4s2Ma60_7IwOQ4WQElen_SXqh1ZalarVPm7yot9eCbaiixbFAe-nk/s640/git-lg.png" /></a><br />
peco ではこの色付けがなくなってしまうので残念です。頑張って保持して欲しいところ。<br />
<h4>使い方</h4><span class="cmd terminal">git diff F</span> とか <span class="cmd terminal">git cherry-pick F</span> とか。<br />
おおよそコミットのハッシュを指定するところ全てで使えるんじゃないですかね?<br />
git diff で複数選択とか便利です。<br />
<br />
<h3>ブランチをフィルタリングする</h3><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zsh/peco-scripts/peco-git-branch.zsh">function peco-git-branch(){
git branch | peco | sed -e "s/^\*[ ]*//g"
}</pre><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zshrc">alias -g B='$(peco-git-branch)'</pre><h4>使い方</h4><span class="cmd terminal">git checkout B</span> とか<br />
<span class="cmd terminal">git merge B</span> とか<br />
<span class="cmd terminal">git diff B</span> など。<br />
<br />
<h3>参考</h3><a href="http://qiita.com/sona-tar/items/fe401c597e8e51d4e243" target="_blank">pecoでgit向けの汎用的なフィルターを2つ作成してみた - Qiita</a><br />
<a href="http://k0kubun.hatenablog.com/entry/2014/07/06/033336" target="_blank">私のpeco活用事例 - k0kubun's blog</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-13744002561936477032014-09-22T10:04:00.000+09:002014-09-22T10:05:32.862+09:00[zsh]cdr: 開いたディレクトリの履歴からディレクトリを開く<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7QiUm0IRncjsFY4zE-fTqaqNGuKjlCMfdgbw_j0GoqbJMBi7ZtcROIFfkEWVSkkcqiarafliH4O9r5uaWqhUk6V8JhpwB8jspyUVDXCY2tjfp4ArypjsyWFvHkswqXlrgUmgogvYydR4/s1600/iTerm.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7QiUm0IRncjsFY4zE-fTqaqNGuKjlCMfdgbw_j0GoqbJMBi7ZtcROIFfkEWVSkkcqiarafliH4O9r5uaWqhUk6V8JhpwB8jspyUVDXCY2tjfp4ArypjsyWFvHkswqXlrgUmgogvYydR4/s320/iTerm.png" /></a><a href="http://wada811.blogspot.com/2014/09/peco.html" target="_blank">peco を導入した | DevAchieve</a> で実は cdr を導入していました。<br />
zsh に組み込まれているコマンドに cdr という<br />
開いたディレクトリの履歴からディレクトリを開くコマンドがあります。<br />
~/.zshrc で cdr を有効にしてあげれば使えるようになります。<br />
<br />
$HOME/.cache/shell/ は用意しないといけないので<br />
<span class="cmd terminal">mkdir -p $HOME/.cache/shell/</span> しておいて下さい。<br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zshrc"># cdr, add-zsh-hook を有効にする
autoload -Uz chpwd_recent_dirs cdr add-zsh-hook
add-zsh-hook chpwd chpwd_recent_dirs
# cdr の設定
zstyle ':completion:*' recent-dirs-insert both
zstyle ':chpwd:*' recent-dirs-max 500
zstyle ':chpwd:*' recent-dirs-default true
zstyle ':chpwd:*' recent-dirs-file "$HOME/.cache/shell/chpwd-recent-dirs"
zstyle ':chpwd:*' recent-dirs-pushd true</pre>設定については以下を参考にして下さい。<br />
<a href="http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#Recent-Directories" target="_blank">zsh: 26. User Contributions</a><br />
<a href="http://blog.n-z.jp/blog/2013-11-12-zsh-cdr.html" target="_blank">zshでcdの履歴管理に標準添付のcdrを使う - @znz blog</a><br />
<br />
<h4>使い方</h4><h5>確認</h5><div class="cmd terminal">cdr -l<br />
1 ~/.zsh<br />
2 ~/.zsh/peco-scripts<br />
3 ~/Documents/workspace<br />
4 ~/dotfiles</div><br />
<h5>開く</h5><span class="cmd terminal">cdr 3</span><br />
<br />
こんな感じですね。<br />
これだけじゃイチイチ開く前に確認しないといけないので peco で選択したいですね。<br />
<br />
<pre class="brush: shell; first-line: 1; highlight: [2,];" title="~/.zsh/peco-scripts/peco-cdr.zsh">function peco-cdr() {
local selected_dir=$(cdr -l | awk '{ print $2 }' | peco)
if [ -n "$selected_dir" ]; then
BUFFER="cd ${selected_dir}"
zle accept-line
fi
zle clear-screen
}
zle -N peco-cdr</pre>2行目で何をしているか。<br />
<blockquote><div class="cmd terminal">cdr -l<br />
1 ~/.zsh<br />
2 ~/.zsh/peco-scripts<br />
3 ~/Documents/workspace<br />
4 ~/dotfiles</div>↑を awk でディレクトリ名だけ抜き出して<br />
<div class="cmd terminal">cdr -l | awk '{ print $2 }'<br />
~/.zsh<br />
~/.zsh/peco-scripts<br />
~/Documents/workspace<br />
~/dotfiles</div>peco で選択して cd する。</blockquote>シンプルなコマンドの組み合わせで凄く便利に!<br />
これなら自分でも何か作れそうでワクワクします。wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-22805918869639254892014-09-22T09:38:00.001+09:002014-12-10T12:59:29.979+09:00peco を導入した<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7QiUm0IRncjsFY4zE-fTqaqNGuKjlCMfdgbw_j0GoqbJMBi7ZtcROIFfkEWVSkkcqiarafliH4O9r5uaWqhUk6V8JhpwB8jspyUVDXCY2tjfp4ArypjsyWFvHkswqXlrgUmgogvYydR4/s1600/iTerm.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7QiUm0IRncjsFY4zE-fTqaqNGuKjlCMfdgbw_j0GoqbJMBi7ZtcROIFfkEWVSkkcqiarafliH4O9r5uaWqhUk6V8JhpwB8jspyUVDXCY2tjfp4ArypjsyWFvHkswqXlrgUmgogvYydR4/s320/iTerm.png" /></a>コマンドラインの行選択ツール <a href="https://github.com/peco/peco" target="_blank">peco</a> を導入しました。<br />
<a href="http://peco.github.io/" target="_blank">peco - Simplistic Interactive Filtering Tool</a><br />
どんなものかわからないと思うので上のリンクから Demo の gif 画像を見て下さい。<br />
なんとなく便利そうな雰囲気がしますよね?<br />
<br />
<h4>インストール</h4>それではインストールしてみましょう。Mac では Homebrew で以下の通り。<br />
<span class="cmd terminal">brew tap peco/peco</span><br />
<span class="cmd terminal">brew install peco</span><br />
それ以外の場合は上のリンクからインストール方法を確認して下さい。<br />
Go で作られているのでインストールが簡単らしいです。<br />
<br />
<h4>peco のカスタマイズ</h4>peco はパイプでコマンドの出力を行選択して、パイプで次のコマンドに渡すコマンドラインツールなわけだけど<br />
ある程度頻繁に使いそうなものについてはスクリプトファイルを書いておいたほうが便利ですね。<br />
こういうものはどんどん拡張したくなるのでスクリプトファイルの保存場所を決めておきます。<br />
<dl><dt>~/.zshrc</dt>
<dd>~/.zsh/peco-scripts/ の読み込みやキーバインドの設定</dd>
<dt>~/.zsh/peco-scripts/</dt>
<dd>peco のスクリプトファイルの保存場所</dd> </dl><br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zshrc"># load peco scripts (require cdr)
for f (~/.zsh/peco-scripts/*) source "${f}"</pre><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zsh/peco-scripts/">% tree peco-scripts
peco-scripts
├── peco-cdr.zsh
└── peco-select-history.zsh</pre><h4>peco-cdr.zsh: 開いたディレクトリの履歴からディレクトリを選択する</h4><a href="http://wada811.blogspot.com/2014/09/zsh-cdr.html" target="_blank">[zsh]cdr: 開いたディレクトリの履歴からディレクトリを開く | DevAchieve</a><br />
<pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zsh/peco-scripts/peco-cdr.zsh">function peco-cdr() {
local selected_dir=$(cdr -l | awk '{ print $2 }' | peco)
if [ -n "$selected_dir" ]; then
BUFFER="cd ${selected_dir}"
zle accept-line
fi
zle clear-screen
}
zle -N peco-cdr</pre><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zshrc"># 履歴から cd
bindkey '^@' peco-cdr</pre><h4>peco-select-history.zsh: コマンドの履歴からコマンドを選択する</h4><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zsh/peco-scripts/peco-select-history.zsh">function peco-select-history() {
local tac
if which tac > /dev/null; then
tac="tac"
else
tac="tail -r"
fi
BUFFER=$(history -n 1 | eval $tac | peco --query "$LBUFFER")
CURSOR=$#BUFFER
# zle clear-screen
}
zle -N peco-select-history</pre><pre class="brush: shell; first-line: 1; highlight: [,];" title="~/.zshrc"># 履歴からコマンド選択
bindkey '^r' peco-select-history</pre><br />
<h5>追記: 2014/12/10</h5>コマンド履歴の重複を削除して peco で選択できるようにしました。<br />
<a href="http://qiita.com/wada811/items/78b14181a4de0fd5b497">[peco]peco-select-history.zsh で表示されるコマンド履歴の重複を削除する - Qiita</a><br />
<br />
<h4>まとめ</h4>使ってみるとわかりますが、すごく便利です!<br />
<br />
参考: <a href="http://shibayu36.hatenablog.com/entry/2014/06/27/223538" target="_blank">pecoを使い始めた - $shibayu36->blog;</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-62383774351919450702014-09-21T18:39:00.000+09:002014-09-21T18:54:47.124+09:00iTerm2 を導入した<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFC5TdJehSlPDlVyOmnnAj2SNoj9fka2iVZMysgiLoHRi-QZJyGeNivvka_fH-pbJVHLsHDTcMbAZEAgo4h4ybcvRVv2XQyq-r5iQE3HOZTAnPxvjgvswpxL3vEITlUmcAVWO72W5XrqE/s1600/iTerm.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFC5TdJehSlPDlVyOmnnAj2SNoj9fka2iVZMysgiLoHRi-QZJyGeNivvka_fH-pbJVHLsHDTcMbAZEAgo4h4ybcvRVv2XQyq-r5iQE3HOZTAnPxvjgvswpxL3vEITlUmcAVWO72W5XrqE/s320/iTerm.png" /></a>Mac をようやく Marvericks にアップデートできたので<br />
ついでに便利そうなツール類を入れまくる活動の第一弾です。<br />
Mac の Terminal より便利で色々設定できる iTerm2 というものを入れてみました。<br />
<br />
<h4>iTerm2 って何よ?どう便利なんよ?</h4>って言われると僕も困ってしまう。↓この辺を読むと便利そうって思うかもしれない。<br />
<a href="http://blog.uittie.com/entry/2014/02/24/iTerm2%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E3%81%BF%E3%81%9F%E3%82%88" target="_blank">iTerm2の使い方まとめてみた - uittie::blog</a><br />
<a href="http://techracho.bpsinc.jp/morimorihoge/2014_01_12/15093" target="_blank">事故らないために普段守っているターミナルの運用ポリシ(Mac + iTerm2) | TechRacho</a><br />
<br />
僕は色々設定できてカラースキーマも設定できればそれで良いかもしれない。<br />
<br />
<h4>カラースキーマ</h4><a href="http://this.aereal.org/entry/2013/01/02/222304" target="_blank">iTerm 2 で使えるカラースキーム、Japanesque を作った - Sexual Knowing</a><br />
<a href="http://blog.remora.cx/2012/10/let-us-use-solarized.html" target="_blank">最強カラースキームと言えば Solarized だよね! | blog.remora.cx</a><br />
このあたりが人気っぽい。<br />
<br />
<a href="http://iterm2colorschemes.com/" target="_blank">Iterm Themes - Color Schemes and Themes for Iterm2</a><br />
あとはコレとか。<br />
僕は Monokai が好きなのでコレで設定した。<br />
<br />
<h4>設定を GitHub の dotfiles リポジトリで複数端末一括管理したい</h4>ハイライト部分がキモ。初回実行時はインストールされてないからエラーでそう。その時考える。<br />
<pre class="brush: shell; first-line: 1; highlight: [11,12,13];" title="https://github.com/wada811/dotfiles/blob/master/dotfilesInstaller.sh">#! /bin/bash
ln -s ~/dotfiles/Brewfile ~/Brewfile
ln -s ~/dotfiles/Settings.terminal ~/Settings.terminal
ln -s ~/dotfiles/.gitconfig ~/.gitconfig
ln -s ~/dotfiles/.gitignore ~/.gitignore
ln -s ~/dotfiles/.sqliterc ~/.sqliterc
ln -s ~/dotfiles/.vim/ ~/.vim
ln -s ~/dotfiles/.vimrc ~/.vimrc
ln -s ~/dotfiles/.zsh/ ~/.zsh
ln -s ~/dotfiles/.zshrc ~/.zshrc
rm ~/Library/Preferences/com.googlecode.iterm2.plist
ln -s ~/dotfiles/.iterm2/com.googlecode.iterm2.plist ~/Library/Preferences/com.googlecode.iterm2.plist
ln -s ~/dotfiles/.iterm2/ ~/.iterm2</pre>Mac のソフトウェアの設定はキャッシュされているので設定を変えたら iTerm2 を再起動しないと設定ファイルには反映されないので注意。<br />
<br />
<h4>おまけ</h4><a href="http://qiita.com/macoshita/items/f7e0f5eda02f45736b52" target="_blank">vim,iTerm2で★とか■とか※とかがずれるのでなんとかした - Qiita</a><br />
"tmux-powerlineのステータスバーがおかしくなる"とかなんとか。<br />
tmux も便利そうなので入れたいが、 iTerm2 に統合されているという話もあり良くわからない。<br />
その件についてはまた今度。wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-23770386669103059742014-09-20T18:23:00.000+09:002014-09-20T18:25:48.301+09:00Mac を Marvericks にアップデートした時にやったこと<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8B0KpL_KLzXN30nLeltbe4pPNbUizGrEgfjpydrFiikaFlQgubdNqp-DJm7oa3b9Pag2uAUv6BZZybNnw8k96sw-lcRTUDtUzph5BY2ofmTRTo7idFuJTnb7tXQf1rukqNytxQOmmq-M/s1600/Apple.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8B0KpL_KLzXN30nLeltbe4pPNbUizGrEgfjpydrFiikaFlQgubdNqp-DJm7oa3b9Pag2uAUv6BZZybNnw8k96sw-lcRTUDtUzph5BY2ofmTRTo7idFuJTnb7tXQf1rukqNytxQOmmq-M/s320/Apple.png" /></a><h4>App Store から Marvericks にアップデート</h4><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><br />
一時停止になったままアップデートされない。<br />
LaunchPad から一時停止しているやつを削除する。<blockquote class="twitter-tweet" lang="ja"><p>LaunchPadから任意アイコンを削除する方法 - Handwriting <a href="http://t.co/HzhPtH0sIg">http://t.co/HzhPtH0sIg</a> Marvericksアプデ始まらないからコレで対応した</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513212599190568962">2014, 9月 20</a></blockquote><br />
バージョンアップできた。<blockquote class="twitter-tweet" lang="ja"><p>Hello, Marvericks!</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513227709825052672">2014, 9月 20</a></blockquote><br />
<h4>Marvericks で問題が起きてないかチェック</h4>Terminal を開いたらすぐに閉じてしまうので設定をいじったら以下の問題が…。<blockquote class="twitter-tweet" lang="ja"><p>Hello, Marvericks! login: /usr/local/bin/zsh: No such file or directory [プロセスが完了しました]</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513234566962626560">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>さて…どうするかな</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513234632699949057">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>なんかアプリケーションとか一部消えてるな…</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513236006921707523">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>brew bundle して Xcode 入れるとこから〜</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513236345284599808">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>機能拡張“/System/Library/Extensions/AppleUSBEthernetHost.kext”は正しくインストールされていないため使用できません。再インストールするか、製品の製造元にアップデートについて問い合わせてください。</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513238868926029824">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Xcode入れたらコレよ…めんどい…</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513238957333549056">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>iTunes 11.4にアップデートした際に「機能拡張AppleUSBEthernetHost.kextが使用できません」というエラーが出てUSBテザリングが使えなくなった時の対処法。 <a href="http://t.co/MYYvQerbRE">http://t.co/MYYvQerbRE</a></p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513239265812033537">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>あぁ…gitを入れる前にhomebrewが更新されてマージコミットされてしまう…</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513240826860666880">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Git 2.0 で pull の Fast-Forward を有効にして Homebrew で update したいじゃん?でも今までの git merge --no-ff でマージコミットしてるせいで失敗するじゃん?困るじゃん? <a href="http://t.co/FTJzydjCh7">http://t.co/FTJzydjCh7</a></p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513241198127882241">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>もう一度コレやらなきゃな</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513241261348642816">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Error: Unknown command: cask になってるからこいつをどうにかするのもやらなくちゃ</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513241676265971712">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>うーん…HomeBrew から入れなおしたほうがいいかもしれんな…;</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513244152478171137">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Uninstall Homebrew <a href="https://t.co/PAymkIriFX">https://t.co/PAymkIriFX</a></p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513244800623992833">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Homebrew — The missing package manager for OS X <a href="http://t.co/cUp5LXIVFd">http://t.co/cUp5LXIVFd</a></p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513245651723763712">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Warning: Your XQuartz (2.7.5) is outdated Please install XQuartz 2.7.6: <a href="https://t.co/HYh5Qx5tqG">https://t.co/HYh5Qx5tqG</a></p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513245990287982593">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Error: No available formula for brew-cask Searching taps... Error: Command failed: L10:brew install brew-cask</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513247253029343232">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>brew-cask がないと思ったら cask に変わってるっぽい</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513247545221320707">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>違うな… Emacs系のツールっぽい</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513247743272185856">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>brew install caskroom/cask/brew-cask</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513249047247724544">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>Error: No available formula for ricty Searching taps... Error: Command failed: L18:brew install ricty</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513249113257684992">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>なんか brew install の指定の仕方が変わったっぽい?</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513249296099975168">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>brew install sanemat/font/ricty</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513250133056978944">2014, 9月 20</a></blockquote><blockquote class="twitter-tweet" lang="ja"><p>ようやくまともに terminal が動くようになったっぽい</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/513254228479860737">2014, 9月 20</a></blockquote><br />
Homebrew-Cask がもしかしたら状態が良くなさそうだけど確認できないので一旦放置。<br />
<br />
<h4>おわり</h4><blockquote class="twitter-tweet" lang="ja"><p>iTerm2を入れてghqを入れてpecoを入れてpecopecoするぞ!</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/512946515233349632">2014, 9月 19</a></blockquote>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-84857940520013924292014-09-20T12:14:00.001+09:002014-09-20T12:14:55.861+09:00Nexus7(2013) を KitKat にバージョンアップするための長い道のり<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb09g-7MtDJS7YlD6aDGX9xl7J8C-HGKy1gu4A19KZy5dDEoxaMtyER1VFIamwn7FFaaHOER-ovzsK-wgcybNF7v07A9b8vYy-Qa8HVobS0XODYUhkshAh5GLa0BzcXrqPnZIswh_S4XY/s1600/android.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb09g-7MtDJS7YlD6aDGX9xl7J8C-HGKy1gu4A19KZy5dDEoxaMtyER1VFIamwn7FFaaHOER-ovzsK-wgcybNF7v07A9b8vYy-Qa8HVobS0XODYUhkshAh5GLa0BzcXrqPnZIswh_S4XY/s320/android.png" /></a>Android 4.4 KitKat が2013年の10月くらいに発表されてな…<br />
<a href="https://developer.android.com/tools/revisions/platforms.html#4.4" target="_blank">Android 4.4 | Platforms | Android Developers</a><br />
<br />
11月の初めに @tao_gaku さんが外部記憶領域とパーミッションまわりの変更について記事を書いてくれてな…<br />
<blockquote class="twitter-tweet" lang="ja"><p>Taosoftware: Android:KitkatのREAD_EXTERNAL_STORAGEと外部記憶領域 <a href="http://t.co/wJRRMHYGUZ">http://t.co/wJRRMHYGUZ</a> 凄くわかりやすく意義のある記事でした!ファイル読み書きに言及するならリンクしておきたい。</p>— @wada811 (@wada811) <a href="https://twitter.com/wada811/status/398465857673637889">2013, 11月 7</a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><br />
<br />
Android 4.3 と Android 4.4 の挙動の変化を見るための<br />
サンプルプロジェクトを作って記事を書こうと決意してな…<br />
<br />
手持ちの Nexus7(2013) の一台しかないから Android 4.3 の挙動を確認したら<br />
Android 4.4 にバージョンアップして挙動を確認して比較する(ただしダウングレードはできない)という<br />
めんどくさそうな感じで放置してな…(今は焼き方を覚えたのでできる)<br />
<br />
そんな感じで放置していたら会社で Nexus7(2013) を手に入れられたので<br />
手持ちの Nexus7(2013) を Android 4.3 で維持しておいて<br />
会社の Nexus7(2013) を Android 4.4 にすることができてな…<br />
<br />
そんなこんなしてたら Android Studio がリリースされてな…<br />
Android Studio で Gradle に productFlavor という便利なものがあってな…<br />
プロジェクト再開して <a href="https://github.com/wada811/Android-StorageReadWriteChecker" target="_blank">wada811/Android-StorageReadWriteChecker</a> ができてな…<br />
<br />
↓この記事を先日やっと書いてな…<br />
<a href="http://wada811.blogspot.com/2014/09/storage-access-and-permission-in-android.html" target="_blank">[Android]KitKatと外部記憶領域とREAD_EXTERNAL_STORAGEとWRITE_EXTERNAL_STRAGEとmaxSdkVersion | DevAchieve</a><br />
<br />
ようやく Nexus7(2013) をアップデートじゃぁああああああああああ!!!!!!!!!!!<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEQ9YJTEiqSrD0F6MdYxp5DEKB6srHMoA91V0enzin9RuhpGkzZk9bStmwEZ9bv7uZChucaw8YN8GH8ggVSVf5S14s8OAnSfCbE4mO_BKhYrAyKkcIUoneFSkxB-6kN3TFo0UECBDdLUs/s1600/Screenshot_2014-09-20-12-11-10.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEQ9YJTEiqSrD0F6MdYxp5DEKB6srHMoA91V0enzin9RuhpGkzZk9bStmwEZ9bv7uZChucaw8YN8GH8ggVSVf5S14s8OAnSfCbE4mO_BKhYrAyKkcIUoneFSkxB-6kN3TFo0UECBDdLUs/s640/Screenshot_2014-09-20-12-11-10.png" /></a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-26949130887962121332014-09-20T11:07:00.001+09:002014-09-20T11:11:22.215+09:00[Android]Google Play アカウント所有者を変更する<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb09g-7MtDJS7YlD6aDGX9xl7J8C-HGKy1gu4A19KZy5dDEoxaMtyER1VFIamwn7FFaaHOER-ovzsK-wgcybNF7v07A9b8vYy-Qa8HVobS0XODYUhkshAh5GLa0BzcXrqPnZIswh_S4XY/s1600/android.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjb09g-7MtDJS7YlD6aDGX9xl7J8C-HGKy1gu4A19KZy5dDEoxaMtyER1VFIamwn7FFaaHOER-ovzsK-wgcybNF7v07A9b8vYy-Qa8HVobS0XODYUhkshAh5GLa0BzcXrqPnZIswh_S4XY/s320/android.png" /></a><p>Google Play アカウント所有者が個人Gmailアカウントに紐付いていて<br />
ユーザーに開発用Gmailアカウントを追加していたのですが、<br />
Google Play アカウント所有者じゃないとできないことがあったので<br />
Google Play アカウント所有者を開発用Gmailアカウントに切り替える手続きをしました。</p><p>移行できれば普段使っている開発用Gmailアカウントで<br />
Google Play Developer Publishing API などを使えるようになるので嬉しいです。</p><br />
<h3><span id="1-1"></span><a href="#1-1"></a>アカウント所有者 と ユーザー の違い</h3><p><a href="https://support.google.com/googleplay/android-developer/answer/2528691?hl=ja&ref_topic=16285" title="" target="_blank">アカウント ユーザーの追加と権限の管理 - Android デベロッパー ヘルプ</a></p><table><thead>
<tr><th>タイプ</th><th>アクセス</th></tr>
</thead><tbody>
<tr><td>アカウント所有者</td><td></td></tr>
<tr><td></td><td>デベロッパー コンソールにフルアクセスできる</td></tr>
<tr><td></td><td>新しいユーザーの招待、ユーザーのデベロッパー コンソールへのアクセスの取り消し、各ユーザーの権限の設定を行うことができる</td></tr>
<tr><td></td><td>有料アプリを販売するため、関連付けられた Google ウォレット Merchant アカウントを所有できる(アカウント所有者のみ)</td></tr>
<tr><td>ユーザー</td><td></td></tr>
<tr><td></td><td>デベロッパー コンソールにさまざまなレベルでアクセスできる</td></tr>
<tr><td></td><td>すべてまたは指定のアプリにアクセスできる</td></tr>
<tr><td></td><td>新しいユーザーの招待やユーザーの権限の編集はできない</td></tr>
</tbody></table><br />
<h3><span id="1-2"></span><a href="#1-2"></a>Google Play アカウント所有者を変更する</h3><p>手順は以下のとおり。</p><ul><li>Google サポートチームに連絡し、アプリを別のアカウントに移行します。</li>
<li>アプリの移行の確認に返信し、既存のアカウントを閉鎖します。</li>
</ul><p><a href="https://support.google.com/googleplay/android-developer/answer/139626?hl=ja" title="" target="_blank">アカウント情報の変更または更新 - Android デベロッパー ヘルプ</a></p><br />
<h3><span id="1-3"></span><a href="#1-3"></a>Google Play アカウントを移行する</h3><p>普通だったら以下の対応だけでOK!</p><ul><li>新しい Google Play アカウントを登録する</li>
<li>新しい Google Wallet アカウントを登録して紐付ける</li>
<li>アプリ移行リクエストを送る </li>
</ul><p><a href="https://support.google.com/googleplay/android-developer/checklist/3294213" title="" target="_blank">アプリを移行する - Android デベロッパー ヘルプ</a><br />
<a href="https://support.google.com/googleplay/android-developer/contact/appt" title="" target="_blank">アプリ移行リクエスト - Android デベロッパー ヘルプ</a></p><p><strong>アプリの収益を受け取るための Google Wallet のお支払い設定を忘れないようにしましょう!</strong></p><br />
<h3><span id="1-4"></span><a href="#1-4"></a>デベロッパー アカウントの解約</h3><p>2,3営業日待てば移行もされるし、<br />
Google Wallet のデポジットも振り込まれてお支払い設定完了できるだろうから<br />
すべてが終わったら移行元の Google Play アカウントを解約しましょう!</p><p>登録料の25ドルが返ってくるらしいです。<br />
<a href="https://support.google.com/googleplay/android-developer/answer/139626?hl=ja" title="" target="_blank">アカウント情報の変更または更新 - Android デベロッパー ヘルプ</a></p>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.comtag:blogger.com,1999:blog-3960362825413961838.post-61305676678342435692014-09-19T20:00:00.000+09:002014-09-20T09:53:39.892+09:00[Android]KitKatと外部記憶領域とREAD_EXTERNAL_STORAGEとWRITE_EXTERNAL_STRAGEとmaxSdkVersion<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s1600/android.png" imageanchor="1" ><img class="right" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjY4tcDbG0bfQ5OjAJI_ZLr9aqF7C8eme9m31469Lni0BVfnusPDWFKgM-opQLvyUvG9rf8KlysQNAt68UfxL7TYLSgaAnvF6t2FM41SfgENmP1OJudcQGDJcJGT7QYFrRSt9wZQxz9VI/s320/android.png" /></a>KitKat で外部記憶領域の読み書きに関するパーミッションに変更がありました。<br />
また、READ_EXTERNAL_STORAGE パーミッションも正式対応となりました。<br />
<br />
この変更についてまとめたいと思います。<br />
まずは言葉の説明から。<br />
<br />
<h4>外部記憶領域(primary external storage)</h4>以前は外部記憶領域といえば SD カード(外部ストレージ、外部SDなどと呼ばれる)のことを指しましたが、<br />
最近はストレージ内部の仮想的な記憶領域(内部ストレージ、内部SDなどと呼ばれる)のことを主に指します。<br />
そのため、内部ストレージと呼ばれるのに外部記憶領域であり、<br />
READ_EXTERNAL_STORAGE や WRITE_EXTERNAL_STRAGE が必要となるという少々混乱する状況でした。<br />
(<a href="http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()" target="_blank">Environment#getExternalStorageDirectory()</a>が内部SDを返すようになったり)<br />
primary external storage などについては以下のサイトを読んでください。<br />
<a href="http://source.android.com/devices/tech/storage/index.html" target="_blank">External Storage Technical Information | Android Developers</a><br />
<br />
<h4>KitKat での変更</h4>KitKat からは EXTERNAL_STORAGE パーミッションの対象ディレクトリが変更となり、<br />
外部記憶領域上のアプリケーションデータ領域はパーミッションが不要となりました。<br />
アプリケーションデータ領域の外部については EXTERNAL_STORAGE パーミッションが必要となっています。<br />
<br />
<h4>アプリケーションデータ領域</h4><dl><dt>本体メモリのアプリケーションデータ領域(アプリ内領域などと呼ばれる)</dt>
<dd>/data/data/<パッケージ名>/</dd>
<dt>外部記憶領域上のアプリケーションデータ領域</dt>
<dd>/<外部記憶領域>/Android/data/<パッケージ名></dd> </dl><br />
<h4>本題</h4>READ_EXTERNAL_STORAGE と WRITE_EXTERNAL_STRAGE が必要なのは<br />
どのディレクトリなのか、どのメソッドなのか調べました。<br />
<br />
<a href="https://github.com/wada811/Android-StorageReadWriteChecker" target="_blank">wada811/Android-StorageReadWriteChecker</a><br />
<table><tr><th>BuildVariants と パーミッション</th><th>READ_EXTERNAL_STORAGE</th><th>WRITE_EXTERNAL_STRAGE</th></tr>
<tr><td>PreKitKat</td><td></td><td></td></tr>
<tr><td>PreKitKatRead</td><td>○</td><td></td></tr>
<tr><td>PreKitKatWrite</td><td></td><td>○</td></tr>
<tr><td>PreKitKatReadWrite</td><td>○</td><td>○</td></tr>
<tr><td>KitKat</td><td></td><td></td></tr>
<tr><td>KitKatRead</td><td>○</td><td></td></tr>
<tr><td>KitKatWrite</td><td></td><td>○</td></tr>
<tr><td>KitKatReadWrite</td><td>○</td><td>○</td></tr>
<tr><td>KitKatWriteCompat</td><td></td><td>○(maxSdkVersion="18")</td></tr>
<tr><td>KitKatReadWriteCompat</td><td>○</td><td>○(maxSdkVersion="18")</td></tr>
</table>データ:<a href="http://qiita.com/wada811/items/ba0404725b056409e1cb" target="_blank">Android - KitKatと外部記憶領域とREAD_EXTERNAL_STORAGEとWRITE_EXTERNAL_STRAGEとmaxSdkVersion - Qiita</a><br />
<br />
<h4>結果</h4><a href="http://qiita.com/wada811/items/ba0404725b056409e1cb#1-1" target="_blank">PreKitKat</a> と <a href="http://qiita.com/wada811/items/ba0404725b056409e1cb#1-5" target="_blank">KitKat</a> の結果から<br />
getExternalCacheDir と getExternalFilesDir で取得できる外部記憶領域上のアプリケーションデータ領域は<br />
KitKat からパーミッションなしでも読み書き可能であることが確認できます。<br />
<br />
READ_EXTERNAL_STORAGE が正式対応となったため<br />
KitKat 以降で READ_EXTERNAL_STORAGE なしでは<br />
Environment.getExternalStorageDirectory で取得できる外部記憶領域は<br />
読み込みできないことが確認できます。(<a href="http://qiita.com/wada811/items/ba0404725b056409e1cb#1-1" target="_blank">PreKitKat</a> と <a href="http://qiita.com/wada811/items/ba0404725b056409e1cb#1-5" target="_blank">KitKat</a>)<br />
<a href="http://qiita.com/wada811/items/ba0404725b056409e1cb#1-6" target="_blank">KitKatRead</a> から READ_EXTERNAL_STORAGE があれば<br />
外部記憶領域の読み込みができることが確認できますね。<br />
<br />
<h4>本題の本題</h4>さて、getExternal~Dir で取得できる外部記憶領域上のアプリケーションデータ領域は<br />
KitKat からパーミッションなしでも読み書き可能ということが確認できましたが、<br />
PreKitKat ではパーミッションが必要です。<br />
KitKat では必要でないパーミッションを PreKitKat のために宣言すると<br />
KitKat ユーザーに対して不要なパーミッションを取得することになります。<br />
結局パーミッションは減らせないのかとなりそうですが、<br />
KitKat で追加された Uses-Permission の maxSdkVersion 属性によって対応が可能です。<br />
<br />
以下のように記述することで PreKitKat では WRITE_EXTERNAL_STORAGE を宣言し、KitKat ではパーミッションを宣言しないことができます。<br />
<pre class="brush: xml; first-line: 1; highlight: [,];" title=""><uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" /></pre>アプリ情報画面のパーミッションの欄を見ると PreKitKat では WRITE_EXTERNAL_STORAGE があり、<br />
KitKat では WRITE_EXTERNAL_STORAGE はないことがわかります。<br />
<table><tr> <td></td> <th>KitKatWriteCompat</th> <th>KitKatReadWriteCompat</th> </tr>
<tr> <th>PreKitKat</th> <td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPkS2PKmb01BkA_AzEIkUA5AurbuJRf-SKlWwKfwaEL9-pyMO4W3efbj1ZyzgjaIoT7ajyiqbzw-u6LvyZBNhMFg1TuGvtpDmsUmZ6spBUOv5wy6TzwPIIvusFMo9n8EkwqupMADWfGQg/s1600/SRWC_WC_PreKitKat.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPkS2PKmb01BkA_AzEIkUA5AurbuJRf-SKlWwKfwaEL9-pyMO4W3efbj1ZyzgjaIoT7ajyiqbzw-u6LvyZBNhMFg1TuGvtpDmsUmZ6spBUOv5wy6TzwPIIvusFMo9n8EkwqupMADWfGQg/s320/SRWC_WC_PreKitKat.png" /></a></td> <td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoVAaNyrmHOrgbE8gjZG-xEAOIV_Be8dC1y-rURFcu1YSKly8drs7p_2vIF8BkOtZeK0HsjBR60aqnnuF8t8KEyzmkAXs7keTvXly1FITmzpF_eI230n2rZN42NV-VULFKf7LvmJVkRc4/s1600/SRWC_RWC_PreKitKat.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoVAaNyrmHOrgbE8gjZG-xEAOIV_Be8dC1y-rURFcu1YSKly8drs7p_2vIF8BkOtZeK0HsjBR60aqnnuF8t8KEyzmkAXs7keTvXly1FITmzpF_eI230n2rZN42NV-VULFKf7LvmJVkRc4/s320/SRWC_RWC_PreKitKat.png" /></a></td> </tr>
<tr> <th>KitKat</th> <td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZAaJxqtA7aMwfRlylsn4lLXV3ECeH6bUYqslNuWc1juwO2_cLDyfNqCR9taImhWMpK9eaMZR4bGh_tZh2GMjuSts5sfz2aOCxxNYoNEtPvcmgoBfljxsOzZ4wxe3hcm0d-_g0mu_8JVA/s1600/SRWC_WC_KitKat.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZAaJxqtA7aMwfRlylsn4lLXV3ECeH6bUYqslNuWc1juwO2_cLDyfNqCR9taImhWMpK9eaMZR4bGh_tZh2GMjuSts5sfz2aOCxxNYoNEtPvcmgoBfljxsOzZ4wxe3hcm0d-_g0mu_8JVA/s320/SRWC_WC_KitKat.png" /></a></td> <td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPAl0UUzMNtn_bS3oqi9LALS9q0eXU5tk9frxb5sMYZWN0GdgcvN00nVKrn6J2bLPUWHfYPCDl9y9-Dv474VZUIzFhHgVOt-6I0rCkNxXEEA8z7NKalNGFzD6zSoyqEARou46Kh5DAr0A/s1600/SRWC_RWC_KitKat.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPAl0UUzMNtn_bS3oqi9LALS9q0eXU5tk9frxb5sMYZWN0GdgcvN00nVKrn6J2bLPUWHfYPCDl9y9-Dv474VZUIzFhHgVOt-6I0rCkNxXEEA8z7NKalNGFzD6zSoyqEARou46Kh5DAr0A/s320/SRWC_RWC_KitKat.png" /></a></td> </tr>
</table><br />
<h3 id="tl;dr">結論</h3><ul><li>Environment への書き込みがあるなら WRITE_EXTERNAL_STORAGE が必要</li>
<li>getExternal~Dir への書き込みだけなら WRITE_EXTERNAL_STORAGE に maxSdkVersion="18" を付けておく</li>
<li>外部記憶領域への読み込みがあるなら READ_EXTERNAL_STORAGE が必要</li>
</ul><br />
<h3>参考</h3><a href="https://developer.android.com/about/versions/android-4.4.html#UserContent" target="_blank">External storage access | Android 4.4 APIs | Android Developers</a><br />
<a href="http://www.taosoftware.co.jp/blog/2013/11/androidkitkatread_external_sto.html" target="_blank">Android:KitkatのREAD_EXTERNAL_STORAGEと外部記憶領域 | Taosoftware</a><br />
<a href="http://www.taosoftware.co.jp/blog/2014/04/write_external_stragemaxsdkver.html" target="_blank">WRITE_EXTERNAL_STRAGEと下位互換のためのmaxSdkVersion | Taosoftware</a>wada811http://www.blogger.com/profile/02677315417874740351noreply@blogger.com