Droidkaigiのリポジトリを参考に自分でGradle Pluginを作成してみる
Droidkaigiのリポジトリのように、マルチプロジェクトで設定ファイルを共有する仕組みを知りたいと思って幾星霜。
今まで重い腰が上がらなかったのだが、Wear OSのプロジェクトが設定をベタ書きにしており非常につらい思いをしていたので、必要に迫られてやることにした。誰かの参考になれば幸いである。
Droidkaigiのリポジトリのように、マルチプロジェクトで設定ファイルを共有する仕組みを知りたいと思って幾星霜。
今まで重い腰が上がらなかったのだが、Wear OSのプロジェクトが設定をベタ書きにしており非常につらい思いをしていたので、必要に迫られてやることにした。誰かの参考になれば幸いである。
Gradleの機能として提供されているversionCatalogsを使って依存関係を定義してみた。
Gradleでライブラリの管理を便利にできそうなプラグインを見かけた。refreshVersionsというプラグインだ。
buildSrcを使って一括管理する方法は知っていたが、プロジェクトごとに用意するのも面倒くさい。なにか楽な方法はないかと思っていたが、これはその解の1つとなりそう。
Floobitsというのはリアルタイムコラボレーションを実現するためのサービス。 VSCodeのVisual Studio Live Shareみたいなやつで、リモート経由でのペアプログラミングとかを実現するためのサービスである。
リモート経由でペアプロしたいが、Android開発でそんなことできるのかというのが出発点だった。 Android StudioのベースとなっているIntelliJ IDEAでもそういう機能があるのか調べたところ、今の所ないというのが結論。 要望自体ははるか昔からあるみたいだが、実現するにはコラボレーション用のサーバ用意したりとハードルがあまりに高いだろうことは想像に難くない。 公式には用意されていないが、見つけたのがこのFloobitsというサービスである。
別にIntelliJに限らず、他のプラットフォームでもプラグインが用意されている。 https://floobits.com/help/plugins Emacs, Sublime Texxt, Neovim, IntelliJ, Atomと多数のエディタに対応している。 Free planであれば5つのWorkSpaceを持てる。 Android Stuioでいえば1つのプロジェクト=WorkSpaceになるだろう。 Free planではprivateなWorkSpaceを持つことはできないので、ソースコードは誰でも見れる状態になる。 Edit権限を与えなければ勝手に編集されることはない。 ちなみにWorkSpaceはActive Workspaceで確認できる。
どんな感じなのか気になったので、パソコン2台使ってとりあえず試してみた。 試した環境が同一LAN内にあるPCではあったことが関係している可能性はあるけれど、遅延はほぼないと思っていいだろう。
Summonなる機能があって、これを使えば他のコラボレーターを自分が編集しているファイルに瞬時に招集することが可能。 「このファイルがさー」「どれだよ?」 なんてときに活躍しそう。 とりあえず試したのはコード編集だけではあるが、他にもチャットができたりコラボレーションのための便利な機能が盛り込まれている。
ただ、ペアプロに便利とはいうものの、Floobitsはあくまでリアルタイムでのペアプロ目的に使うにとどめた方がいいだろう。 Floobitsにアップロードしたプロジェクトを、Floobitsに接続しない状態で更新→FloobitsのWorkSpaceに接続という流れになると、リモートのファイルを上書きするか、リモートのファイルでローカルを上書きするかの2択になってしまう。 Gitでバージョン管理していても、FloobitsのWorkSpace自体はGitで管理されているわけではないので、下手するとGitの履歴自体が上書きされてなかったことにされる恐れもありそう。 プロジェクトはGitで別途管理して、サブ的にFloobitsを使うという感じがいいのかもしれない。 ゼロからいきなりFloobitsのWorkSpaceにジョインして開発を進めるとおかしなことになりそう。
gitと併用してFloobitsを使う場合のFAQがあった。 https://floobits.com/help/faq 運用でカバーする必要があるっぽい。
リモート経由でペアプロするのには非常に便利だと思う。 またFloobitsはAndroidに限らず使えるというのは便利な点だろう。 セキュリティ的にどうなんだというところがクリアできるなら、普通に便利な気がする。
いつもOverwrite local/Overwrite remoteが、どっちがどっちなんだっけと使うときに混乱するのでメモ。
どっちがどっち、というのはovwerwrite localが、現在の設定をリモートリポジトリの設定で上書きするのか、現在の設定でリモートの設定を上書きするのか混乱してしまうのである。 Overwrite localは現在の設定をリモートの設定で上書きする、が結論なんだけど。 これがわかりにくいと思うのは私の英語力がないせいなのだろうか。
ちなみにSettings Repositoryをご存じない方向けに簡単に紹介。
IntelliJ IDEAで使える設定共有用のプラグイン。 私の場合で言うと、Android Studio(stable/canary)とIntelliJ IDEA community editionを行ったり来たりすることがあるので、このプラグインを使って設定を共有している。 バージョンアップする際に以前の設定を引き継ぐというのはできるが、同時に運用しているときにAで行った設定変更をBでもまたやらないといけない、というのが起こらなくなるので非常に便利だと思う。
利用しているプラグインによっては、そのプラグインの設定ファイルもバックアップ対象になるらしい。 例えば私はIdeaVimを利用しているが、どのファイルのどの位置にカーソルが移動した、という情報までバックアップ対象になってしまっている。 そのため必要に応じて不要な設定ファイルは.gitignoreで管理対象から外すなど工夫が必要。 (私はvim_settings.xmlは管理対象から外している)
MacであればFileメニューのところにSettings Repositoryがあるので、GitHubなりBitbucketなりで管理用リポジトリを用意してそのURLを設定すれば使えるようになる。
ちなみにどうもエディタでタブを使わないとか、キーマップの設定でどれを使うかなどまでは合わせてくれないようだ。 例えば私の使っているキーマップはMac OS X 10.5+ copyとなっているのだが、このキーマップ設定自体は共有してくれるものの、これが有効な状態にまでは復元してくれない。 そのため、どのキーマップを使うか、コードスタイルはどれを使うかなどは手動で直さないといけないようだ。
ストアに公開しているアプリは2018年8月までにtargetSdkVersionを26以上にする必要がある。その関係で以前にリリースしたアプリを更新しているのだが、その際に最初のハードルとなるのが古いAndroid Studioで作ったプロジェクトを現在のバージョンに更新する作業である。
最近何回も同じことをやっているので、備忘録的に書いておく。
基本的には全部Migrate to Android Plugin for Gradle 3.0.0に書いてあるので、そのとおりにやるだけである。
書いている途中でAndroid Studio 3.1が正式版になった。が、3.0から3.1への更新はそんなに大きく変更しなくても済むので、基本は3.0へのマイグレーションガイドに書いてあることに対応すればよいはず。
まず始めにGradle(Gradle wrapper)のバージョン更新を行う。Android Studio3.0は最低でもGradle4.1以上が必要。(3.1はGradle4.4以上)
gradle wrapperの更新はgradle-wrapper.propertiesファイルを書き換えてgradle syncを行うだけ。
私は./gradlew wrapper --gradle-version=<Gradleのバージョン>コマンドで更新している。これで更新したらシェルスクリプトの更新もかかる場合があるので、こっちのほうがいいのかなという雰囲気で選んでいるだけだったりする。
コマンドで更新した場合、distributionUrlで指定されるgradle wrapperが4.x-bin.zipといった感じでバイナリのみのものになる。Android Studioはallにしとけと変更を促してきて、結局手書きでdistributionUrlを書き換えることになるので、普通にマイグレーションドキュメントにあるようにgradle-wrapper.propertiesを書き換えるだけでいいと思う。
ちなみに利用するgradleのバージョンだが、私の場合Twitterで見かけたGradleのリリースツイートを見て覚えてるバージョンを利用している。今だと4.6。
使えるバージョンはhttps://gradle.org/releases/で確認できる。基本的には最新使っとけばいいんじゃないだろうか。
プロジェクトで利用しているgradle pluginのバージョンが古い場合、原因がよくわからないエラーが多発する。例えばNo signature of method: com.android.build.gradle.internal.scope.VariantScopeImpl.getGenerateRClassTask() is applicable for argument types: () values: []とか。こういうのは利用しているgradle pluginを最新のバージョンに更新すると解消されることが多かった。
基本的にAndroid Studioが利用しているプラグインの新しいバージョンがあれば教えてくれるはず(網掛けになって新しいバージョンがあることを示唆してくれる)ので、それに従ってgradle pluginのバージョンを上げてみると解決する場合が多いだろう。
エラーメッセージで検索してもこれといった解決策が見つからないという場合には、利用しているプラグインのバージョンを上げることを試してみよう。
昔はライブラリプロジェクトを利用している場合、publishNonDefault trueを設定して、アプリケーションモジュールをdebugビルドするときは、ライブラリプロジェクトもdebugビルドにするなんて指定をしている人もいただろう。
この設定をしている場合、Android Studio3.xにアップデートするにあたってちょっとした手直しが必要になる。
Android Studio3.0からはライブラリモジュールのビルド設定は、利用するアプリケーションモジュールのものと同じものが利用されるようになった。appモジュールでdebugビルドを選んだら、自動的に依存しているライブラリモジュールもdebugビルドでビルドされる。
そのため以下の手直しが必要。
Flutterを触り始めたのだが、とにかくWidgetのレイアウト変更がツライと感じていた。
AndroidでいうところのViewのレイアウトがコードでゴリゴリ書いていく感じになっているので、インデントが深くなってツライ。Widgetの考え方もAndroidのViewとはちょっと違う(レイアウトに関する設定はレイアウト情報を持つWidgetでくるむとか)
ゼロから作る分にはまだいいのだが、一度作ったレイアウトに対して、「このTextにmargin付け加えたい」となったときがツライ。シンプルなレイアウトならまだいいが、Widgetが何個も登場したり、何回層もネストされてたりすると正直触りたくない。
例えばこんな感じ。
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("FriendlyChat"),
),
body: new Column(
children: <Widget>[
new Flexible(
child: new ListView.builder(
padding: const EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, index) => _messages[index],
itemCount: _messages.length,
),
),
new Divider(height: 1.0,),
new Container(
decoration: new BoxDecoration(
color: Theme.of(context).cardColor,
),
child: new Text("hoge"),
),
],
),
);
}
これはまだかわいいものだが、それでもめんどうくさい。
そこでLive Templateを追加して、IntelliJのSurrond With機能を使って簡単にWidgetを囲えるようにしてみた。Flutterのチュートリアルを試したりするのに活躍するのでかなり捗ると思う。
Preference > Editor > Live Templateが定義場所。
定義する場所は別にどこでもいいのだろうけれど、Flutterに関することなのでFlutterのところに追加した。
new Column(
children: <Widget>[
$SELECTION$
]
),
Dartファイルに適用されるように指定して、Reformat according to styleにチェックも入れておく。

