ページ

2011/09/23

Android ioschedのDashboardLayoutをタイトルなしのダイアログで使う

|
Google I/Oのアプリioschedに含まれているDashboardLayoutをカスタムダイアログで適用しようとしましたが、タイトルバーを非表示にしたところ、レイアウトが崩れてしまいました。
DashboardLayoutを使っているActivityのレイアウトファイルをそのまま使ったわけではなく、 Fragmentを使わないように書き換えたのですが、その際に誤って削ってしまった「android:layout_weight="1"」が原因でした。
以下、詳細のメモです。

まず、最初にダイアログに使ったレイアウトです。
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minHeight="300dp"
    android:minWidth="300dp"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@drawable/background">
    <TextView
        android:text="@string/title_a"
        android:textColor="@color/accent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center" />
    <com.google.android.apps.iosched.ui.widget.DashboardLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1">
        <Button
            android:id="@+id/button_a"
            style="@style/DashboardButton"
            android:text="@string/label_button_a"
            android:drawableTop="@drawable/icon" />
        :
    </com.google.android.apps.iosched.ui.widget.DashboardLayout>
</LinearLayout>
これをタイトルバーありの状態で表示すると以下のようになります。

2011/08/24

Android PreferenceScreenのタイトルバーをカスタマイズする

|
Androidの設定画面では、PreferenceScreenをクリックすると次の階層の設定画面に進みます。
これはActivityのように思えますが、実際にはダイアログが表示されています。

このタイトル部分のスタイルを変えようと思ったのですが、最初の画面だけが変更され、PreferenceScreenで遷移した先の画面のタイトルバーを変えられず、苦労したので記録しておきます。
結論から言うと、PreferenceScreenのタイトルバーはカスタマイズできず、同じような見た目・挙動になる別の方法をとりました。

まず該当部分をカスタマイズできるのか、Androidのソースコードを見てみたところ、android.preference.PreferenceScreenに以下のような記述がありました。
private void showDialog(Bundle state) {
    Context context = getContext();
    if (mListView != null) {
        mListView.setAdapter(null);
    }
    mListView = new ListView(context);
    bind(mListView);

    // Set the title bar if title is available, else no title bar
    final CharSequence title = getTitle();
    Dialog dialog = mDialog = new Dialog(context, TextUtils.isEmpty(title)
            ? com.android.internal.R.style.Theme_NoTitleBar
            : com.android.internal.R.style.Theme);
    dialog.setContentView(mListView);
    if (!TextUtils.isEmpty(title)) {
        dialog.setTitle(title);
    }
    dialog.setOnDismissListener(this);
    if (state != null) {
        dialog.onRestoreInstanceState(state);
    }

    // Add the screen to the list of preferences screens opened as dialogs
    getPreferenceManager().addPreferencesScreen(dialog);
    
    dialog.show();
}

2011/08/19

WindowsでRails開発するなら…

|
Ruby on Railsの開発をWindowsでしようとすると、速度の遅さが気になります。
railsコマンドを使う度に数分間待たされたりして、生産性に関わる遅さです。
加えて、コマンドライン操作をすることが多いですが使えるものが限られていて、grepするためにCygwinを使っていて、ではCygwinに切り替えられないかと思うとRubyのバージョンが古い…という状況です。

まず以下のサイトなどを参考にさせていただきました。
http://tobysoft.net/wiki/index.php?Ruby%2FWindows%A4%C7Ruby%A4%AC%C3%D9%A4%A4%B7%EF
http://d.hatena.ne.jp/miau/20110404/1301916045

coLinuxを試そうと思いましたが、使っているWindows7のPCではうまくできず、別の方法を探しました。
(もう少し詳しく調べればできたかもしれませんが、64bitマシンにはインストールできないとエラーが出てしまいました。)

デュアルブートにする手もありますが、普段はWindowsで、Railsを使うときだけLinuxにしたい、と思っていたので候補から外しました。

そこではじめて試したのが、VMware Playerです。
Linuxディストリビューションは、使ってみたいと思っていたUbuntuにしました。
下記から日本語Remix CDのisoファイルをダウンロードして使いました。
http://www.ubuntulinux.jp/products/JA-Localized/download

