2013/11/27

Android の Files と Cache の違い

Android はアプリの情報を格納するための場所として、以下のようなメソッドを提供しています。
それぞれ、以下のようなパスになります。Xperia Acro HD (SO-03D) で動作させてみた結果。デバイスによって異なる可能性があります。
getFilesDir()
/data/data/com.kokufu.android.test.exstoragetest/files

getExternalFilesDir()
/mnt/sdcard/Android/data/com.kokufu.android.test.exstoragetest/files

getCacheDir()
/data/data/com.kokufu.android.test.exstoragetest/files/cache

getExternalCacheDir()
/mnt/sdcard/Android/data/com.kokufu.android.test.exstoragetest/files/cache

見てのとおり、ほぼ同じディレクトリを表しているのですが、どう違うのでしょうか?

getCacheDir() の JavaDoc には、以下のように書かれています。

Returns the absolute path to the application specific cache directory on the filesystem. These files will be ones that get deleted first when the device runs low on storage. There is no guarantee when these files will be deleted.
Note: you should not rely on the system deleting these files for you; you should always have a reasonable maximum, such as 1 MB, for the amount of space you consume with cache files, and prune those files when exceeding that space.

(意訳)
アプリ固有のキャッシュディレクトリの絶対パスを返します。ここに格納されているファイルは、ストレージの容量が少なくなった場合削除されます。いつ削除されるかは保証されていません。
Note: システムがこれらのファイルを消すことを期待してはいけません。妥当な上限(たとえば 1MB など)を決め、キャッシュファイルがそれらの値を超えるようであれば、あなたが削除しなければなりません。


つまり、Cache ディレクトリは勝手に消される可能性があるけれど、いつ消されるかは保証されていないってことですね。
逆に言うと、Files ディレクトリはシステムに勝手に消されることはありません。

しかし、忘れてはいけないのが以下の画面の存在。

設定 → アプリ

この画面で「データを削除」を選択された場合、有無を言わさず Files ディレクトリ以下が(Cache ディレクトリも含めて)削除されてしまいます。
システムに勝手に消されることは無いけれど、ユーザに消されることはあるということです。



2013/11/26

Raspberry Pi に の pulse-audio で音がブツブツ切れるので USB DAC (LXU-OT2) をつないでみた

我が家の Raspberry Pi に pulse-audio を入れてみました。

pulse-audio のインストール
$ sudo apt-get install pulseaudio pulseaudio-module-zeroconf 

pulse-audio で再生。
$ paplay /usr/share/sounds/alsa/Rear_Right.wav
すると、音がブツブツ途切れるではありませんか。
全く使い物になりません。

ALSA で再生してみる。
$ aplay /usr/share/sounds/alsa/Rear_Right.wav
こちらは、ちゃんと再生されます。

pulse-audio のバージョンとかいろいろ考えたのですが、とりあえず別の DAC で試してみるのはどうかと思いつきました。
というのも、先日買った Stereo (2013年1月号) という雑誌に USB-DAC (LXU-OT2) が付録でついていて、活用できていなかったので付録につられて買っただけです。オーディオマニアではありません。

Raspberry Pi の上に重ねてみると、調度良い大きさ。

早速、USB で接続してみました。
USB-DAC を使用する方法はいろいろありますが、今回は使い物にならないデフォルトの音声出力を切ってしまうことにしました。
以下のように、1行コメントアウトするだけです。

/etc/modules
#snd-bcm2835

USB-DAC を使って pulse-audio で再生してみると、音が途切れること無く再生されました。
検索しても同じような症状を見つけられなかったので、私の Raspberry Pi のハード的な欠陥なのかもしれません。

ちなみに、 Stereo (2013年1月号) は月刊誌なので今では手に入りにくいようですただ、今調べたところ、10000円くらいで売りに出てるサイトもありました。再販したんでしょうか?
ちなみに、最初のお値段は 2800円でした。


以下なんかが代替商品になるかもしれません。

上海道場【初段】 超小型 手のひらサイズ USB DAC (D/Aコンバーター DAコンバーター) Donyaダイレクト DN-USBDAC ZY [メ04] |【上海問屋】通販サイト

購入していないのでなんとも言えませんが…
購入したらレビューしたいと思います。

2013/11/25

Android のソースコードでバージョン間の差分を簡単に確認する方法

Android の良い所は、いざとなったら OS のコードまで追っていくことが出来ることですNexus や エミュレータ以外では必ずしも正確ではありませんが。
アプリが不思議な動作をした時も自分のコードが悪いのか、OSのバグなのか追うことが可能です。
例えば、私は先日 MultiSelectListPreference の不思議な動作に出会い、結局 Android のバグであることに気づきました。

