読者です 読者をやめる 読者になる 読者になる

Android Studio で ABSにチャレンジしてみた

android IDEA AS gradle

id:sos_jp さんが GooglePlayService版書いてくれましたー。
すごい感謝です!こういうノウハウは貯まるといいですよねー

でもこれ読んでて build.gradleの存在忘れてたよ。。。(汗 *1

明日から使えるgradle
で情報一度まとめてたのにな。。。(汗



しらべる経緯的にはこんな感じ)

状況的には

  • イベント着火的には
  • actionbarshaloc/pom.xml
    • MavenProject
      • ActionBarshalock::Lifecycle
      • compile(Before Make) //本体がmakeする前にコンパイルが走る

で本体側で実行=>エラー。

appt 等のパスが変わったからのようです

PATH=$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/17.0.0:$PATH

と.bash_profileに追加してみても効果がないようです(IDEA側で設定をしないと駄目な感じなのかな?)
と思ってコンソールから実行はしてみましたが

ERROR] Failed to execute goal com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.5.3:generate-sources (default-generate-sources) on project actionbarsherlock: Execution default-generate-sources of goal com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.5.3:generate-sources failed: Could not find tool 'aapt'. Please provide a proper Android SDK directory path as configuration parameter <sdk><path>...</path></sdk> in the plugin <configuration/>. As an alternative, you may add the parameter to commandline: -Dandroid.sdk.path=... or set environment variable ANDROID_HOME. -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException

iMac-No5:actionbarsherlock_m $ which aapt
/Users/XXXX/android-sdks/build-tools/17.0.0/aapt

android maven plugin側の問題のようです*2

 でもASまだPreviewだし、IDEA12&Androidで頑張りたいよ〜
という場合はシンボリックリンク貼って凌ぎましょうで対処可能のよう。

cd $ANDROID_HOME/platform-tools
ln -s ../build-tools/17.0.0/aapt aapt
ln -s ../build-tools/17.0.0/aidl aidl
ln -s ../build-tools/17.0.0/lib lib

追記)

cd $ANDROID_HOME/platform-tools
ln -s ../build-tools/18.0.1/aapt aapt
ln -s ../build-tools/18.0.1/aidl aidl
ln -s ../build-tools/18.0.1/lib lib

に変更も現在できるけど、renderscriptが更新失敗したそうで
その人は17のまま使ってね って話があるよう
(18 => 18.0.1は一応renderscript直した版らしい)

http://twitter.com/kimukou2628/status/338600730632015872:twitter:detail:right


あと環境によっては下記の対処も必要らしい

やっぱりIDEAの環境構築や設定凄く難しい><



試した手順)

構成的にはこんな想定

  • abstest
    • ASで作った通常プロジェクト
  • actionbarsherlock
    • 普通のeclipse android project型
    • ec-exportタイプの build.gradle を追加します
    • ローカルにgradle自体がない場合は、abtestあたりから下記の3ファイルをコピーします
      • gradleフォルダ
      • gradlew
      • gradlew.bat
  • lib_yutori
    • ASで作ったLibraryプロジェクト
  • プロジェクトを新規作成(abstest)してから、

いつも通りモニョモニョいじっていきます

  • abstest/build.gradle
repositories {
   mavenCentral()
}
apply plugin: 'idea'

プロジェクトファイルを作り直したい時用。
慣れてないとよく変な構成(いわゆる壊れた状態)になるので、記述しておくと楽

./gradlew idea 

で実行します

実行前に直下の

  • .iml
  • .ideaフォルダ

等を消しておくこと

一応
 ProjectStructure => NewModule で作りませう。
って話があるんだけど
GradleModuleの指定がないので
 Import Module =>Gradle Porject
で手動補完してくイメージ?

  • abstest/settings.gradle
include ':abstest'

library_name=':abs'
//include library_name
includeFlat library_name //仮想パス

lib_prg = project(library_name);
lib_prg.projectDir=new File(settingsDir,'../actionbarsherlock')
println "[name]=" + lib_prg.name
println "[dir ]=" + lib_prg.projectDir

library_name2=':yutori'
//include library_name2
includeFlat library_name2 //仮想パス