インストールには下記の冒頭部分を参考にさせていただきました。
http://blogs.itmedia.co.jp/kichi/2010/05/ubuntu-1004vmwa.html

デフォルトから変えているのはメモリのサイズで、「仮想マシンの設定」の「メモリ」の部分を1024MBにしています。

その結果ですが、同じマシンとは思えないほど快適になりました。
(同じ問題を抱えている方にとってはこの言葉だけで十分な気がするのでこれ以上書きません。)
好みや慣れもあると思いますが、vim、zsh、screenを入れればかなり生産性が上がります。

Railsだけでなく、全般をUbuntuでやれないか(移行できないか)調べてみたいと思います。

2011/08/06

Herokuへのpushに失敗する

|
Ruby on Railsの話題です。

Gemfileに修正を加えたのですが、
Herokuにpushできなくなってしまいました。
Gemfile.lockを削除してbundle installし直すなど試しましたが上手く行かず…

環境は以下です。
(どこまで書けば役に立つでしょうか。。)
  • Windows7
  • Git-Bash(MINGW32)
  • ruby 1.9.2p290 (2011-07-09) [i386-mingw32]
  • Bundler version 1.0.15

上手く行ったのは以下でした。
ruby on rails - Why won't Heroku accept my Gemfile.lock in Windows? - StackOverflow

2011/06/11

SAStruts ボタンのラベル

|
急にSAStrutsです。

JSPに日本語を直接書かず、プロパティファイルに集約することを考えました。

普通のラベルなどは<bean:message>を使うことで簡単にできましたが、ボタンのラベルに適用することができず少し手こずりました。
タグの属性にタグを使いたい時、EL式を定義するか新しいタグを作るかと思ってしまいますが
ちゃんと用意されていました。
結果的にはSAStruts(s:submit)の新しいやり方でなくStrutsのときから用意されていたやり方(html:submit)でした。

プロパティ(application_ja.properties):

labels.login_id=ログインID

普通のラベル表示:
<bean:message key="labels.login_id" />

ボタンに適用(NG):
<s:submit value="<bean:message key="labels.login_id" />" />

ボタンに適用(OK):
<s:submit><bean:message key="labels.login_id" /></s:submit>

ボタンに適用(OK):
<html:submit><bean:message key="labels.login_id" /></html:submit>

2011/06/05

Android DBアクセスなどを簡略化するフレームワーク

|
AndroidでのO/Rマッピングなどをやってくれるフレームワークのようなものを作ってみました。
既にどこかにあるのかもしれませんが、まぁそれでも良いです。

Androidのライブラリ/フレームワークの場合、R.javaを含んでいるとどうしても
プロジェクトとしてソースコードが見える状態で組み込まないといけないようなので、
オープンソースプロジェクトとして作りました。
fastroid

まだごくわずかなことしかできないので、これから拡張していきたいと思います。
とりあえず、以下のことができます。
・画面から入力値をとってくる
・入力チェックする(必須チェックのみ)
・SELECT/INSERT/UPDATE/DELETEする

SELECTに関しては、JOINできるようにしたいと思っていますが
まだ特定条件でしかできません。

SQLite用のクラスをそのまま使って書くと、大したテーブル操作をしていなくても
ごちゃごちゃしてきます。
これが大分解消されるはずです。
…というのがよく分かるサンプルプロジェクトや説明書を
作らないといけないですね。

2011/05/21

Android Preferenceの内容が他の項目に変わる

|
カスタマイズしたPreferenceを作りました。
しばらく画面内に1つしかそのPreferenceを使っていなかったのですが、
数を増やしたところおかしなことになりました。

増やしたもののうち、Dependencyを設定しているカスタムPreferenceがあるのですが
依存先のチェックボックスを操作したところ
そのカスタムPreferenceと他のカスタムPreferenceが入れ替わる現象が起こりました。
さらに、カスタムPreferenceをタップしてダイアログを開き、
OKで閉じても他の項目と表示が入れ替わってしまいます。
しかし、他の項目と思ってタップすると、開くダイアログは入れ替わり前の内容です。

Preferenceの一覧表示だけがおかしい?と見当をつけて調べたところ、
原因はonBindView()にありました。

