2013年8月25日日曜日

mvn eclipse:eclipseでソースコードとJavadocをダウンロードしてくれるsettings.xml

mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
ってやるとEclipseプロジェクトファイルを作ってくれるのと同時に依存ライブラリのソースコードとJavadocをダウンロードしてくれるんだけど、-DdownloadSources=true -DdownloadJavadocs=trueって毎回書くのはめんどい。
コマンドのエイリアス作ったり、pom.xmlに書いたりすれば解決するけど、なんとなくどちらも気持ち悪かったので、 settings.xmlに記載したった。


これで以下のコマンドを打つだけでソースコードとJavadocをダウンロードしてくれるはず!
mvn eclipse:eclipse

2013年8月11日日曜日

ListAdapterのgetViewが呼び出される階層を調べてみた

ListViewを継承して独自のカスタムViewを作ろうとしてた時に必要になったので、 ListAdapterのgetViewが呼び出される階層を調べてみた。
android.widget.ListAdapter#getView
↑
android.widget.AbsListView#obtainView
↑
android.widget.ListView#makeAndAddView
↑
android.widget.ListView#fillDown
↑
android.widget.ListView#fillGap
↑
android.widget.AbsListView#trackMotionScroll
↑
android.widget.AbsListView#scrollIfNeeded
↑
android.widget.AbsListView#onTouchEvent
まだ続いてるけどここまでわかればOKでしょ。 ちなみにこれ4.2.2の挙動ね。

2013年6月8日土曜日

githubをMavenリポジトリとしてAndroidライブラリプロジェクト(aar)をデプロイして使用する

序章

Android StudioとGradleのビルドシステム(Plugin)が正式にリリースされ、個人的に気になっていたAndroidライブラリプロジェクトの扱いについて調べてみた。新しいGradleのビルドシステムではライブラリプロジェクトはaar(Android archive)という1つのアーカイブで配布することが可能になった。aarファイルは拡張子によって判別され、フォーマットはzip形式である。(aarファイルについての詳細はまた今度。)従来はライブラリプロジェクトを使用するためにプロジェクト一式が必要だったけど、1つのアーカイブを参照するだけで使用出来るようになるので再利用しやすくなったってこと。

※ちなみにこれまでもandroid-maven-pluginというサードパーティ製のプラグインを使用することで解決されてきたのだけど、個人的には正式にサポートされたというのが大きい。

現時点ではビルドシステムのソースコードを見る限り、aarを参照する方法は"External module dependencies"タイプしかサポートされていない。これはどこかのリポジトリに配置されたモジュールを参照するということ。Gradleでは様々なリポジトリ形式に対応しているので、それらの形式(MavenとかIvyとか)でaarをデプロイする必要がある。

注意したいのはただ単にローカルファイルシステム上に配置されたaarを参照出来ないという点である。以下はNGパターン。

dependencies {
    compile files('path/to/some/a.aar', 'path/to/some/b.aar')
    compile fileTree(dir: 'path/to/some', include: '*.aar')
}

GradleでもMavenリポジトリ形式が一般的っぽいのでとりあえずaarをMavenリポジトリ形式でgithubにアップロードして使用出来るか試してみた。結果何事もなく出来たので手順を公開しておく。

環境

  • Android Studio 0.1.1
  • Mac OS X 10.8.3

デプロイ編

まずはAndroid Studioを使用して新規プロジェクトを作成する。こんな感じ。Eclipseユーザーにはわかりづらいかもしれないけど、Android Studioで新規プロジェクトを作成する場合はプロジェクト=アプリではなく、モジュール=アプリとなる。つまり、1つのプロジェクト内にライブラリモジュールや本体アプリモジュール、テストアプリモジュールを配置していくことになる。慣れればこっちのがわかりやいかもね。ちなみにEclipseでbuild.gradleファイルをエクスポートしてAndroid Studioでインポートする場合は上記の通りではない。

ナビ通り進めていくと以下のようなbuild.gradleを含んだプロジェクトが作成される。

現時点でのAndroid Studioは「Mark this project as a library」にチェックを入れてもライブラリプロジェクトとして扱ってくれないらしい。。なので手動で修正。(ソースコードを見る限りそのうち直ると思う。)

apply plugin: 'android'

の箇所を以下に変更。

apply plugin: 'android-library'

試しにaarが作成されるか、ターミナルを起動してビルドしてみる。aarはデバッグ版はassembleDebug、リリース版はassembleReleaseのGradleタスクで作成される。プロジェクト配下で以下のコマンドを実行。

$ cd <project_home>
$ ./gradlew assembleRelease

