2012/12/30

android.net.Uri と java.net.URI の変換

android.net.Uri と java.net.URI の違い で java.net.URI と android.net.Uri はほぼ同じであると書きましたが、継承関係にあるわけでもなく、変換用の関数が用意されているわけでもありません。

では、これらは変換出来ないのかというと、そうではありません。
もともと文字列で表現されるアドレスのパーサですから(正確にはパーサを内包したコンテナというべきでしょうか?)、文字列にしてしまえば相互に変換することができます。

String path = "http://anonymous@192.168.0.1:8888/main.html?id=00001#fragment";
Uri androidUriA = Uri.parse(path);
URI javaUriA = URI.create(androidUriA.toString());

Log.i(TAG, "A " + javaUriA.toString());

URI javaUriB = URI.create(path);
Uri androidUriB = Uri.parse(javaUriB.toString());

Log.i(TAG, "B " + androidUriB.toString());

android.net.Uri と java.net.URI の違い

Android でネットワーク系の開発をしていると必ず出てくる Uri。
これ、android.net.Uri と java.net.URI と2種類あって混乱する時があります。(java.net.URL ってのもありますが、それはまた別のお話)
で、どう違うのか調べてみたので備忘録として書いておきます。

まず、どちらも URI を表すクラスである点では同じです。
参考

そして、パッケージ名を見れば明らかなのですが、 android.net.Uri は android 用に作成されたクラスなのに対して、 java.net.URI は java で定義されているクラスです。
(import しちゃうと途端に区別がつきにくくなるんですけどね…)

まず、大きな違いとしては、java.net.URI は Serializable なクラスなのに対し、android.net.Uri は Parcelable なクラスであるところと、 android.net.Uri は abstract なクラスであるところが挙げられます。

以下に、それぞれに定義されているメソッドを列挙してみました。

2012/12/29

Emulator を起動しようとしたら X Error of failed request

Android アプリを開発していて、いつものように Emulator を起動しようと思ったら、以下のようなエラーが出てしまいました。
Starting emulator for AVD 'Nexus7'
X Error of failed request: BadRequest (invalid request code or no such operation)
Major opcode of failed request: 139 (ATIFGLEXTENSION)
Minor opcode of failed request: 66()
Serial number of failed request: 13
Current serial number in output stream: 13
ちなみに、環境は以下のような感じ
  • Ubuntu 12.04 LTS
  • グラフィックボード GV-R455D3-512I
  • Android SDK 21
  • Eclipse 4.2 (Juno) SR1
  • ADT 21
で、探してみると以下にヒントがありました。
android - Error on starting emulator for avd after adt 20 install - Stack Overflow

どうも ADT の問題というより、グラフィックボードのドライバの問題の可能性が。
という訳で、ドライバを再インストールしてみました。

参考
穀風: Ubuntu 12.04 LTS に RADEON HD 4550 ドライバを入れたらデュアルディスプレイが出なくなった

すると、問題なく Emulator が起動するようになりました。

2012/12/28

Stunnel4 on Ubuntu が起動しない

Ubuntu 12.04 LTS に stunnel をインストールしてみました。

$ sudo apt-get install stunnel4
$ sudo cp /usr/share/doc/stunnel4/examples/stunnel.conf-sample /etc/stunnel/stunnel.conf

/etc/stunnel/stunnel.conf を適当に編集して、実行。
すると、以下のようなエラーが出てしまいました。

$ sudo /etc/init.d/stunnel4 start
SSL tunnels disabled, see /etc/default/stunnel4

/etc/default/stunnel4 の中を見てみると、以下のような一文が。
# Change to one to enable stunnel automatic startup
ENABLED=0
なるほど。
ENABLED を1にしないといけないということですね。
というわけで、以下のように修正。
# Change to one to enable stunnel automatic startup
ENABLED=1

実行できました。
$ sudo /etc/init.d/stunnel4 start
Starting SSL tunnels: [Started: /etc/stunnel/stunnel.conf] stunnel.


ところで、 /etc/stunnel/README を読んでいたら、以下のように書いてありました。
In order to have the tunnels start up automatically on system boot you must *also* set ENABLED to 1 in /etc/default/stunnel4
最初に読んだのに見落としていた…orz

2012/12/22

ScrollView を使わないで TextView に スクロールバーを表示する

Android の ScrollView、便利なのですが、内容にあわせて高さを変更したい場合などには向いていません。

特に、TextView の最大高を行数で指定したい場合、ScrollView を使用することが出来ません。
まぁ絶対使えないのかと言われると不可能ではないと思いますが、かなり面倒くさいことになると思います。

では、簡単に出来る方法は無いのかというと、View には Scrollbar を表示する機能がデフォルトでついているので、これを利用することが出来ます。
参考:Android TextView with scrollbars and maxHeight - Stack Overflow

まず、生成する TextView を以下のように定義します。
<TextView
    android:id="@+id/text_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:singleLine="false"
    android:maxLines="3"  // ←ポイント
    android:scrollbars="vertical" />

上記のように maxLines を指定しておくと、使用しているフォントサイズにあわせて TextView の高さを自動調整してくれます。

さて、このままでスクロールしてくれれば本当に簡単なのですが、残念ながらそこまで簡単ではありません。
以下のコードを Java 側に記述しておく必要があります。
(大抵の場合は Activity.onCreate に書いておけばよいでしょう。)
TextView textView = (TextView)findViewById(R.id.text_view);
textView.setMovementMethod(ScrollingMovementMethod.getInstance());

これで TextView の中身がスクロールするようになります。

ちなみに、参考にしたサイトには、以下の記述があります。
android:textColor="@android:color/secondary_text_dark_nodisable"
これは、Android 2.3 以前では、TextView をクリックした時に文字色が反転してしまうため、文字色を灰色にすることで、その問題を防ぐという意味があります。
しかし、これを書いてしまうと TextView の文字色が灰色になってしまうので、ベストな方法とは言い難いです。

この問題は、 android.Theme.Dark の場合にのみ起こるようなので、android:Theme.Light 等を Application や Activity の theme として設定すれば回避することが出来ます。
もちろん、全体のテーマから変更されるので、全体的に白を基調としたデザインに変更されてしまいますが、Google としては白基調を推奨しているようなので、なるべくなら白基調でうまく作っていくのが良いでしょう。


注:
今回の方法では指に追従するスクロールになってしまいます。
フリックで自動スクロールするようにするためには、 ScrollingMovementMethod を継承した独自の MovementMethod を作成する必要があります。

2012/11/30