2011/05/05

Android CheckStyle設定

|
AndroidプロジェクトでのCheckStyle設定についてです。

Android Open Source Projectのコードスタイルでは、フィールド名はmから開始する、
などのルールがあります。
Code Style Guidelines for Contributors

これはコントリビューター向けのものではありますが、
自分のアプリの書くコードもなるべくこれに沿っていた方が見やすいかなと思っています。

# 多くはCode Completeにあるような推奨されるor避けるべき書き方の話なので
# Android特有のルールというのは実は少ないかもしれません。

そこでCheckStyleでチェックしようとしたのですが、ちょっと苦労したので載せておきます。
Android用のCheckStyle設定を公開してくださっている方がいます。
Checkstyle for Android

でもこれ、一部間違いがあって動きませんでした。

Android 見つけにくいResources$NotFoundExceptionの原因

|
TextViewに文字列や数値を表示する画面を作りました。
正しくレイアウトのXMLを記述して、プロジェクトも再ビルドして、R.javaにIDは存在しているはずなのに
Resources$NotFoundExceptionが出てしまいました…。

しばらく例外メッセージの中の「見つからない」と言われているIDを見ていて、気づきました。

TextViewにはsetText(CharSequence text)だけでなくsetText(int resid)があるのです。

そのため、以下のようなコードを書くとコンパイルエラーは出ません。
int price = 1000;
((TextView) view.findViewById(R.id.price)).setText(price);

これを動かすと、リソースID「1000」のR.stringを探そうとするので上記の例外が発生します。

例えば以下のようにres/values/string.xmlが書いてあったとします。
<resources>
    <string name="app_name">Test</string>
</resources>

この場合は以下のようにすれば「Test」がTextViewに表示されます。
((TextView) view.findViewById(R.id.price)).setText(R.string.app_name);

最初の例外が出る例は、以下のように文字列に変換すれば動きます。
int price = 1000;
((TextView) view.findViewById(R.id.price)).setText(Integer.toString(price));

数値はCharSequenceではないので当たり前の動作なのですが、
コンパイルエラーが出ないので注意した方が良さそうです。
本当は、R.javaの定数がintなどのプリミティブ型でなく列挙型等になっていると、
間違ってint型を指定してもコンパイル時に検出できて良いのですけどね。

2011/05/04

Android (ソースコード解説) SlidingDrawerでwrap_contentを効かせつつ表示/非表示での高さを切り替える

|
SlidingDrawerを使って、「Gmailアプリでチェックボックスにチェックを入れたときに表示されるボタン群」のようなものをきれいに実現する方法です。

ソースコードのポイントを解説します。

※完成イメージと、それに至るまでの問題は以下で説明しました。
Android SlidingDrawerでwrap_contentを効かせつつ表示/非表示での高さを切り替える

※ソースコードは以下に掲載しました。
Android (ソースコード掲載) SlidingDrawerでwrap_contentを効かせつつ表示/非表示での高さを切り替える

Android (ソースコード掲載) SlidingDrawerでwrap_contentを効かせつつ表示/非表示での高さを切り替える

|
SlidingDrawerを使って、「Gmailアプリでチェックボックスにチェックを入れたときに表示されるボタン群」のようなものをきれいに実現する方法です。

完成イメージと、それに至るまでの問題は以下で説明しました。
Android SlidingDrawerでwrap_contentを効かせつつ表示/非表示での高さを切り替える

ソースコードをとりあえず載せます。
また長いので、解説は改めて投稿します…。

まずはレイアウトです。

Android SlidingDrawerでwrap_contentを効かせつつ表示/非表示での高さを切り替える

|
他の部品を隠さずにSlidingDrawerを使い、コンテンツの大きさに合わせてSlidingDrawerをレイアウトする方法についてです。この説明もタイトルも、一言でうまく伝えられないので、まずは完成イメージをまず載せます。
ソースコードは改めて投稿します。

完成イメージ

1. 画面の下方にスクロールする部品があります。(TextView)
2. ドロワーを開くと、スクロールするビューのスクロールバーがずれています。つまり、ドロワーで隠れてしまった部分を下方にスクロールすることで表示できます。
3. 実際、最下部までスクロールできます。(「終わり」という部分です。)
4. ドロワーを閉じると、スクロールビューが元のサイズに戻ります。