DroidKaigi2017の会場には行かなかったけれども、参加した人や公開されたスライドなんかは一通りチェックしている。そんな中でこちらのスライドでSave Actionsなるプラグインを知る。
Android Studioで保存時にフォーマットを自動で揃える
Save Actions – JetBrains Plugin Repository
Android Studioでビルドしたりファイルの保存が行われた際に、自動的にoptimize importやreformat codeを実行してくれるプラグインである。
ファイルの保存時にrefomart codeを実行する方法として、cmd+sにマクロを割り当てて行うという方法は以前から知っていたのだが、私は導入していなかった。というのも、私はAndroid Studioを使っていてただの一度も自分からファイルの保存を行ったことがないからである。そもそもcmd+Sを押す習慣がなかったのだ。それだったら気がついたときにalt+cmd+lでreformat codeを実行するのと大差ないなと思って導入しなかった。なのでreformat codeを実行することもよく忘れていた。(droidkaigi2017のリポジトリにフォーマットしてないコードをプッシュしたりしていた、申し訳なかった)
しかしこのSave Actionsプラグインに出会えたことで、今後そんなミスは起こさないだろう。
このSave Actionsは、Android StudioのPreference > Pluginsからは検索することができない。作者の方がAndroid Studioによる動作確認が取れていないのがその理由らしい。
導入するにあたっては、JetBrainsのPlugin Repositoryからzipファイルをダウンロードしてきて直接インストールする必要がある。
ちなみに、今のところAndroid Studioだからきちんと動作をしないという事象には出くわしていない。
素晴らしいなと感じたのが、ファイルが自動保存されるタイミングやビルド(デバッグ実行)したタイミングで、自動的にreformat codeが走ってくれること。しかもそのSave Actionsのreformat codeで修正された部分は、自分が修正したコードとは異なる色で表示される(新規が緑、変更が青、Save Actionsによるreformat分はグレーみたいな感じで色分けされる)。あくまでAndroid Studioのエディタ上での表示の話なので、コミットする際に別れてくれるわけではないけれども。
なお、Save Actionsを導入する場合は、必ずFile path exclusionsに.gradleファイルを追加する必要がある。
https://github.com/dubreuia/intellij-plugin-save-actions/issues/51
Gradleファイルをいじる際に、キーをタイプするたびにreformat codeなどが走るというバグがあるからだ。
個人的にはプラグインのバグというより、IntelliJ系IDEの仕様なのではないのかと思っている。gradleファイルはspaceを追加するだけでも「syncしろ」と言ってくるので、このあたりの動きが関連しているようにも思う。ともあれ、当座のところはgradleファイルをSave Actionsの対象外にすることでしのげる。
ともあれ、個人的にとても便利なプラグインだと思う。あまりに感動して作者にお礼のツイートを送ってしまうほど、ドンピシャなプラグインだった。
少し幸せになる技術というスライドで紹介されていたが、私は少しどころではなくかなり幸せになれた。ありがたい。
タイトルが分かりにくいんですが、こちらの画像をご覧ください。