lib_prg = project(library_name2);
lib_prg.projectDir=new File(settingsDir,'../lib_yutori/lib_yutori')
println "[name]=" + lib_prg.name
println "[dir ]=" + lib_prg.projectDir
  • abstest/abstest/build.gradle
buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
apply plugin: 'android'

dependencies {
    //compile files('libs/android-support-v4.jar')
    compile fileTree(dir: 'libs', includes: ['*.jar'])
    compile project(':abs')
    compile project(':yutori')
//    compile project( library_name  as String) //◎◎
//    compile project( library_name2 as String)//◎◎
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 4
        targetSdkVersion 17
    }
}

◎◎は出来んかった。。。 settings.gradle が走る前の段階で
dependenciesが参照されてしまうよう・・・


備考)
環境により文字コード等引っかかってビルドできない場合は

  1. gradle.propertiesを作成
  2. 環境変数を設定(JAVA_OPTS/_JAVA_OPTION)
  3. android DSLをいじる

1)の例

  • abstest/gradle.properties
systemProp.ANDROID_HOME=/Application/android-sdks
systemProp.JAVA_OPTS=-Dgroovy.source.encoding=UTF-8 -Dfile.encoding=UTF-8

2)の例

  • $HOME/.bash_profile
export JAVA_OPTS='-Dgroovy.source.encoding=UTF-8 -Dfile.encoding=UTF-8'
export _JAVA_OPTIONS='-Dfile.encoding=UTF-8 -Dgroovy.source.encoding=UTF-8'

3)の例
android DSLでCompileタスクの方に強制。これallProjectタスクでさすがに書けないんだろうな。。。
templateをいじるべきか(汗

  • build.gradle
android{

    tasks.withType(Compile) {
        options.encoding = 'UTF-8' 
    }
}


ライブラリプロジェクト側>

  • actionbarsherlock/build.gradle
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}

apply plugin: 'android-library'

dependencies {
	compile fileTree(dir: 'libs', includes: ['*.jar'])
}

android {
    compileSdkVersion 17
    buildToolsVersion "17"

    defaultConfig {
        minSdkVersion 4
        targetSdkVersion 17
    }
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        instrumentTest.setRoot('tests')
    }
}
  • lib_yutori/lib_yutori/build.gradle
buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
//apply plugin: 'android'
apply plugin: 'android-library'

dependencies {
    compile files('libs/android-support-v4.jar')    //☆
    //compile fileTree(dir: 'libs', includes: ['*.jar']) //☆☆
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 4
        //targetSdkVersion 16  //[NOTE]他の設定と一致させないとビルドができません><
        targetSdkVersion 17 
    }
}

☆)一応記述的には残っていても(libsにjarがなくても)
実際に参照したソースをコンパイルするのでなければ問題がありませんが、
1個1個名前指定はもにょりますよね。。。
理想は☆☆ の方の記述です


 gralde の文法確認的にはコマンドラインでやるほうが楽です
(IDEで遣りたい方は Android Studio のGUI系 設定メモ - exception thinkの外部実行登録で遣る方法もあります )
abstestフォルダ内で

./gradlew clean

でOKです。

jarがぶつかるかどうかは

./gradlew clean build

まですれば重複jar等で引っかかる(support-v4とか)
まで一応確認は可能

eclipse では

  • MainP/libs/support-v4
  • LibP/libs/support-v4

で、同じverのjarであれば重複除外を ADTさんがしてくれるのですが
gradleさんは別物なのでそういうことはしてくれません
<ここ AS<=>EC相互運用してるとネックになる気もする・・


AS上からだと

な表示なんでわからんのですよね‥‥(汗



  • で次に AS(IDEA)の売りのコード補完を聴かせるための設定をいじっていきます

 IDEA時代から相変わらず libs のフォルダ等は自動的に import設定等になってないので
ProjectStructureから手動で修正します。
注)
凄く大事なことですが、

  • abstest ではなく
  • abstest-abstest

の設定にパス等を設定して行かないと補完等が一切聞きません*3
ココらへん含めて、某IDEAの伝道師の方は「AS糞い」と仰ってるんだと思われます。。。


 という理由は