2011/05/03

Android アノテーションでRadioButtonの値をコード値として取得

|
Androidのラジオボタンは、HTMLのラジオボタンのようなvalueを持っていません。
「どのRadioButtonが選択されたか」と「選択されたRadioButtonのテキスト」くらいしか
そのラジオボタンを特定する情報がありません。

そのため、ラジオボタンの値をDBへ登録しようなどと考えていると
リソースIDとコード値の割り当てをハードコーディングすることになってしまいます。

例えば以下のような感じです。
RadioGroup radioGroup = (RadioGroup) activity.findViewById(R.id.radio_group_foo);
int checkedId = radioGroup.getCheckedRadioButtonId();
int value;
switch (checkedId) {
case R.id.radio_button_foo_1:
 value = 1;
 break;
case R.id.radio_button_foo_2:
 value = 2;
 break;
} 

このマッピングを色んなところに散らかすのは嫌です。

AndroidのUIに関するプログラミングである以上、
リソース(R.java)を扱うのは避けられそうにないので、外部の設定ファイルにマッピングを書くのは難しそうです。
そこで、アノテーションを使ってラジオボタンの値を設定するフィールドに情報をまとめることにしました。

ソースコードにマッピングを書くのは変わりませんが、
情報がまとまるのでコードは見やすくなるはずです。
イメージは、SAStrutsのような、アノテーションをpublicフィールドに定義する感じです。

以下、必要なアノテーションです。

Java リフレクションで取得するフィールドの順番

|
リフレクションでフィールドを取得すると、フィールドの順番が何に基づいているのか分からない結果となりました。

Java API仕様を見ると、確かに順序は決まっていないという記述がありました。
Class#getFields()

この Class オブジェクトが表すクラスまたはインタフェースのすべてのアクセス可能な public フィールドをリフレクトする、Field オブジェクトを保持している配列を返します。返された配列内の要素は、ソートされていたり、特定の順序になっていたりすることはありません。


Javaの標準的な機能ではフィールドの定義順でフィールド情報を取得することはできなさそうです。

以下のように、フィールド名やアノテーションを使えば順序を規定することはできそうです。
Java reflection: Is the order of class fields and methods standardized? - stackoverflow

これを使って、AndroidのParcelableの実装を汎用化しようと思います。
# Parcelable#writeToParcel(Parcel, int)やコンストラクタにフィールドを列挙するのを毎回書かずに済むようにします。

Android フレームワークとか

|
Androidプログラミングを始めてまだ数カ月ですが、
入門書やWebの情報を参考に作成していると、
同じようなコードを何度も書くようでうんざりしてきます…。

Androidのフレームワーク、ライブラリなどはないのでしょうか?

個人的に、ライブラリ化できそうだと思うのは以下のようなものです。
まだ勉強中なのでもっとあるのかもしれませんが。

  • 入力チェック
  • DBアクセス

Android SDK自体、フレームワークなのですが
一般的なWebアプリケーション等と同様、
多数の入力画面やBean的なものを書こうとすると
どうしても上記のような部分が面倒に感じます。

既存のライブラリを含めてしまうとかなりアプリ容量が大きくなるし、
動作も保証できないのが不安なのかもしれませんが。

UIに関してはライブラリがあるようですが、
見つからなければ、今進めているアプリの開発の中で
簡易なものを作ってみようかなと思います。

Android TabHostで下側にタブを表示するときにビューが隠れないようにする方法

|
# これまであまりに一般的すぎる内容ばかり書いていたので、ある程度調べてもわからなかったこと、つまづいたことを中心に書いていきたいと思います。

AndroidでTabHostによるタブを作成するとき、下側にタブを作成するにはRelativeLayoutを使う必要があるようです。
しかしこのとき、メインのビューを下一杯まで広げると、タブでビューの一部が隠れてしまいました。

RelativeLayoutを使う場合の注意ですが、相対的な配置なので、
他の要素とどのような位置関係にあるのかを指定しなくてならないようです。

上側に表示するFrameLayoutにこれを指定することで解決しました。
android:layout_above="@android:id/tabs"