Xperia acro HD (SO-03D) を 4.0 にしたら重くなったのでプリインアプリを無効化してみた

au の IS12S に遅れること約4ヶ月、やっと docomo SO-03D も4.0へのバージョンアップが発表されました。
もう、このままバージョンアップしない可能性もあるかと思っていたので、嬉しい限りです。

さて、喜び勇んでバージョンアップしたものの、起動したら動作がモッサリ…
いや、モッサリっていうか重い。激重。
ANR (Application not responding) 出まくるし。
それも、今まで問題なく動いていたアプリで。
他の4.0端末では問題なく動いているアプリで。

「なんじゃこりゃーーーー!」

一瞬で使い物にならない端末になってしまいました。

もしかしたら、バージョンアップ後の一時的なものかもしれませんが、それにしたってこれはひどすぎる。
原因を調査しようと思い、実行中のアプリを見てみると、やはり docomo 系のアプリが何やら動いている様子。
どう見ても、使わないものばかりのようなので、無効にしてみることにしました。
(4.0 からはプリインを無効に出来るようになったと、以前どこかで読んだことがあったので。)

設定 → アプリ

本当は「すべて」というタブがないといけないのですが、見当たりません。
実は、タブを左にスライドさせると出てきます。
たまたまだと思うのですが、わざと見せないようにしてるのではと勘ぐってしまいますね。

2012/11/20

R.id.xxx を switch 文で使うと case expressions must be constant expressions

これまで1プロジェクトで作成していた Androidアプリを機能別にライブラリ化してみました。
すると、 case expressions must be constant expressions というエラーが。


Migrate Android Code をクリックしてみると、以下のような文が表示されました。

ざっと意訳すると、以下のような感じでしょうか。

ADT 14 以降のライブラリプロジェクトでは R.id.menu_settings のようなリソースフィールドが定数ではなくなります。これは、再コンパイル無しでライブラリを使用できるようにするためです。

この変更により、(リソース)フィールドを switch 文の中で直接使うことが出来なくなります。代わりに、if-else を使用するようにしてください。

Eclipse では switch を自動的に if-else に変更することが出来ます。switch 文の上にカーソルを置き、Quick Fix を呼び出してください (Windows, Linux の場合は Ctrl-1, Mac の場合は Cmd-1)。
そして、 Convert switch to if-else を選択します。

リンク先の http://tools.android.com/tips/non-constant-fields を見てみると、ほぼ同じことが図入りで説明されています。


というわけで、「ライブラリプロジェクトにおいて、リソースフィールドを条件分岐に使用する場合は、switch ではなく if-else を使うように」ってことだそうです。

ちなみに、「ライブラリプロジェクト」とは
Project → Properties → Android で Is Library にチェックを入れたプロジェクトのことです。


configChanges=”orientation” を指定しているのに回転時に Activity が再生成される!?

Android の Activity は回転時に再生成されるという事実は、かなり有名だと思います。
そして、AndroidManifest.xml に android:configChanges="orientation" を記述しておくと、再生成を抑制してくれるというのも結構有名だと思います。
参考: Handling Runtime Changes | Android Developers
<activity android:name=".MyActivity"
          android:configChanges="orientation"
          android:label="@string/app_name">

ところが、我が家の Nexus7 では、上記のように設定しているのにも関わらず、回転すると Activity が再生成されてしまいます。
おかしいなぁ、と思って調べたところ、以下のサイトに情報が。

Kiroru Official Blog : onConfigurationChanged が呼ばれない!

「minSdkVersion か targetSdkVersion で 13以上の数字を設定している場合は、 orientation の他に screenSize も指定するように」とのことです。


しかし、よく見てみたら Handling Runtime Changes | Android Developers に書いてあったのね…
以前、読んだことがあるからと言って、読み飛ばしてしまったのが失敗でした。



ところで、この「回転時に再生成される仕様」って、Activity は長いこと放置されても(つまり、Destroy されても)、同じ状態に復活すべき。という発想から来てるんだと思います。
そう設計されているものは、一度削除してから生成しなおしても問題ないはずだと。

しかし、実際は、長い間放置された場合はホーム画面に戻る方が良いけど、回転時は現状を維持して欲しい。みたいなケースがあるわけです。
そういう場合には、configChanges を使用するのは有効です。

が、安易に使用すると、ちょっと他のアプリを起動していたら初期化されてしまうという問題につながるので、気を付けた方が良いかもしれません。

2012/11/08

Android Open Source Project を Eclipse に取り込む (2)

Android Open Source Project を Eclipse に取り込む で Android のソースコードを Eclipse に取り込むところまではうまくいったのですが、残念ながらエラーが出てしまいました。

Project 'AndroidOpenSourceProject' is missing required library: 'out/target/common/obj/JAVA_LIBRARIES/google-common_intermediates/javalib.jar'

Project 'AndroidOpenSourceProject' is missing required library: 'out/target/common/obj/JAVA_LIBRARIES/gsf-client_intermediates/javalib.jar'
だそうです。

2012/11/07

Android Open Source Project を Eclipse に取り込む (1)

@ Eclipse 4.2.0 Indigo

先日、Nexus7 用に Android をビルドしてみたので、次はコードをいじってみることにしました。
まずは、 Using Eclipse | Android Open Source を参考にして、 ソースコードを Eclipse に取り込みたいと思います。
注意
今回は Android Open Source Project (AOSP) を丸々取り込む方法です。
普段の Android アプリ開発時に、ソースコードを参照したいという場合は、以下の方が簡単でしょう。
穀風: Android のソースコードを Eclipse から使用できるようにする
参考
本エントリーは、既にAOSPのソースコードをダウンロード済みの前提で書かれています。
まだ、ダウンロードしていないという方は以下からどうぞ。
穀風: Nexus7 用に Android をビルドしてみた (2)


それでは早速 Eclipse に取り込んでいきたいと思います。
$ cd ~/android_src
$ cp development/ide/eclipse/.classpath .
$ chmod u+w .classpath

.classpath の内容を見てみると、 out/target/common が必要のようです。
つまり、ビルド済みのライブラリを用意しなければならないということですね。
私の場合は、Nexus7 用に Android をビルドしてみた でビルドしてあったので、そのまま使えそうです。

また、eclipse.ini のメモリ設定も書き換える必要があると書いてありますが、こちらも既に設定済みでした。
私の設定は以下です。
推奨よりさらに大きい値になっていましたが、大きい分には問題ないはずです。

-XX:MaxPermSize=256m
-Xms512m
-Xmx1024m


