日記:楽天WebAPIコンテストで銅賞獲ったどー!

昨日になりますが、2月末が締め切りだった楽天WebAPIコンテストの結果発表が楽天WebAPIのサイト上で行われていました。

http://webservice.rakuten.co.jp/campaign/2011/0125/

これに、私が作成した自転車備品マネージャーコスメマネージャーを応募していたのですが、そのうちのコスメマネージャーがスマートフォンアプリ部門で銅賞をいただきました!

楽天ポイントを1万ポイントもらえるというのも嬉しいですが、コンテストで賞が取れたということ自体がとても嬉しいです!(^-^)他のスマートフォンアプリを見ると、画面も洗練されているし、凄そうだなぁと思うので、また研究させてもらおうかなと思いました。自分の考えだとどうも古くさいというか直列なデザインのアプリになりがちなのですが、他のアプリは自分にはない発想やレイアウトで勉強になりそうです。

これからも頑張っていいアプリ作りたいなぁと思います!


Android:計画停電情報を作りました。

リリースは10日前になりますが、計画停電情報というAndroidアプリを作りました。


計画停電情報

もう連日ニュースで流れておりますが、東日本大震災がありました。当時、私は何やってたか忘れましたけど、昼夜逆転していてウツラウツラしながら、PCの前にいました。椅子に座ったまま寝ていて、ふと目を覚ましたら、twitterのTLが地震一色になっていました。すぐにテレビをつけたら、津波がやってくるので逃げろと。
みるみるうちに津波に飲み込まれていく町を見ながら、もうなんともいたたまれない気持ちになって、やりばのない感情をずっと感じていました。たぶん同じような人はいっぱいいただろうと思います。

ただただ、twitterのTLとテレビを見ながら、大丈夫だろうか?と心配して祈ることくらいしかできなかったところに、夜子ままさんに誘われて、PrayForJapanというAndroidアプリの作成に関わりました。募金サイトのまとめをするということをやりました。

その後、ちょうど仕事もなかったのと、この気持ちをぶつけられるような自分でもできることはないかと思い、twitterのTLで欲しいアプリを聞いたところが、計画停電情報を作るキッカケでした。しかじろーさんに毎日新聞のサイトを教えてもらい(当時の東京電力の資料はPDFのみだったので)、毎日新聞の計画停電情報のページを解析するプログラムを書いて、現在地の計画停電情報がわかるようにしました。その際、フォロワーの皆さんにテストを手伝っていただきました。何度か修正してようやく、「動いたよ!」と言われて安堵して、その後睡眠。そこからはもう私 VS 東京電力&毎日新聞との戦い。

グループは固定で、時間が変わるのだろうと思っていたら、まさかの両方が変わるという事実に、かなり驚きました。計画停電エリアの人は、今日は何グループで、いつ停電するのかを毎日調べないといかんとか、大変すぎると。まだ途中ですが、考えられる便利な機能を適宜追加していき、データも適宜更新していたら、毎日新聞のサイトがデータの形式を変更したため(というよりは、編集ミスだったと思われる)、アプリがバグってしまい、多くの皆様に迷惑をかけました(勝手に毎日新聞のサイトのデータを解析するアプリを作っていたので毎日新聞さんは悪くないです、念のため。)twitterで直してもらえないかと連絡したら、すぐに直していただけたので、よかったのですが、その影響で完全に東京電力の資料を元にしたデータにしないといかんなぁと思いました。

この頃になると、東京電力さんもExcelで計画停電の資料を公開してくれていたので、Excelをアップするだけでよくなるようなシステムを作ろうと思って、GoogleのAppEngineにプログラムを置きました。デ部のzaki50さんにライブラリのこととか、データのキャッシュをするためのソースコードを提供いただいて、比較的簡単に実装でき、本当に助かりました。

自前でサーバを準備できたので、あとはこちらでWebAPIを書けば、いくらでも機能強化できるのでそこからはある意味、欲しいデータを取れるWebAPIを書けばいいのですごい楽になりました。まぁサーバ側とAndroid側の2つのプログラムを書く必要は出てきたのですが、それを差し引いても余りあるアドバンテージでした。アプリのパフォーマンスも体感で3倍は速くなったとtwitterで言われました。

ただ欠点もありました。計画停電情報のアプリで、住所の入力が面倒だからなんとかならないか?という要望が多かったので、なんとかしたいと思い、サジェスト(入力候補がでてくるやつ)を実装したら、GAEの無料帯域を使い切ってしまったのです。既に70,000DLを超えていたので、サジェストするためのデータをバンバンやり取りしていたらすぐでした。アプリが使えなくなってしまっては元も子もないので、先にBilling設定(有料設定)をしておいたので、ユーザに迷惑はかからなかったんですが、今度はシステムを維持するのにお金がかかるようになってしまったのです。

さすがに自腹を切ってアプリを提供しつづけるのはしんどい(金持ちでもないし…)、かといって有料のアプリにするのは目的と違うので、アプリに広告を入れるようにしました。ただ、いきなりアプリに広告を入れたのでは、「これが目的だったんかい」と思われたくはなかったので(もちろんそういうつもりもなかったですし…)、ユーザの意思で広告のON/OFFができるようにした上で、リリースしました。