FrameLayoutはTabWidgetの上にある、という指定です。

以下、全体のレイアウトです。タブのコンテンツは含まれていません。

<?xml version="1.0" encoding="utf-8"?>
<TabHost
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@android:id/tabhost"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <RelativeLayout
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical">
  <FrameLayout
   android:layout_alignParentTop="true"
   android:layout_above="@android:id/tabs"
   android:id="@android:id/tabcontent"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent" />
  <TabWidget
   android:id="@android:id/tabs"
   android:layout_alignParentBottom="true"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content" />
 </RelativeLayout>
</TabHost>

2011/03/07

EclipseからSubversionリポジトリにアクセスできない

|
PCを新しく購入したのですが(Windows7)、以前のPC(Windows XP)で使っていたNAS上のSVNリポジトリにEclipseからアクセスすることができませんでした。以下のようなエラーが発生してしまいます。

svn: Unable to open an ra_local session to URL
svn: Unable to open repository 'file:///L:/svn/~'

原因はわかりませんが、どうやらドライブ名を記述しているのがいけないようで、以下のようにディスク名を指定するとアクセスできるようになりました。

file://ls-xhl479/share/svn/~

以下のサイトからヒントを得ました。
最初はWindows7の問題かと思いましたが、あまり関係なさそうです。
http://www.tertullian.org/rpearse/subclipse_windows.htm

2011/03/04

Google Chromeで複数のGoogleアカウントを同時に利用する

|
Androidアプリ公開用に、普段使っているのアカウントとは別に新しいGoogleアカウントを取得しました。
しかし、あるタブで普段のアカウントでログイン、別のタブではAndroidのデベロッパーコンソールに新しいアカウントでログイン、とやっていると何かするたびにログインし直さなければなりませんでした。(当たり前ですが)

別のブラウザを使う、という方法はすぐに思いつきましたが、Chromeを使いたいと思い調べてみると、ありました。
複数のアカウントを同時に使用する: Google Chrome で複数のプロフィールを使用する

いくつか方法がありそうですが、プロフィール情報を分けて保存し、それぞれを読み込むショートカットを作成する上記の方法を選びました。すぐにできました。

元々のショートカットと、このショートカットを使い分けることで、複数のアカウントを同時に利用することができます。

Google Chromeにはいくつかアイコンがついているようなので、アイコンも変えておくと便利そうです。



他にも、マルチログイン機能というものを使えば同じブラウザでアカウントを切り替えられるようですが、すべてのサービスに対応しているわけではないようです。
基本情報とスタート ガイド: 複数のアカウントを同時に使用する

Android ライブ壁紙をリリース

|
最初のAndroidアプリとしてライブ壁紙を作ってみました。
Android Market

2011/02/22

Android ライブ壁紙設定画面の背景色

|
以下のページを参考に、ライブ壁紙の設定画面(PreferenceActivity)を作成しました。
http://developer.android.com/resources/samples/CubeLiveWallpaper/AndroidManifest.html

この場合、設定画面の背景が半透明になり、後ろの画面が透けて見えます。
通常の不透明な画面にする方法を探していたのですが、AndroidManifest.xmlの以下の設定を修正するだけでした。

android:theme="@android:style/Theme.Light.WallpaperSettings"

以下のページに記載されている、Androidで提供されているテーマTheme_Blackを使用すれば通常の黒い画面になります。
http://developer.android.com/reference/android/R.style.html

AndroidManfest.xmlに書く場合には、Theme.Blackと「.」で区切るようです。

android:theme="@android:style/Theme.Black"

2011/02/19

Android Menuサンプル

|
メニューのサンプルを作成しました。

実行イメージ:


Android Listサンプル

|
Androidでリスト表示をするサンプルを作成しました。

実行イメージ:

ListActivityを継承して作成します。


package com.example.listviewsample;

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class ListViewSampleActivity extends ListActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // レイアウトは不要
        //setContentView(R.layout.main);
        
        // アダプタに項目を設定
        setListAdapter(new ArrayAdapter(
          this,
          android.R.layout.simple_list_item_1,
          new String[]{
            "item1",
            "item2",
            "item3",
          }));
    }
}