続いて、指示に従い Eclipse を起動します。
workspace はデフォルトのままで良いと書いてありますが、私は別の workspace にしてみました。
そのへんは好みだと思います。

Eclipse が起動したら
File → New → Java Project

細かい話ですが、このメニューは Perspective によって変わってしまうので、もし Java Project が出てこない場合は Java Perspective になっているかを確認してみると良いと思います。
もし、それでもメニューに出てこない場合は、
File → New → Other...
ダイアログで
Java → Java Project
とたどれば、Java Project が作成できるはずです。

2012/10/27

ClipboardManager で NoClassDefFoundError

Java のパッケージは便利なのですが、同じ名前でパッケージが違うと時々混乱します。
Android の ClipboardManager もそんなクラスの一つです。

テキストを Clipboard にコピーする方法として、以下の様なコードがよく提示されています。
あえて import 文を見せているところが重要。
import android.content.ClipboardManager;

// 省略

private void copyToClipboard(String text) {
    ClipboardManager clipboardManager =
            (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    clipboardManager.setText(text);
}


これ、最近のADTでは、"Class requires API level 11 (current min is 7)" というように怒られます。


このエラー、「API11 未満ではこのクラスは提供されていないよ。」という意味ですから、この時点で何かおかしいとは思うわけですが、とりあえず、@TargetApi(11) をつけて問題を回避してみます。
import android.content.ClipboardManager;

// 省略

@TargetApi(11)
private void copyToClipboard(String text) {
    ClipboardManager clipboardManager =
            (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    clipboardManager.setText(text);
}

これを、API11 未満の端末で動作させると、NoClassDefFoundError が発生します。
E/AndroidRuntime(221): java.lang.NoClassDefFoundError: android.content.ClipboardManager

先ほど Eclipse で警告が出ていたように、Class が存在していないようです。

2012/10/26

adb を使わないで fastbootモードにする @ Nexus7

先日、穀風: Nexus7 を工場出荷状態に初期化してみた で fastbootモードにする手順として、以下のように書きました。
fastboot Nexus7 をUSBで接続して、Cygwin から以下のコマンドを実行。
$ adb.exe reboot bootloader

しかし、改めて Building for devices | Android Open Source を読んでいたら、以下のような記述を発見。
During a cold boot, the following key combinations can be used to boot into fastboot mode


(adb を使わなくても、)電源ON してからロゴが表示されている間に音量ダウンキーを押せばオッケーとのことです。

実際やってみると、電源キーから手を離してしまうとダメでした。
「電源を押したまま、ロゴが表示されたタイミングで音量ダウンキーを押す」とうまくいきます。
ネット検索してみると、多くの方が、「音量ダウンキーを押したまま、電源キー長押し」と書いています。
確かに、そちらの方が確実ですね。

2012/10/23

Nexus7 用に Android をビルドしてみた (3)

穀風: Nexus7 用に Android をビルドしてみた (2) でソースコードの取得が完了したので、次は Building the System | Android Open Sourceを参考に、実際のビルドに移ります。
ターゲットはBuilding for devices | Android Open Sourceに載っていました。
$ source build/envsetup.sh
$ lunch full_grouper-userdebug
$ make -j4

気長に待つこと数時間。
コンパイルが終了しました。

あとは実機に焼くだけです。
Nexus7 を接続し、まずは fastbootモード立ち上げます。
$ adb reboot bootloader

私の Nexus7 は既にアンロック済みなので、このまま続行しますが、まだの場合は以下のコマンドでブートローダーをアンロックします。
$ fastboot oem unlock

出力先のディレクトリに移動し、書き込みコマンドを実行します。
$ cd out/target/product/grouper
$ fastboot -w flashall

書き込みが終了すると、自動的にリブートがかかり、あのお馴染みの起動画面が立ち上がります。
エミュレータを良く使ってる人は見飽きているはずのこれです。


数秒待つと、Android のホーム画面に。
当然ですが、Gmail も Google Play もないプレーンな Androidです。

なんか、役に立たない子になっちゃったなぁ(笑)
まぁ、ちょっと遊んだら工場出荷時に戻してやろうと思います。


2012/10/22

Nexus7 用に Android をビルドしてみた (2)

穀風: Nexus7 用に Android をビルドしてみた (1) で環境構築が済んだので、次は Downloading the Source Tree | Android Open Sourceを参考にソースコードを取ってきます。

ダウンロード先は任意に決められますが、今回は ~/android_src というディレクトリにソースコードをダウンロードすることにしました。

また、Building for devices | Android Open Sourceによると、Nexus7 用のブランチは 「android-4.1.1_r4 or master」 と書かれています。
ただ、先日のアップデートで Nexus7 は Android 4.1.2 になってしまいました。
後ほど書きますが、ビルドに必要なバイナリも 4.1.2 用しか提供されていません。
とりあえず、今回は android-4.1.2_r1 を取ってくることにしました。(Nexus7 のデバイスネームは grouper って言うらしい)
2013/2/5 追記
現在の最新ブランチ(タグ)は android-4.2.1_r1.2 です。
Nexus 系はどんどん新しいバージョンが出るので、どのブランチを取って来るべきか悩みます。
基本的には提供されているバイナリ(下記)を見て決定すればよいでしょう。
指定できるブランチ(タグ)名は https://android.googlesource.com/platform/manifest にブラウザなどでアクセスするとわかります
$ mkdir ~/android_src
$ cd ~/android_src
$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.1.2_r1
$ repo sync

結構長い時間がかかりますが、ソースコードの取得が終了するまで気長に待ちます。

その間に、Nexus7 の動作に必要なバイナリを取得しておきます。
Building for devices | Android Open Source によると、ICS 以降、オープンソースに出来ないハードウェアドライバのバイナリが必要であるとのこと。
それらを、Google's Nexus driver page からダウンロードしておく必要があるそうです。

ちなみに、2012/12/22 現在のスクリーンショットは以下です。
既に 4.1.2 のものしか提供されていませんので、これらをダウンロードしてきます。

ダウンロードしたファイルをソースツリーのルートに置きます。
今回は ~/android_src です。
tar ball を展開すると、シェルスクリプトが作成されますので、それらを実行します。
$ ls *.tgz
broadcom-grouper-jzo54k-26240daf.tgz    nvidia-grouper-jzo54k-56de148f.tgz
elan-grouper-jzo54k-c889b8f4.tgz        nxp-grouper-jzo54k-4bfb1fb6.tgz
invensense-grouper-jzo54k-aae1cd0c.tgz  widevine-grouper-jzo54k-aca0e725.tgz
$ for i in *.tgz
> do
> tar zxf $i
> done
$ for i in *.sh
> do 
> ./${i}
> done

この時、各スクリプトを実行すると、ライセンスに同意するよう求められます。

同意するには、Y や Yes ではなく、I ACCEPT と書かなければいけません。

全てうまく行くと、vendor というディレクトリに必要なファイルが展開されます。

過去のビルドがあって、バイナリを新規に追加した場合は、以下のコマンドを実行して残骸を消しておく必要があるようです。
$ make clobber

うまく行ったら、もとのファイルは削除してしまってかまいません。
rm *.tgz *.sh

穀風: Nexus7 用に Android をビルドしてみた (3)

Nexus7 用に Android をビルドしてみた (1)

@ Ubuntu 12.04 LTS

Nexus7 を手に入れたので、自分でビルドしていろいろいじってみようかと思います。
とりあえずは、AOSPから取ってきたソースコードをビルドして焼いてみるところまで。

以下を参考に環境を構築します。
Initializing a Build Environment | Android Open Source

基本的には書いてある通りなのですが、現在は sun JDK 6 の入手先が変わっているので要注意。
以下のサイトを参考にさせていただきました。
Installing Java6 JDK on Ubuntu 12.04 | digital nomad
$ mkdir ~/src
$ cd ~/src
$ git clone https://github.com/flexiondotorg/oab-java6.git
$ cd ~/src/oab-java6
$ sudo ./oab-java.sh
$ sudo apt-get install sun-java6-plugin sun-java6-jre sun-java6-bin sun-java6-jdk

update-java-alternatives を使用して実行環境を java-6-sun にしておきます。
参考: まさおのブログ (表): Ubuntu 複数インストールされている java を切り替え
$ update-java-alternatives -l
java-1.6.0-openjdk-amd64 1061 /usr/lib/jvm/java-1.6.0-openjdk-amd64
java-1.7.0-openjdk-amd64 1051 /usr/lib/jvm/java-1.7.0-openjdk-amd64
java-6-sun 63 /usr/lib/jvm/java-6-sun
$ sudo update-java-alternatives -s java-6-sun

必要なパッケージインストール
$ sudo apt-get install git-core gnupg flex bison gperf build-essential \
  zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev \
  libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386 \
  libgl1-mesa-dev g++-multilib mingw32 openjdk-6-jdk tofrodos \
  python-markdown libxml2-utils xsltproc zlib1g-dev:i386
$ sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib/i386-linux-gnu/libGL.so

/etc/udev/rules.d/51-android.rules に以下の行を加える(ファイルがない場合は作成する)
# adb protocol on grouper (Nexus 7)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e42", MODE="0666"
# fastboot protocol on grouper (Nexus 7)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e40", MODE="0666"

CCACHE と repo もインストールしておく
$ sudo apt-get install ccache
$ mkdir ~/bin
$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
$ chmod a+x ~/bin/repo

~/.bashrc に以下を加える
export USE_CCACHE=1
PATH=~/bin:$PATH

変更を反映させて環境構築完了。
$ source ~/.bashrc

穀風: Nexus7 用に Android をビルドしてみた (2)

2012/10/19

CheckedTextView と SimpleAdapter の組み合わせで IllegalStateException

以下のようなコードを Android 2.2 以前の端末で実行すると IllegalStateException が発生します。
List<Map<String, String>> data = new ArrayList<Map<String, String>>();
for (int i = 0; i < 10; i++) {
    Map<String, String> map = new HashMap<String, String>();
    map.put("item", String.valueOf(i));
    data.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(
                this,
                data,
                android.R.layout.simple_list_item_single_choice,
                new String[] {"item"},
                new int[] {android.R.id.text1});
mListView.setAdapter(adapter);

LogCat の出力は以下のような感じ
E/AndroidRuntime(2226): java.lang.IllegalStateException: android.widget.CheckedTextView should be bound to a Boolean, not a class java.lang.String

これ、やっかいなのは Android 2.3 以降では普通に実行できるのです。
なので、きちんと古い端末で動作確認しないと問題を発見できません。

この問題の原因は SimpleAdapter の実装にあります。
2.3 以降の SimpleAdapter は TextView を継承している View に対して暗黙的にテキスト (データに対しtoString()したもの) を割り当ててくれるのですが、古いものにはそのような機能はありません。

そのため、2.2 以前を対象にする場合は ViewBinder を明示的に定義してやる必要があります。
具体的には、以下のように setAdapter より手前で setViewBinder を呼んでやります。
adapter.setViewBinder(new ViewBinder() {
    @Override
    public boolean setViewValue(View view, Object data, String textRepresentation) {
        CheckedTextView v = (CheckedTextView) view;
        v.setText((CharSequence) data);
        return true;
    }
});
mListView.setAdapter(adapter);

2012/10/11

Exception が発生した時の LogCat の読み方 (3)

穀風: Exception が発生した時の LogCat の読み方 (2) に続いて、もう少し現実的なパターンを書いておきます。

サンプルは前回までと同じものです。


Button3 を押すと、以下のような Exception が発生します。

これまでのルールだと一行目を見て、RuntimeException が発生したということになります。
まぁそれで間違いではないのですが、RuntimeException というのは例外処理を必須としない一般的な Exception です。
どんなエラーが起こったかの情報にはなりません。

実は、今回のエラーは別スレッドで起こっているので、このようなログが出力されるのです。

2012/10/10

Nexus7 を工場出荷状態に初期化してみた

せっかく Nexus7 を買ったので、カスタムロムを作って遊ぼうと思っているのですが、ミスった時に元に戻せないと危険なので、工場出荷時に戻せるか試してみました。

今回は Cygwin on Windows 7 Professional (64bit) で実行しましたが、当然 Linux でも出来ると思います。

以下は前提条件です。
  • Android SDK がインストールされていること
  • %SDK Location%/platform-tools にパスが通っていること
  • 開発者向けオプション - USBデバッグがONになっていること

Nexus7 のファクトリーイメージを以下のサイトからダウンロードしておきます。
Factory Images for Nexus Devices - Android — Google Developers

2012/10/10 時点でのダウンロード先

それでは、早速初期化してみます。
まずは、Nexus7 をUSBで接続して、Cygwin から以下のコマンドを実行。
$ adb.exe reboot bootloader
もしくは、音量ダウンキー+電源ボタンで起動(2012/10/26 追記 穀風: adb を使わないで fastbootモードにする @ Nexus7

すると、Nexus7 が再起動し、fastboot モードで立ち上がります。
fastboot モードで立ち上がったところ
ドロイド君がパカっとお腹を開けられてしまっています。

2012/10/07

Exception が発生した時の LogCat の読み方 (2)

穀風: Exception が発生した時の LogCat の読み方 (1) では、最もシンプルな LogCat の読み方を書きましたが、実際はそんなに単純な Exception が出ることは稀です。
今回はもう少し現実的な Exception を見てみたいと思います。

サンプルは前回と同様のものです。


Button2 を押すと、以下のような Exception が発生します。


上から見ていくと、IndexOutOfBoundsException が発生したことがわかります。
どんな Exception なのかは調べてみて下さい。

さらに、次の行を見ていくと、ArrayList.java の 257行目が発生源のようです。
そんなコードを書いた覚えはありません…

2012/10/06

Exception が発生した時の LogCat の読み方 (1)

先日、知人が Exception (例外)が発生した時のデバッグが大変だと言うので、話を聞いてみたところ、LogCat を使っていないということがわかりました。
いや、正確には LogCat 自体は知っていて、怪しそうなところに片っ端からログを出力してデバッグしているとのこと。
いわゆる printfデバッグですね。

デバッグ手法として間違ってはいないけど、まずはスタックトレースの見方を知らないと大変だよねってことで、結構真面目に説明してあげました。
せっかくなので、ここにも書いておこうかと思います。


まずは、サンプルコードを作ります。
今回は、ボタンを押したら Exception が発生するサンプルを作成してみました。
以下にアップロードしてあります。
ExceptionThrower.zip


あえて、どんな Exception が発生するかわからないようにしてみたので、実行する前にコードを見て、どんな Exception が発生するか想像してみるのも良いでしょう。

2012/09/26

onActivityResult が呼ばれた直後に onPause が走ることがある

先程、onActivityResult が呼ばれるタイミングについて調べて、記事を書きました。
穀風: onActivityResult が呼ばれるタイミング

しかし、ES File Explorer というアプリを呼び出した場合だけ、その挙動がおかしいのです。
以下がそのログです。(動かしたコードは先の記事を参照してください)

onActivityResult が呼ばれるタイミング

@Android 2.3.7  Xperia acro HD

onActivityResult は onResume の前に呼ばれるという記述をよく見かけるのですが、実はそんな単純じゃなさそうなので、調べて見ました。
Activity の一般的なライフサイクルについては以下に書きましたので参考にしてみてください。
穀風: ホームボタン と 戻るボタン で Activity の終了処理が異なる


今回は、ボタンが一つだけある Activity を用意して、ボタンを押した時に startActivityForResult を呼ぶ単純なテストを作成してみました。
コードは最後に載せてあります。

2012/09/19

Eclipse のプラグイン情報を引き継ぐ

Eclipse を Indigo (3.7) から Juno (4.2) にアップデートしました。(@Windows 7 64bit)
本体のアップデートは

Help → Install New software...
http://download.eclipse.org/eclipse/updates/4.2

とするのが簡単なのでしょうが、私は昔からのクセで、新しい Eclipse を別ディレクトリにインストールして、暫くの間2バージョン共生状態で運用することにしています。

ただ、その際に面倒くさいのがプラグインの移行です。
少し前までは、 dropin フォルダを利用していたのですが、やはり更新のしやすさを考えると Eclipse Marketplace や更新サイトの利用が増えてきてしまい、結局インストールし直すことになるのが面倒でした。
しかし、今回は Eclipse 3.6 から加わったプラグインの引き継ぎ機能を使って、これが楽に出来ました。

2012/07/28

Android JUnit で Parameterized test case

@Android 2.3.3 (API 10) 以降

先日、
JUnit3 で Parameterized test case (1)
JUnit3 で Parameterized test case (2)
というエントリを書きましたが、本当は、Android JUnit で Parameterized test をしたかったのです。
Native Java Project なら、おとなしく JUnit4 を使っておけば良いわけですから。

というわけで、早速 JUnit3 で Parameterized test case (2) で作成したコードを Android JUnit に移植してみました。

今回のプロジェクトは以下にアップしてあります。ご自由にお使いください。
AndroidJUnit3Experiment.zip

2012/07/27

JUnit3 で Parameterized test case (2)

昨日、JUnit3 で Parameterized test case (1) というエントリを書いたのですが、その後いろいろいじっていると、ちょっと不満が出てきたので改造してみました。

本日のコードも以下にアップしてありますので、ご自由にお使いください。
JUnit3Experiment_02.zip

昨日の問題点

一番の不満は、テストを走らせるときに、AllTests.java を選択してから走らせなければならないということ。
「全部走らせる」 = 「プロジェクトを選択して Run」 が Eclipse っぽいような気がします。

JUnit3 で Parameterized test case (1)

JUnit4 には Parameters アノテーションがあって、同じテストをパラメータを変えて実行することができます。
しかし、JUnit3 にはそのような機能がないため、本来はパラメータ毎にテストメソッドを記述しなければなりません。
なんてイマイチな仕様なんだ…

しかし、よく考えてみると、 TestSuite を利用すれば、JUnit4 と同じように Parameterized test が出来ることに気づきました。
以下、やってみた結果です。

今回、作成したプロジェクトは以下においてあります。
ご自由にお使いください。
JUnit3Experiment_01.zip

2012/7/28 追記
ちょっとだけ不満が残ったので、改造してみました。
穀風: JUnit3 で Parameterized test case (2)

2012/07/24

Android の Custom View で Scrollbar を使用する

Android で Custom View を作った場合、Scroll bar を表示したいケースがあると思います。

こういうやつ

実現する方法はいろいろあると思いますが、android.view.View にはデフォルトで Scroll bar を表示するオプションがついているので、これを使ってやれば簡単です。

2012/07/02

Android 上で SQLite データベースの内容を見る

これ、出来そうでなかなか良い方法が見つからなかったのです。
デベロッパーたるもの、なければ作れば良いってことで、そんなアプリを作ってみました。

SQLite Viewer Free | Google Play

Android端末の方は以下からどうぞ
market://details?id=com.kokufu.android.apps.sqliteviewer.free



2012/06/07

NetBIOS name を使って Samba ディレクトリをマウントする

@ Ubutnu 12.04 LTS

Windows の共有ディレクトリを Linux からマウントする場合、以下のように IP アドレス直指定ならうまくいきます cifs filesystem がないと言われる場合には、smbfs をインストールする必要があります。
$ sudo apt-get install smbfs

$ sudo mount -t cifs //ip_address/dir mnt/mnt_point

しかし、Server が DHCP でアドレスを割り当てられている場合、この方法はかなり面倒くさいです。
Windows ではアドレス欄に
\\servername\dir
と打てば良かったのに…

というわけで、同じように NetBIOS name を使用してマウントできる方法を調べました。

2012/06/04

Ubuntu software center が消えた

@ Ubuntu 12.04 LTS

多分、Gimp がらみでいろいろいじっていたからだと思うのですが、ふと気づくと Ubuntu software center が unity のランチャに表示されなくなりました。
このアイコンが表示されてるはずなのに無くなった

「まー無いなら無いで良いんだけど」とか思いつつ復活できないかトライしてみました。

2012/06/03

Ubuntu (64bit) で gnome-keyring-pkcs11.so が無いと言われる

Ubuntu 12.04 LTS (64bit) で Wine を起動すると、以下のようなエラーがでてしまいます。

p11-kit: couldn't load module: /usr/lib/i386-linux-gnu/pkcs11/gnome-keyring-pkcs11.so: /usr/lib/i386-linux-gnu/pkcs11/gnome-keyring-pkcs11.so: cannot open shared object file: No such file or directory

一応、起動するので放ったらかしておいたのですが、やはりエラーを放っておくのは思わぬ不具合の原因になるので、直せないものか探してみました。

2012/05/30

Eclipse on Linux でホワイトスペースを可視化する

最近、Ubuntu ネタばかりです。
やはりメインマシンとして Ubuntu を使い始めると、サブとして使っているのとは違う不満(というか要求)が出てくるものですね。

Windows の Eclipse には JStyle というプラグインがあって、White Space (Tab, 全角スペース, 改行等)を以下のように可視化してくれます。
(色が薄くて、画面では見づらいかもしれませんが、エディタ上だと絶妙な色加減です)


ところが、このプラグイン、残念なことに Windows 専用なんです。

Linux 用のプラグインがどこかにないかなぁと探していたら、なんと、Eclipse 3.7M3 以降だとデフォルトで White space 可視化機能が入っているというではないですか!
参考:
Eclipse: Make Tabs visible, Spaces invisible - Stack Overflow


というわけで、使ってみました。

2012/05/29

proxy 越しに sudo を使う


@ Ubuntu 12.04 LTS

proxy 設定の必要なマシンで sudo コマンドを使う場合、ユーザの環境変数が引き継がれないので注意が必要のようです。
例えば、add-apt-repository とかを使う場合、以下のような名前解決が出来ない旨のエラーが出てしまいます。

$ sudo add-apt-repository xxx
pycurl.error: (6, "Couldn't resolve host 'launchpad.net'")

こういうときは、/etc/sudoers に以下を記述してやればオッケー。
Defaults env_keep="http_proxy"
Defaults env_keep+="https_proxy"

注意点としては、
  • sudoers の編集には visudo を使用すること
  • 2番目の env_keep は += であること
  • ユーザの環境で正しく http_proxy, https_proxy が設定されていること
といったところでしょうか。


2012/05/28

Ubuntu で TortoiseGit 風のクライアント

先日、最も使用頻度の高いメインマシンを Windows XP から Ubuntu 12.04 LTS に移行しました。
これまでも Ubuntu を入れているマシンは使っていたので、得に不自由もなく、いやむしろ動作も軽くなり、満足していたのですが、ちょっと不満が出てきました。

TortoiseGit 風のアイコンオーバーレイが欲しい!
必須じゃないんだけど、やっぱりあるとわかりやすい。

ということで、探してみたらありました。
RabbitVCS というらしいです。
早速、以下のサイトを参考にインストールしてみました。

2012/05/26

Ubuntu で FakeRAID/1

先日書いたように、デスクトップマシンを Ubuntu 12.04 LTS にしました。
そのマシンのマザーボードGIGABYTE GA-EP45-UD3Rには FakeRAID 機能がついていて、ついでというのも何ですが、ちょうどHDDも余っていることだし RAID を組んでみようかと思い立ったのです。

OSは単体のSSDにインストールしてあるので、RAIDを組むのはデータ保存用のディスクです。

2012/05/25

Android の アクセスリクエスト は一度許可すると取り消せない

Android で Google のサービス(Google Drive とか Picasa)等にアクセスするアプリケーションは以下のようなアクセスリクエストを要求してきます。

これ、一度「許可」を押してしまうと、取り消す方法がないようです。
正確には、端末をリセットするか root を取ってシステムのデータベースを削除するしかないようです。

参考:

「少なくとも 2.3 までは」と書いてあるので、もしかしたら、Honeycomb 以上だと消せるAPIがあるのかもしれません。


一応、エミュレータかルートを取った端末でのリセット方法が書いてあったのでメモしておきます。

2012/05/05

Ubuntu 12.04 LTS に RADEON HD 4550 ドライバを入れたらデュアルディスプレイが出なくなった

Windows XP マシンとして長年使ってきたデスクトップマシンがあるのですが、XP のサポートもあと2年を切ったし、最近は Ubuntu を使うことも増えていることもあって、そのマシンも Ubuntu に切り替えてみることにしました。

2012/04/16

Android Icon 用 Inkscape テンプレートを作りました

アプリを作ったら絶対に避けて通れないのがアイコンづくり。
センスのある人はきっと簡単にできちゃうんでしょうけど、私はこれがとても苦手です…
あぁ、誰かセンスのある人、アイコン描いてくれないかなぁ。

とまぁ、それはさておき、アイコンを作るときに役立つソフトが、GimpInkscape
え?Photoshop と Illustrator?そんな高いソフトは買えません(; _ ;)

…話がそれ気味ですね。
話を元に戻すと、Inkscape でアイコンを作るとき、Icon Design Guidelines - Android Developers に従ってアイコンを作るわけです。
今回は、そのガイダンスに従って作るために、ガイド(Inkscape の補助線)を予め書き込んだテンプレートを作成してみました。
大した手間ではないですが、毎回作るのはやっぱり面倒くさいですからね。

2012/03/28

Android SDK Tools を Rev. 17 にしたら ClassNotFoundException が発生するようになった

2013/5/28 追記
ADT ver. 22 でも ClassNotFoundException が発生するようになりました。
原因は、この ver. 17 での仕様変更が(バグで)無効になったから…
暫定的なバグのようですが、しばらく直らないかもしれませんので、ご注意ください。
穀風: Eclipse ADT を Ver. 22 にしたら ClassNotFoundException が発生するようになった

1週間ほど前、Android SDK Tools の Rev. 17 がリリースされたとのことで、早速アップデートしてみました。

ところが、これまで動いていたアプリが突然動かなくなってしまったのです。
起動時にいきなり落ちるという悲しい状況。
エラーログは以下のような感じです。

Uncaught handler: thread main exiting due to uncaught exception
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.kokufu.android.apps.xxxx/com.kokufu.android.apps.xxxx.TestActivity}: java.lang.ClassNotFoundException: com.kokufu.android.apps.xxxx.TestActivity in loader dalvik.system.PathClassLoader@44e39248
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
    at android.app.ActivityThread.access$2200(ActivityThread.java:119)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4363)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: com.kokufu.android.apps.xxxx.TestActivity in loader dalvik.system.PathClassLoader@44e39248
    at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
    at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2409)
    ... 11 more

動いていたものに一切手は入れていませんので、原因は明らかに今回のアップデート。
Updated SDK Tools and ADT revision 17 | Android Developers Blog を確認してみても、それらしい記述はないような…
ん? Support Library もアップデートって書いてある。
で、よくよく見てみると、今回落ちている TestActivity は android.support.v4.app.FragmentActivity を継承していました。

2012/03/25

Xperia X10 (SO-01B) をアメリカで Wi-Fi ルータとして使用する方法のまとめ

今回、サンフランシスコに1週間滞在することになったのですが、諸処の事情でネットワークにつながっているのが必須の状態でした。
しかし、ローミングサービスを毎日使うとさすがに利用料が高すぎる…
というわけで、プリペイドSIMを自分のスマートフォンに刺して使えないものかと画策しました。

ところが、私が持っているauのスマートフォンはアメリカでプリペイドSIMを差すことができないらしいのです。
参考 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1264341902


がーーん。
しかし、幸いなことに私には以前2台持ちで契約していた Xperia X10 (SO-01B) があります。
こいつを Wi-Fi ルータにしてやれば私のauスマートフォンも海外で使えるではないですか!
(au のスマフォを使えることが必須だったわけではないのですが、妻と自分の2台使えるようにしたかったので、Wi-Fiルータ化が出来るようにしたかったのです)

というわけで、Xperia を Wi-Fi ルータとして使えるようになったので報告しておきます。
(間に紆余曲折ありましたが、その辺は別ブログにアップしておきました。)

2012/03/05

Android の HTTP クライアントは何を使うべきか?

2015/9/19 追記
Android M では Apache の DefaultHttpClient が使えなくなりました。
OS イメージにはしばらく維持され、コンパイルを通すためのオプションも提供されるようですが、今後新規に作成するアプリでは HttpURLConnection を使うのが良いでしょう。
元ネタは↓
Android's HTTP Clients | Android Developer's Blog

Android の HTTP クライアントは 3つあります。

2012/03/04

タブレット用 AVD が起動しない

@ Windows 7 Professional

Android タブレットを持っていない私、タブレットの動作確認はエミュレータでやるしかないのです。
で、WXGA800 の仮想デバイスを作成しました。

スペックは以下のような感じ。

2012/03/02

ListView は Graphical Layout で作ったまま使ってはいけない

ListView の表示時に無駄が多すぎなのではないか? というエントリを書いたところ、いならさんという方からコメントをいただきました。
【Androidアプリ】AdapterのgetView()が必要以上に呼ばれる件|べっ、別にWeb言語のことなんか好きじゃないんだからねっ!!/// という記事によると、layout_width と layout_height が両方共 fill_parent じゃないと、この現象が起こるとのこと。

まさに、ご指摘の通り!
ListView の height が以下のように wrap_content になっていました。

2012/02/22

Fragment の勉強のためにサンプルアプリを動かしてみた

Google が Fragment を用いた NewsReader というサンプルを提供しているようなので、落として動かして見ました。

まず、以下のリンクの「Download the sample app」から NewsReader.zip をダウンロードしてきます。 http://developer.android.com/training/multiscreen/index.html

2012/02/17

setOnClickListener の実装方法

Android プログラムを書いていると、イベントリスナを実装することは日常茶飯事ですが、「インターフェースを実装した実体であれば何でもよい」という緩い制約のため、いろいろな書き方があります。

普段何気なく使い分けているのですが、どのように使い分けているのか自分の整理も含めて書いてみることにしました。
とりあえず、思いついた4つを書いておきますが、この辺の分け方は恣意的です


  1. 既存のクラスにインターフェースを実装する
    public class MyView extends View
            implements android.view.View.OnClickListener {
        // 他のコンストラクタは省略
        public MyView(Context context) {
            super(context);
    
            setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
        }
    }

    このように、自分自身にインターフェースを実装して、onXXXListener に this を与えてやる方法です。
    この方法、よく見かけるのですが、私は多用しないようにしています。
    例えば、以下のように Activity に実装した場合のことを考えます。

    public class MyActivity extends Activity implements OnClickListener {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            View titleView = findViewById(R.id.title);
            titleView.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
        }
    }

    この場合、Viewの数が増えてきた場合に対応できませんし、それを置いておいたとしても、「titleView をクリックしたら、Activity の onClick が呼ばれる」という状況は分かりにくいこと極まりません。
    私は、「名は体を表す」ように実装してあげるように心がけるべきだと思います。

  2. 匿名クラスを使う 1
    public class MyActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            View titleView = findViewById(R.id.title);
            titleView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                }
            });
        }
    }

    この方法もよく見かけますし、私もよく使います。
    慣れるまではちょっと見にくいかもしれませんが、慣れてしまえば、簡単な処理なら内容をすぐ確認できるため便利です。
    ただ、複雑な処理を書く場合は見にくくなったりする難点があります。
    また、クリックされた時の処理が状態によって変わったりする場合、setOnClickListener を呼ぶたびにインスタンスが生成されるため、多少パフォーマンス的に難ありだと思われます。

  3. 匿名クラスを使う 2
    public class MyActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            View titleView = findViewById(R.id.title);
            titleView.setOnClickListener(showAlertDialog);
        }
    
        private final OnClickListener showAlertDialog = new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                
            }
        };
    }

    「匿名クラスを使う 1」の問題を回避するために私が時々使う方法です。
    メンバ変数に OnClickListener への参照を持たせておくわけです。
    クリックしたときの処理が複雑で長くなる場合や、別々のボタンに同じ処理を持たせたい場合に便利です。
    ただし、メンバ変数を持たせると、いろいろなボタンで使いまわせなくなるので要注意です。
    この記述、あまり見かけないのは、そういう意味でJavaの思想からずれているからかもしれません
    (まー、1番目の方法「既存のクラスにインターフェースを実装する」でも、複数のボタンに対して使いまわすと、同じ問題が起こりますけどね…)
    2012/2/22 追記 「あまり見かけない」というのは勘違いでした。Android のソースコードの中でも結構使っていますね。

    この方法で一番のメリットは、インスタンスの生成が1度きり。というところです。
    Android のようなリソースが限られた環境の場合は、意味がある場合もあります。しかし、メリットとデメリットをよく理解した上で使用しないと痛い目にあうかも…。

    また、この方法、クラスは匿名なのですが、メンバ変数に名前が必要で、その命名が難しいことが難点です。
    私は、setOnClickListener 近辺を読んでいるときに処理の流れがわかるよう、showAlertDialog のように、動作を表す変数名にするようにしているのですが、この方法だと Listener であることが分かりにくくなってしまいます。
    だけど、showAlertDialogListener では意味が変わってしまいます。
    本来なら、 onClickListenerForShowAlertDialog とでも付けるのが良いのでしょうが、「長い割にわかりにくいかなー」と思い採用していません。

  4. リスナクラスを定義する
    public class MyActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            View titleView = findViewById(R.id.title);
            titleView.setOnClickListener(new ShowAlertDialog());
        }
    
        private class ShowAlertDialog implements OnClickListener {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                
            }
        };
    }

    ある意味、一番王道です。
    OnClickListener の実装をきちんと定義してあげるわけですね。
    この問題も、3番同様、名前の付け方が難しいという問題を持っています。

    上記では private なインナークラスとして実装していますが、インナークラスとして実装出来るような場合は、3番の方が使い易いでしょう。(インスタンスの生成タイミングを制御したい場合などは別ですが)
    この方法は様々なクラスで同じイベントリスナを使いたいというような場合に使えます。(そういうケースはあまり多くないと思いますが…)