以下ファイルが生成されていればOK。

$ find . -name '*.aar'
./library/build/libs/library.aar

続いて、Mavenプラグインを使用してMavenリポジトリ形式でデプロイするためlibrary/build.gradleに追記する。Mavenプラグインについてはここを参照。

// プロジェクトルート配下のrepositoryディレクトリにデプロイする
def deployTo = new File(rootDir, "repository")

// Mavenプラグインの利用を宣言
apply plugin: 'maven'

uploadArchives {
    repositories {
        mavenDeployer {
            repository url: "file://${repos.absolutePath}" // デプロイ先
            pom.version = '0.0.1' // ライブラリバージョン
            pom.groupId = 'com.u1aryz' // グループ名
            pom.artifactId = 'sample-lib' // アーティファクト名
        }
    }
}

ターミナルに移ってプロジェクト配下で以下のコマンドを実行。

$ ./gradlew uploadArchives

プロジェクト配下のrepositoryディレクトリに以下のようにファイル群が出来ていれば成功。

$ ls -laR repository
total 0
drwxr-xr-x   3 u1aryz  staff  102  6  1 02:01 .
drwxr-xr-x  18 u1aryz  staff  612  6  1 02:01 ..
drwxr-xr-x   3 u1aryz  staff  102  6  1 02:01 com

repository/com:
total 0
drwxr-xr-x  3 u1aryz  staff  102  6  1 02:01 .
drwxr-xr-x  3 u1aryz  staff  102  6  1 02:01 ..
drwxr-xr-x  3 u1aryz  staff  102  6  1 02:01 u1aryz

repository/com/u1aryz:
total 0
drwxr-xr-x  3 u1aryz  staff  102  6  1 02:01 .
drwxr-xr-x  3 u1aryz  staff  102  6  1 02:01 ..
drwxr-xr-x  6 u1aryz  staff  204  6  1 02:01 sample-lib

repository/com/u1aryz/sample-lib:
total 24
drwxr-xr-x  6 u1aryz  staff  204  6  1 02:01 .
drwxr-xr-x  3 u1aryz  staff  102  6  1 02:01 ..
drwxr-xr-x  8 u1aryz  staff  272  6  1 02:01 0.0.1
-rw-r--r--  1 u1aryz  staff  298  6  1 02:09 maven-metadata.xml
-rw-r--r--  1 u1aryz  staff   32  6  1 02:09 maven-metadata.xml.md5
-rw-r--r--  1 u1aryz  staff   40  6  1 02:09 maven-metadata.xml.sha1

repository/com/u1aryz/sample-lib/0.0.1:
total 936
drwxr-xr-x  8 u1aryz  staff     272  6  1 02:01 .
drwxr-xr-x  6 u1aryz  staff     204  6  1 02:01 ..
-rw-r--r--  1 u1aryz  staff  457944  6  1 02:09 sample-lib-0.0.1.aar
-rw-r--r--  1 u1aryz  staff      32  6  1 02:09 sample-lib-0.0.1.aar.md5
-rw-r--r--  1 u1aryz  staff      40  6  1 02:09 sample-lib-0.0.1.aar.sha1
-rw-r--r--  1 u1aryz  staff     422  6  1 02:09 sample-lib-0.0.1.pom
-rw-r--r--  1 u1aryz  staff      32  6  1 02:09 sample-lib-0.0.1.pom.md5
-rw-r--r--  1 u1aryz  staff      40  6  1 02:09 sample-lib-0.0.1.pom.sha1

このファイル群を構成そのままでまるまるgh-pagesブランチにコミットしてgithubにプッシュする。以下のようになっていればOK。

ここまで手順通りに進んでいれば以下の記述をbuild.gradleに追記するだけでaarを参照することが出来る。

repositories {
    maven { url 'http://<githubユーザー名>.github.com/<githubリポジトリ名>/repository' }
}

dependencies {
    compile 'com.u1aryz:sample-lib:0.0.1'
}

※Mavenリポジトリと言ってもただのファイル群なので、プロジェクト配下でなくてもいいけど、その場合はmavenのurlは変わる。

ビルド編

今度はgithubにデプロイしたライブラリプロジェクトを参照してビルドしてみる。自分でデプロイしたものを参照したい場合は適宜読み替えて。ここでは俺がデプロイしたやつを使用するでよ。

新規プロジェクトを作成してもいいけど、めんどいのでさっき作成したSampleLibraryプロジェクトにAndroid Applicationモジュールを追加する。

  • Android StudioでFile -> New Module…を選択
  • Android Applicationを選択してNext