maven android plugin のユーザさん(IDEA系)は
build.xml/ADT に強制される文化でないので手動で登録するのが常識な文化のようです


  • import Module
    • Gradle Project でインポートしていきます

注)ASは環境により
import Moduleしても表示が更新されないか、importModule自体が実行できないことがあります
その場合は下記のようにすればよいかと思います

  • 一度通常画面に戻って ProjectStructureをひらきなおす
  • 通常画面から ImportModuleをする


 import Module で登録した
ライブラリプロジェクトも同じく
libs のフォルダ等は自動的に import設定等になってないので
ProjectStructureから手動で修正します。

  • どうも下部の方のlibsを参照するのが正しいようで、画像修正


 メインプロジェクトの方に モジュール関連を登録します

[+]ボタンをクリック


依存させるimport Moduleを選択


エクスポートチェックを入れる

 さて、実際にclassが生成されていないと補完動作が動かないので*4

  • 一度実行して ABSのclassファイルを作成する
  • コンソールから abstestのフォルダ内で下記のコマンドを実行
./gradlew clean build

かの操作をする必要があります

を参考にすすめたイメージです。

 これでよいのであれば

  • IDEA12時代の maven project を import Module で追加

のイメージと変わらないわけなのですが・・・

 AS自体をなんか起動し直すと、補完が認識はするようになりました*5

 しかしこの状態だと

  • dependency に設定された importModule のクラスが見えないよ!

という AS(IDEA)さんの壁にぶつかってしまい、実際のbuild.gradleの実行まで出来ません><

と思ってたんですけど

abstestフィルダ内で

./gradlew build 

で同じエラーが出てるのでgradleレベルで駄目なようですorz

:abstest:mergeDebugResources UP-TO-DATE
:abstest:processDebugManifest UP-TO-DATE
:abstest:processDebugResources UP-TO-DATE
:abstest:compileDebug
/Users/XXXX/Documents/IDEAProject/abstest/abstest/src/main/java/com/example/abstest/MainActivity.java:5: パッケージ com.actionbarsherlock.app は存在しません。
import com.actionbarsherlock.app.SherlockActivity;


試しに lib_yutori に、新規クラス hogeDriven を追加してビルドしてみます
AS上はbuildを一度行えば補完参照するようになりますが

でもう一度実行してみます

/Users/XXXX/Documents/IDEAProject/abstest/abstest/src/main/java/com/example/abstest/MainActivity.java:6: シンボルを見つけられません。
シンボル: クラス hogeDriven
場所    : com.example.lib_yutori の パッケージ
import com.example.lib_yutori.hogeDriven;

結論として、この構成ではまだ
gradleマルチプロジェクト としては相互参照できていないようですorz


根本解決編)
@ さんに最終的には解決して頂きました。*6

ようは

  • abstest/settings.gradle の宣言時に[:]が要らない
//include ':abstest' 
//メイン側は問題ない気もするけど[:]外してもincludeされるので書き方は揃えておいたほうが良
include 'abstest' 

library_name='abs' //[OK]
//[NG]デフォ形式がこの記述だがこれつくと生成されるaarに[:]や[/]が付与=>誤動作
//library_name=':abs' 
//include library_name
includeFlat library_name //仮想パス

lib_prg = project(":$library_name") //開くときには[:]が必要
lib_prg.projectDir=new File(settingsDir,'../actionbarsherlock')
println "[name]=" + lib_prg.name
println "[dir ]=" + lib_prg.projectDir

library_name='yutori' //[OK]
//[NG]デフォ形式がこの記述だがこれつくと生成されるaarに[:]や[/]が付与=>誤動作
//library_name2=':yutori'
//include library_name2
includeFlat library_name2 //仮想パス

lib_prg = project(":$library_name2") //開くときには[:]が必要
lib_prg.projectDir=new File(settingsDir,'../lib_yutori/lib_yutori')
println "[name]=" + lib_prg.name
println "[dir ]=" + lib_prg.projectDir
  • abstest/build.gradle に allprojects DSLでver宣言を付与する必要が有
repositories {
   mavenCentral()
}
apply plugin: 'idea'

allprojects{
    version = '1.0'
    println('all!') //動作確認のために突っ込んでるだけなので普通はいらない
}