これらの方法、Activity と View のようにライフサイクルを共にしている場合は問題ありませんが、センサー等にリスナを登録する場合、Activity が見えなくなっても、センサからの参照は生きているということに気を付けてください。
放っておくとOutOfMemoryで落ちてしまいます。
その辺についてはまた別の機会に書こうと思います。

2012/02/07

ListView の表示時に無駄が多すぎなのではないか?

getView が呼ばれるタイミングと動作というエントリで書いたのですが、ListView を表示する時の動作をチェックしていたら少し気になることを見つけました。
先のエントリに載せたコードを動作させたときのログが以下です。

2012/02/06

Android の Adapter#getView が呼ばれるタイミングと動作

Android の開発では、ListView 等を使うことがよくあります。
ListView 等(他には GridView、Gallery など)を使う場合は Adapter を使いますが、その肝となる getView がどのように呼ばれるのか、気になったので調べてみました。

具体的には、以下のような Adapter を作り、実際に動作させた結果を見てみます。

2012/02/02

Android のソースコードを Eclipse から使用できるようにする

Android 4.0 (API Level 14) 以降、Android のソースコードは Android SDK Manager からダウンロードしてくることが出来るようになったようです。

これまでは、repoでソースコードを取ってきて、必要なファイルだけ抜き出して…といったような作業が必要だったのですが、これで大分楽ちんになりました。
(4.0 より前のSDKをベースにして開発する場合は、自分でソースをとってこないといけません)