画像の例ではアプリのパッケージ名がjp.gcrete.sample.daggersandboxで、そこからさらにapiとかdiとかのパッケージに分化してます。
Android Studio2.2にしてから、なぜかそのサブパッケージの部分が単にapiではなく、jp.gcreate.sample.daggersandbox.apiと省略されずに表示されていました。
Layout EditorのようにAndroid Studioの設定でそうなっているのかとも思いましたが、該当するような設定項目はありませんでした。
なんでだろうなと思って探してみたところ、issueが立ってました。
https://code.google.com/p/android/issues/detail?id=223389
https://code.google.com/p/android/issues/detail?id=222914
どうもDataBindingを有効にすると発生するそうです。実際、この画像のプロジェクトでもDataBindingを使っており、これをfalseに変更すると普段通りの表示になりました。


DataBindingを使っている人のみ影響を受けるみたいです。
最近はfindViewByIdを使わなくて済むからくらいの軽い理由で、DataBindingを多用しているので早く直ってほしいです。
まあProjectウィンドウが見づらくてなんか気持ち悪いってだけなんですけどね。
Android Studio 2.2.1で直ったみたいです。
layout.xmlを開いた際に、デフォルトではDesignタブで開かれると思います。これをTextに変更する方法です。
Android Studio 2.1まではレイアウトのPreview画面に歯車アイコンがあって、Prefer XML EditorにチェックをつければOKでしたが、Android Studio 2.2のPreview画面にはそのようなものが見当たりません。
Android Studio 2.2からは、設定画面から変更するようです。

Preference > Editor > Layout Editorで設定できます。