これ adv-MLでも外人がみんな[出来ねー]って流れてたネタなんで
gradleドキュメント読解能力が違うわ。。。(汗

  • 下層にフォルダ掘って設定しろ

しかかいてないんだよね。自分も教えてもらうまで知らなかったし(汗

でもASさんはこの構成認知してないんでbuild.gradle を直そうとしやがるorz
((これ安易にダイアログOK押すと、ファイル消したりbuild.gradleを強制書き換えする漢らしい仕様orz

試した構成は下記にあります。

というか IDEAエキスパートのイマイ先生の言じゃないけど

  • build.gradle弄る前提のモヒカン前提っぷり
  • ASが認識できないbuild.gradle構成とかだとGUIが誤動作して消そうとする

っつうのは・・うーん・・(汗

一応遣り取りログ系は冗長なので移動しました



試行ログ<NGの話)

遣り取りログのお話を色々と聞いて、
実際ローカルで.aar参照できるか試してみる流れに

  • abstest/build.gradle
dependencies {
    //compile files('libs/android-support-v4.jar')
    compile fileTree(dir: 'libs', includes: ['*.jar'])

    lib_abs = project(':abs');
    compile lib_abs
    lib_yutori = project(':yutori');
    compile lib_yutori

    fn_abs = new File(lib_abs.projectDir,"build/libs//abs-debug.aar")
    //[NG]                    fn_abs = new File(fn_abs.projectDir,"build/libs/abs-debug.arr!/classes.jar")
    //[OK]aar(zip)解凍  fn_abs = new File(lib_abs.projectDir,"build/libs/abs-debug/classes.jar")
    println "[${fn_abs.exists()}]= ${fn_abs.dump()}"
    compile files(fn_abs)

    fn_yutori = new File(lib_yutori.projectDir,"build/libs//yutori.aar")
    //[NG]                    fn_yutori = new File(lib_yutori.projectDir,"build/libs/yutori.aar!/classes.jar")
    //[OK]aar(zip)解凍  fn_yutori = new File(lib_yutori.projectDir,"build/libs/yutori/classes.jar")
    println "[${fn_yutori.exists()}]= ${fn_yutori.dump()}"
    compile files(fn_yutori)
}

[false]= <java.io.File@74b3d096 path=XXXX/actionbarsherlock/build/libs/abs-debug.aar prefixLength=1>
[false]= <java.io.File@74b3d096 path=XXXX/lib_yutori/lib_yutori/build/libs/yutori.aar prefixLength=1>

となってるわけですが、

1目の問題として)
 まずファイル名に [/abs-debug.aar"] という名前を出力していて参照ができない
=> new File時に修正されてしまうと。

2つ目として)
でファイル名を編集(頭から[/]除去)してみます

[true]= <java.io.File@74b3d096 path=XXXX/actionbarsherlock/build/libs/abs-debug.aar prefixLength=1>
[true]= <java.io.File@74b3d096 path=XXXX/lib_yutori/lib_yutori/build/libs/yutori.aar prefixLength=1>

ファイルは見れるようになりました。

ただ
compile DSL指定で aar自体の解析ができていないようです

3つ目として)
aarはzipファイルなので 解凍して参照してみます
class.jarを参照すればコンパイル自体は通るようになります

解凍するのが微妙な話だと

fileSystem = com.sun.nio.zipfs.ZipFileSystem(new File(lib_abs.projectDir,"build/libs/abs-debug.aar"))
path1 = fileSystem.getPath("classes.jar");
fn_abs = path1.toFile();

って書き方になると思うのですが、gradleレベルで参照エラーorz
gradleをJava1.7で動かさないと駄目なのかしら。。。(汗

*1:でもgradle1.6のソース検索してみるとbuild.gradleの自動読込処理はなくなってるみたいですね<汗 OSSの移り変わりというか仕様変更早いわ。。。

*2:以前にも platform-tools 等の移動で修正入ったそうですし。。そのうち治るかと

*3:設定するだけ無駄になってしまう

*4:ここらへんはandroid maven pluginの時から変わらない

*5:maven pluginは maven build後に直ぐ認識したような。。。

*6:よちよち怖いw、アルターさん怖いw、埼玉怖いw