ただ、このソースコード、インストールするだけではEclipseから参照することができない状態です。
(そのうち改善されると思いますが)
これでは宝の持ち腐れなので、参照できるようにしてあげようと思います。

2012/01/21

Nested weights are bad for performance

突然ですが、私、Eclipse プロジェクトの Warning アイコンが嫌いです。
プロジェクトの横に出ている黄色い三角形のやつです。

Warning が出たままで放っておくなんてありえない!と思います。
徹底的に直して、いつもこのアイコンが出ないようにプロジェクトを作るよう心がけています。
…A型ではないです。
だって、これを放置する習慣がついちゃうと、本当に重要な Warning が出たときに無視してしまうでしょ?

ところが、最近 ADT が XML に lint をかけて警告してくれるようになったのです。
いや、それ自体は良いことです。
ダメな書き方を教えてくれるわけですから。

しかし、
Nested weights are bad for performance
という Warning、修正方法がないみたいです。たぶん。
(参考情報: http://groups.google.com/group/android-developers/browse_thread/thread/9bfd6a5731b038bb/854b654344e382bf?lnk=raot

リンク先のスレッドでも言っていますが、縦方向と横方向が入れ子になるようなレイアウトの場合、 両方に weight 属性を持たせないといけない場合があるはず。
で、その答えが、「ただの Warning だから気にしなくて良いよ」ってのはどうなんでしょうかね。

こういうのは Warning じゃなくて Information に止めておいて欲しい。
または、Java の アノテーションみたいに、「これはわかってるけど、あえてそうしてるの」ってのを明示的に書けるようにしておいて欲しい。
と思います。

と思ったら、Information に変更する方法がありました。結構普通に。

2012/01/17

emulator-arm.exe が起動しない

Android SDK を r16 にしました。で、Emulator を起動しようとすると、
問題が発生したため、emulator-arm.exe を終了します。ご不便をおかけして申し訳ありません。
とのメッセージが。


ネットを調べてみると、メモリが足りないとの情報が。
しかし、2GB近く物理メモリは空いている…

2012/01/16

Google APIs の Javadoc が表示されなくなった

2012/01/19 追記
ごめんなさい。以下に書いてある方法は使えませんでした
この方法を実行した後に実機で動作させようとすると、以下のようなエラーが発生してしまいます。
java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
動確しないで、不確かな情報を載せてしまい申し訳ありません。
言い訳なんですが、ちょうど動作が不安定になるような大きな変更を入れてる最中にJavadocが表示されなくなった事に気づき、結構書き換えてる時だからJavadocが無いと余計不便で調べてみたのです。
で、変更してみたけど、もともとうまく動かないプロジェクトでやってたから動確せず。で別件に手をとられ放置…という流れでした。
そういうのブログに書くなよって話ですよね。いや、お恥ずかしい…




Google APIs [Android 4.0.3] を使うと、Javadoc (インテリセンスっぽいやつ)が表示されず、
Note: This element has no attached source and the Javadoc could not be found in the attached Javadoc.

というようなエラーが表示されてしまいます。

おかしいと思って、ライブラリを右クリック → プロパティ