ナビ通り進めて作成されたmainモジュールのbuild.gradleにrepositoriesとdependenciesを追記する。

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}

// 追記
repositories {
    maven { url 'http://u1aryz.github.com/Android-NewPopupMenu/repository/release' }
}

apply plugin: 'android'

dependencies {
    compile files('libs/android-support-v4.jar')
    compile 'com.u1aryz:android-newpopupmenu-lib:1.0.1' // 追記
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 16
    }
}

プロジェクトを開き直すとAndroid Studioがbuild.gradleを読みなおして以下のようにExternal Librariesに追加されているはずや。(これはちょっとめんどい)

あとは今まで通りライブラリプロジェクトを使用出来る。

終章

自分で手を入れる必要のないライブラリプロジェクトを使用したい場合は、この方法のがスマートだね。例えば、ActionBarSherlockとかを使用したい場合とか。ちなみにActionBarSherlockは4.3.2でGradle対応するのでmavenCentralにアップされるのが待ち遠しいね〜。

2013年5月25日土曜日

Android StudioでRecent Projectのリストをクリアする

Android Studioでいろいろ触りまくっているとRecent Projectがいっぱいになってすごい邪魔になる。IntelliJだとRecent Projectをクリアするメニューがあるんだけど、Android Studioだと見つからなかった。なので、無理やりRecent Projectをクリアする方法をメモ。基本的にはIntelliJで無理やりやる方法と一緒。ちなみにMacね。

以下のファイルを開く
/Users/<username>/Library/Preferences/AndroidStudioPreview/options/other.xml

んで以下のあたりのrecentPathsのlistの中身を消す。
  1. <component name="RecentProjectsManager">  
  2.   <option name="recentPaths">  
  3.     <list>  
  4.       <option value="$USER_HOME$/AndroidStudioProjects/SampleUseLibrary" />  
  5.     </list>  
  6.   </option>  
  7.   <option name="names">  
  8.     <map>  
  9.       <entry key="$USER_HOME$/AndroidStudioProjects/SampleUseLibrary" value="" />  
  10.       <entry key="$USER_HOME$/dev/github/ActionBarSherlock/actionbarsherlock-samples/fragments" value="" />  
  11.     </map>  
  12.   </option>  
  13.   <option name="lastPath" value="$USER_HOME$/AndroidStudioProjects/SampleUseLibrary" />  
  14. </component>  

以下が修正後。
  1. <component name="RecentProjectsManager">  
  2.   <option name="recentPaths">  
  3.     <list>  
  4.     </list>  
  5.   </option>  
  6.   <option name="names">  
  7.     <map>  
  8.       <entry key="$USER_HOME$/AndroidStudioProjects/SampleUseLibrary" value="" />  
  9.       <entry key="$USER_HOME$/dev/github/ActionBarSherlock/actionbarsherlock-samples/fragments" value="" />  
  10.     </map>  
  11.   </option>  
  12.   <option name="lastPath" value="$USER_HOME$/AndroidStudioProjects/SampleUseLibrary" />  
  13. </component>  

2013年1月3日木曜日

Androidで「Unknown error merging manifest」

AndroidでライブラリプロジェクトのAndroidManifest.xmlをメインプロジェクトに自動でマージさせるにはproject.propertiesにmanifestmerger.enabled=trueを加えるだけで良い。 しかし、メインプロジェクトのandroid:targetSdkVersionがライブラリプロジェクトより低いと以下のようなエラーメッセージが表示される。
Unknown error merging manifest
もっとわかりやすいメッセージを表示してほしいよね。

2013年1月2日水曜日

GradleでSlim3 + JPPのビルドスクリプトを書いてみた

Android(アプリ)も新しいビルドシステムとしてGradleを採用したこともあって、流行りに流行りまくっているGradleを試してみた。とりあえず会社でよく使うSlim3 + JsonPullParserのビルドスクリプトを書いてみた。

Gradleでaptを処理する場合はAntタスクを使うらしい。そんでもってSlim3はJava1.5のaptでJPPはJava1.6のaptを使う必要があるらしいので、これまためんどい。