そのおかげか、ものすごく好意的に受け入れてもらえて、広告収入が見込めるようになったのでサーバ料金も払えるようになり、ガンガン機能追加に集中できるようになりました。今はVer 2.2.0で、サポート掲示板を作りました。それもGAE上に置いてます。

最初の1週間は色々とあって(データ形式の問題とか、機能の要望とか)、かなり頑張りましたが、今週はちょっと落ち着いてます。それでも機能追加はやっていますが、先週に比べれば、落ち着いてます。その間に、色んなメディアに取り上げてもらって、もう数日で10万DLにいきそうな勢いです。

このアプリを作ったことでたくさんのお礼・応援をいただき、いろんなアイデアも頂きましたので、このアプリは自分が作ったというよりは、応援してくださった方々のアプリだと思います。自分は実装しただけで。たくさんDLしていただいて、多くの人の役に立てたのは嬉しいことです。ですが、本来はこういうアプリが必要とされないほうがいいので、本当に早く、計画停電が終わって安心できる日常が戻ればいいなと思います。

それまでは、頑張って機能追加していこうと思います。


計画停電情報


Android:コスメマネージャーをリリースしました

2/27の話になりますが、コスメマネージャーというAndroidアプリをリリースしました。

自転車備品マネージャーの、化粧品版なのですが、こちらは楽天のランキングなども見られるようにしてあります。あとデザインをzamuuさんに依頼して作っていただきました。やっぱりプロにデザインしてもらうと見栄えが違うっ!?

私としても女性をターゲットに絞ってアプリを作成したのは今回が初めてなので、早速twitterで色んな意見が聞けてとても参考になります。女性の感覚や、どういうところに注目しているかなどはアプリを出してみないとわからないものですね〜。

このアプリは楽天ウェブサービスAPIコンテストに応募したので、どうなるかが楽しみです!!


Android:DatePickerDialogで取得した値をDBに保存

DatePickerDialogを使ったのが初めてで、そこで取得した値をsqliteに保存する方法はどうしたもんかなと。また、取得した値をDatePickerDialogに反映させる方法も、どうしたもんかなと。

面倒なので、まんま私が書いたコード載せます。

簡単にいうと、
DatePickerDialogに設定する場合は、
SimpleDateFormatで指定したフォーマット(yyyy-MM-dd)に合わせてDateに変換します。

DBに保存する場合は、
SimpleDateFormatで指定したフォーマット(yyyy-MM-dd)の形式の文字列を保存します。
fmt.format(date)で、”2011-03-02″のような文字列が取得できます。

    private void dateEdit(final long id, String strdate) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        Date date;
        try {
            if (strdate == null || strdate.equals("")) {
                date = new Date();
            } else {
                date = fmt.parse(strdate);
            }
            DatePickerDialog dialog = new DatePickerDialog(this,
                    new DatePickerDialog.OnDateSetListener() {
                        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                            Date date = new Date(year - 1900, monthOfYear, dayOfMonth);
                            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
                            mDBHelper.updateDate(id, fmt.format(date));
                            // カーソルを再取得して更新をListViewに反映させる
                            mCursor = mDBHelper.getAll();
                            mAdapter.changeCursor(mCursor);
                        }
                    },
                    date.getYear() + 1900,
                    date.getMonth(),
                    date.getDate());
            // クリアする
            dialog.setButton(DialogInterface.BUTTON_NEUTRAL,
                    getString(R.string.txt_clear),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            mDBHelper.updateDate(id, "");
                            // カーソルを再取得して更新をListViewに反映させる
                            mCursor = mDBHelper.getAll();
                            mAdapter.changeCursor(mCursor);
                        }
            });
            dialog.show();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

Android:SimpleDateFormatに潜む罠

某WebAPIを使っているアプリを作成中です。
そのWebAPIから取得できるJSONに、lastBuildDateという日付を表す項目があったので、せっかくなのでそれをパースして日本語表記で出力しようと思ったのですが、Javaだとどうやって日付の文字列をDateに戻すのだろうと…。

ググったら、SimpleDateFormatというクラスがありました!

lastBuildDateの形式は、”EEE, dd MMM yyyy HH:mm:ss Z”でした。
Wed, 23 Feb 2011 02:55:21 +0900
みたいな感じです。なので、それを指定してみました。

// 失敗・・・
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
// jsonはJSONObject
try {
    Date lastBuildDate = format.parse(json.getString("lastBuildDate"));
} catch (ParseException e) {
    Toast.makeText(context, e.getLocalizeMessage(), Toast.LENGTH_LONG).show();
}

パースに失敗したよ!というトーストが表示されました。何故に!?

わからなかったので、SimpleDateFormatについてさらに調べたところ、オブジェクトを生成するときに引数でLocaleを渡している例を発見。しかも日本語だとMMMとしたときとかに日本語になったりするらしい。それはパースできんわ。ということで、引数を足してみました。

// Locale.ENGLISHを追加。これで上手くいった!!
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
// jsonはJSONObject
try {
    Date lastBuildDate = format.parse(json.getString("lastBuildDate"));
} catch (ParseException e) {
    Toast.makeText(context, e.getLocalizeMessage(), Toast.LENGTH_LONG).show();
}

Androidというよりも、Javaの話題なのですが、Androidだと端末毎にLocaleが決まるので、注意が必要ですね。Localeを英語にしていたら気付かずにバグを仕込むところでした(まぁ英語にする場合はデバッグのときくらいですが)

以上です!!