Rejasupoem

deliver value to customers continuously or die;


Rebuild.fmクライアント(非公式)開発の裏話

2014-02-18

Rebuild.fmクライアント(非公式)をリリースしましたの開発の中で生まれたtipsや思い出を紹介しようと思います。 結構長いです。

目次

  • アプリのバージョニング
  • RSSフィードの取得
  • メディアの再生/停止ボタン
  • Show Notesの表示
  • MenuDeledate
  • データの保存とテスト
  • Tweetの取得
  • FontAwesome
  • 通知の管理
  • ライセンス表示
  • 進捗と開発のボトルネック

バージョニング

Android端末の設定からアプリ情報を見ると "バージョン0.1.2-SHA1" の形式になっていると思います。 Androidアプリのバージョンコードは整数でなければなりませんが、バージョン名は文字列なので、開発者が好きなように使うことができます。 たとえばビルドした日付を入れている開発者もいますし、独自に定義したコードを使っている人もいます。 僕の場合はオープンソースでやってるし、日付よりGitのログの方が有用かなと思って、このようにしました。

というか思い立って調べたらJake Wharton神の記事が出てきたので、ほぼそのとおりに設定しました。 以下、アプリのビルド設定の一部です。

def versionMajor = 0
def versionMinor = 1
def versionPatch = 2
def versionBuild = 0 // bump for dogfood builds, public betas, etc.

def gitSha() {
    return 'git rev-parse --short HEAD'.execute().text.trim()
}

android {
    compileSdkVersion 18
    buildToolsVersion "19.0.1"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 18
        versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
        versionName "${versionMajor}.${versionMinor}.${versionPatch}-${gitSha()}"
    }

    ...

こんな感じで、バージョンコードとバージョンネームの生成はコードに任せています。

RSSフィードの取得

エピソードの取得ですが、アプリの起動時にRebuild.fmのRSSを取得しています。 Androidで使えるRSSクライアントが見当たらなかったので、SAXParserを使って頑張ってparseしています。

一応ライブラリにしました:rejasupotaro / AsyncRssClient

今思うとjsonicとgsonを使って、

  • before
url -> [ xml -> entity ] -> entity
  • after
url, meta -> [ xml -> json -> entity ] -> entity

こうした方が良かったなと思いました。

メディアの再生/停止ボタン

最近別のアプリでも再生/停止ボタンを作ったのですが、

2つのステートを持つImageViewは、CheckBoxを使うと簡単に実装できます。

media_start_and_pause_button.xml

まず、drawableにチェックされているときと、チェックされていないときの画像を定義します。

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
            android:state_checked="true"
            android:drawable="@android:drawable/ic_media_pause" />
    <item
            android:state_checked="false"
            android:drawable="@android:drawable/ic_media_play" />
</selector>

style.xml

次に、Widget.CompoundButton.CheckBoxを継承したチェックボックスのスタイルを作って、drawableを上書きします。

<style name="MediaStartAndPauseButton" parent="android:Widget.CompoundButton.CheckBox">
    <item name="android:button">@drawable/media_start_and_pause_button</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
</style>

FragmentのLayout

チェックボックスに定義したスタイルを適用します。

<CheckBox
        android:id="@+id/media_play_and_pause_button"
        style="@style/MediaPlayAndPauseButton"
        android:layout_marginLeft="@dimen/margin_icon_button"
        android:layout_gravity="center"
        />

こうすることでOn/Off時の画像の切り替えのコードを書かなくてよくなります。また、

mMediaStartAndPauseButton.setOnCheckedChangeListener(
        new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    start(episode);
                } else {
                    pause();
                }
            }
        });

OnCheckedChangeListenerが使えたり、isCheckedメソッドが使えたりして、かなり具合がいいです。

Show Notesの表示

書いてる途中で寝てしまったのでうちに帰ってから書く。

MenuDeledate

書いてる途中で寝てしまったのでうちに帰ってから書く。

データの保存とテスト

書いてる途中で寝てしまったのでうちに帰ってから書く。

Tweetの取得

書いてる途中で寝てしまったのでうちに帰ってから書く。

FontAwesome

書いてる途中で寝てしまったのでうちに帰ってから書く。

通知の管理

書いてる途中で寝てしまったのでうちに帰ってから書く。

ライセンス画面

書いてる途中で寝てしまったのでうちに帰ってから書く。

進捗と開発のボトルネック

Code Frequencyをご覧のとおり、11月に着手してその一週間後に機能的にはほぼ完成していました。 そのあと忙しくなってあまり時間が取れずに2月のリリースになったのですが、何がそんな大変だったのかというと、UXとかUIを考えるのにすごく時間がかかりました。

XMLを書いては端末にインストールして確認し、場合によってはFragmentにしたりActivityに戻したりしながら進めてるので、すごく時間がかかっています。 チームで開発しているときは、各々が得意分野をやりますが、一人だと全部自分でしないといけないので、自分の弱点がそのまま開発のボトルネックになるということを実感しました。