apply plugin: "java"
sourceCompatibility = 1.6
targetCompatibility = 1.6
buildDir = "target"
def slim3Version = "1.0.+"
def appengineVersion = "1.7.+"
def jppVersion = "1.5.+"
repositories {
mavenCentral()
maven {
url "https://www.seasar.org/maven/maven2"
}
}
configurations {
providedCompile // <scope>provided</scope>
aptCompile5 // 1.5
aptCompile6 // 1.6
}
sourceSets {
apt_generated
main.compileClasspath += configurations.providedCompile
test.compileClasspath += configurations.providedCompile
test.runtimeClasspath += configurations.providedCompile
}
dependencies {
compile("org.slim3:slim3:${slim3Version}") {
exclude group: "com.google.appengine", module: "appengine-api-1.0-sdk"
exclude group: "com.google.appengine", module: "appengine-api-labs"
}
compile "com.google.appengine:appengine-api-1.0-sdk:${appengineVersion}"
compile "com.google.appengine:appengine-api-labs:${appengineVersion}"
compile "net.vvakame:jsonpullparser-core:${jppVersion}"
providedCompile "javax.servlet:servlet-api:2.5"
aptCompile5("org.slim3:slim3-gen:${slim3Version}") {
exclude group: "org.apache.ant", module: "ant"
}
aptCompile6 "net.vvakame:jsonpullparser-apt:${jppVersion}"
testCompile "junit:junit:4.7"
testCompile "com.google.appengine:appengine-api-stubs:${appengineVersion}"
testCompile "com.google.appengine:appengine-testing:${appengineVersion}"
}
task clean(overwrite: true) {
ant.delete(dir: buildDir)
}
task compileAptJava(overwrite: true, dependsOn: clean) {
// 生成コードを出力するディレクトリを予め作成
// sourceSets.apt_generated.output.resourcesDir.mkdir() // なぜか出来ない
ant.mkdir(dir: sourceSets.apt_generated.output.resourcesDir)
// apt 1.5
ant.path(id: "aptFactoryPath", location: configurations.aptCompile5.asPath)
ant.apt(
compile: false,
includeAntRuntime: false,
srcdir: "src/main/java",
factorypathref: "aptFactoryPath",
classpath: configurations.compile.asPath,
preprocessdir: sourceSets.apt_generated.output.resourcesDir,
encoding: "UTF-8"
) {
sourceSets.main.java.srcDirs.each {
src(path: it)
}
}
// apt 1.6
ant.javac(
includeAntRuntime: false,
classpath: configurations.compile.asPath,
srcdir: "src/main/java",
encoding: "UTF-8"
) {
compilerarg(line: "-proc:only")
compilerarg(line: "-processorpath ${configurations.aptCompile6.asPath}")
compilerarg(line: "-s ${sourceSets.apt_generated.output.resourcesDir}")
}
// 自動生成コードが入ったディレクトリをソースディレクトリとして追加する
sourceSets.main.java.srcDirs += sourceSets.apt_generated.output.resourcesDir
}
// compileJavaタスクの前にcompileAptJavaタスクを実行させる
compileJava.dependsOn compileAptJava
view raw build.gradle hosted with ❤ by GitHub
実はこれ、javacのバグによってエラーメッセージが誤って報告されるので気持ち悪い。
もっと良い方法があったら誰か教えて(´・ω・`)

参考資料)

2012年6月3日日曜日

さくらVPSのUbuntu10.04(64bit)にgitolite(g3)をインストール

Ubuntu11ならaptitudeで簡単にインストール出来るみたいだけど、
Ubuntu10.04の場合、アレコレちょっとめんどかったのでインストールログを残しておくことにした。
(それとg3のインストール方法を紹介している日本語のサイトがなかったという理由も)

git-coreのインストール


$ sudo apt-get install git-core

セットアップ準備


1人目のgitolite管理者ユーザーの鍵を予め作成しておく。
$ ssh-keygen -t rsa

gitoliteユーザーを作成する。
$ sudo adduser gitolite

gitoliteユーザーから参照出来る場所に公開鍵を配置する。(あとで削除してね)
$ cp -p .ssh/id_rsa.pub /tmp/ubuntu.pub

gitoliteのインストール / セットアップ


gitoliteユーザーで行う。
$ sudo su - gitolite

githubからクローン
$ git clone git://github.com/sitaramc/gitolite

gitoliteインストール
$ gitolite/install

gitoliteのセットアップを行う。(WARNING出るけど気にしない)
$ export PATH=$HOME/gitolite/src:$PATH
$ gitolite setup -pk /tmp/ubuntu.pub
$ exit

管理用リポジトリをクローン


セットアップ時に指定した公開鍵のユーザーで管理用リポジトリをクローンする。
 (ここでは同サーバなのでlocalhost)
$ git clone gitolite@localhost:gitolite-admin.git

リポジトリを追加する場合はgitolite-admin/conf/gitolite.conf にrepoを追加してプッシュするだけ。 
ユーザーを追加する場合はgitolite-admin/keydir配下に公開鍵を 追加してプッシュするだけ。 
これでリポジトリを追加する作業がgitosisより楽になったー