上記のバグ、特定の Android のバージョンだけで起こるのです。
そういう時に役に立つのが、バージョン間の比較を行うことの出来るサイト。

私は GrepCode というサイトを利用させてもらっています。
Android に限らず 様々なオープンソースプロジェクトのソースコードを保持していて、ブラウザ上で簡単にバージョン間の差分チェックができます。

Android のソースコードは以下。
GrepCode: android - Java Project - Source Code

2013/11/24

Dialog Theme を適用した Activity に ActionBar を表示する

Android でダイアログを表示する際、DialogFragment を使用するのではなく、Activity に Dialog Theme を適用して表示することが出来ます。
何かのリザルトを表示する時等、使い方によっては大変便利です。

ところで、せっかく Activity を使っているのだから、メニューを表示したいと思うのは私だけでしょうか?
Android 2.x 系だとメニューボタンを押したら、下からニュッとメニューが表示されるので、Dialog Theme を適用した Activity でもメニューを使用する事が出来ます。
しかし、Android 3.x から導入されたメニューは ActionBar。 Dialog Theme を適用すると表示されなくなってしまいます。

とはいえ、物は Activity なので、以下のように Custom Theme を作成することで、Action Bar を復活させることが可能です。
2013/11/21

MultiSelectListPreference にバグがあり、勝手に選択解除されることがある

Android の MultiSelectListPreference、便利なのですが致命的なバグがあることがわかりました。
以下のような手順で操作をすると、勝手に選択が解除されます。
場合によっては Preference の内容も書き換えてしまいます。

この問題は少なくとも 4.1.1_r1 で直っています。
2013/11/16

Eclipse に .project の無い既存の Android プロジェクトをインポートする

@Eclipse Juno SR2
@ADT Rev. 22.3
@Android SDK Rev. 19

以前、「Eclipse に既存の Android プロジェクトをインポートする」というエントリで以下のように書きました。

.project ファイルがない場合は何も表示されません。その場合は、Eclipse でインポートできるサンプル等ではないので、別の方法で Eclipse に取り込んでやる必要があります。

その後、「別の方法」が提供されたので書いておこうと思います結構すぐに出来るようになったのですが、書こうと思いながら大分時間が経ってしまいました…

File → New → Other...

Android → Android Project from Existing Code

Root Directory を入力

選択したディレクトリを再帰的に検索してプロジェクト一覧が表示されます。
この時、プロジェクト名は AndroidManifest.xml 内で宣言されているアプリ名になります。
別の名前にしたい場合は、ここで変更することも可能です。

Finish を選択すると、選択したプロジェクトがインポートされます。

2013/11/14

Android SDK をアップデートしたら BufferOverflowException が出るようになった

最近、ちょっと古い Android Project を Eclipse で実行しようとすると以下のようなエラーが起こるようになりました。

Android Console の出力
[2013-11-14 22:04:14 - Dex Loader] Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
[2013-11-14 22:04:14 - LifeCycleTest] Conversion to Dalvik format failed: Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.

調べてみると、Eclipse を再起動してみろとか、いろいろ書かれているのですが…

私の環境では再起動してもダメで、以下のように Project Build Target を最新にしてやるとうまく動くようになりました。

Project → Properties → Android → Project Build Target


エラーの内容からすると、生成された dex ファイルに問題がある様子。
ということは、Build に失敗しているわけで、心当たりを探してみると、一つ思い当たることが。

先日、Android SDK のバージョンを 19Android 4.4 KitKat にした時に、古い Android SDK Build-tools を全て Delete したのです。
Android SDK Build-tools Rev. 19 以外が Not installed


時間が無くて調べきれていませんが、対応する Android SDK Build-tools が無いと、正しく dex ファイルが生成できないのではないかと思われます。


追記
ちょっと気になったので確認してみましたが、結論としては Android SDK Build-tools は関係なく、現時点(2013/11/14) の最新SDK Android SDK Tools Rev. 22.3
Android SDK Platform-tools Rev. 19
では Project Build Target が API 15Android 4.0.3 以前の Project のビルドにはことごとく失敗します。
Android SDK をアップデートしたら、Project Build Target もアップデートしないといけないようです。

そもそも、Project Build Target のバージョンはなるべく最新に保ち、Deprecated なものなどに気を配って開発していくべきですので、あまり問題はないと思いますが、リリース直前の複数のプロジェクトを抱えているとやっかいなことになりそうです。
まぁ、そういう場合は SDK のインストールディレクトリから分けるべきなのでしょう。。。