2010年08月30日

Android SDKバージョンの違いによる落とし穴

つい先日、Androidアプリのバージョンアップを行ったところ、1.5端末で落ちるという報告がいくつも届いた。
修正は微々たるもので、Manifestのターゲットを変えるなどもしておらず、なぜ発生するのかが不明だったのだが、ようやく判明。

調査の結果、Android SDKのバージョンによる落とし穴であった。

以前まではandroid-sdk-r3-windowsのSDK(android2.0まで対応しているSDK)を使用しており、作成するアプリがmin-sdkが3でtarget-sdkが4のアプリのため、問題なく開発できていたのだが、最近、開発用PCの移動に伴い最新版のandroid-sdk-r6-windowsのSDK(2.2対応しているもの)をダウンロードし、使用し始めていた。

問題は、以前までのSDKは1.5端末であってもdrawable-mdpiを見に行くように動いていたのだが、最新版では見に行かなくなってしまい、画像がありませんというエラーで強制終了となってしまう。
回避策としては、drawable-mdpiではなく、drawableに画像を入れてあげることで1.5端末でも問題なくなる。

完全なテスト不足なのだが、動作していたものが動かなくなるのはきつい。。。
今後はベースの環境を変える際はより一層の注意を払います。。。

yoshike2 at 14:48|PermalinkComments(0)TrackBack(0)この記事をクリップ!Android | YourGolf

2010年08月24日

Androidのカメラプレビュー時の向きについて

Androidのカメラのプレビュー時の向き指定を縦にするべく、色々と苦しめられましたので、分かったことを共有します。

結論。

Activityをlandscapeにすること!

今まで、以下のようにパラメータをセットして、縦表示に対応してきました。
params.set("orientation", "portrait");
しかし!!端末によって動作するものと動作しないもののが結構あることがわかりました。DroidとかDroid Xとか。NexusOneでも2.1と2.2で動作が違ったりとか。

なので、カメラを縦表示プレビューにどうしてもしたい場合はActivityをlandscapeにし、ボタンやら画像やらテキストやらは力技で縦表示にあわせるしかありません。
画像の場合は、画像の向きを-90度回転させて表示すればオーケー。
テキストやボタンはサイズを縦、横変えてあげて、文字列はonDrawメソッドでcanvasを-90度回転させましょう。

やっかいなのはダイアログです。
アニメーションで回転させてsetFillAfter(true)でいけるかなと思いましたが、駄目です。回転後に向きが元に戻っちゃいます。
カスタムレイアウトをダイアログにはめ込んで縦表示にみせかけるという方法も駄目です。ダイアログはデフォルト真ん中に表示されますが、表示位置をずらそうとしても、どうしてかダイアログ上部に空白ができてしまいます。
縦表示をした時に幅が細いダイアログか、位置が左によったダイアログになってしまします。
ちなみに表示位置は、dialog.getWindow().getAttributes()で取得したAttributeのxやyを変えることで調整できます。

結局、行った方法としてはダイアログは使わずダイアログもどきのレイアウトを作成。表示してダイアログと同じ動きになるよう対応しました。

ちなみに、Activityをダイアログのthemeで表示することでも対応できるかと思います。今回はActivityを分けたくなかったので使いませんでしたが。


Android 2.2からは新たにsetDisplayOrientationメソッドが導入されたので、2.2以上のみターゲットということでしたら、こいつを使えば良いかと思います。

もしかしたらもっとスマートに縦表示できる方法があるかもしれません。
ご存知の方はコメントお願いします。

yoshike2 at 15:48|PermalinkComments(0)TrackBack(0)この記事をクリップ!Android | カメラ

Dorid & Droid X 端末でMapが強制終了してしまう件

Androidのアプリ開発を行っていると、特定の端末のみで発生するエラーに出くわすことがあります。

先日対応したバグもDroid, Droid X 端末でのみ(もしかしたら他にもあるかもしれませんが)発生していたバグだっためメモしておきます。

該当バグはGoogleMap表示時に落ちていたエラーで、以下のようなバグレポートが送信されておりました。

java.lang.ClassCastException: android.graphics.drawable.BitmapDrawable
at com.google.android.maps.MyLocationOverlay.getLocationDot(MyLocationOverlay.java:180)
at com.google.android.maps.MyLocationOverlay.drawMyLocation(MyLocationOverlay.java:561)
at com.google.android.maps.MyLocationOverlay.draw(MyLocationOverlay.java:511)


GoogleMapを使用し、MyLocationOverlayを使っているアプリでは共通して発生するかと思います。
悩ましい問題でしたが、他にも同様な問題に直面した方がおり、対応方法は以下のページを参考にさせて頂きました。
Android applications that use the MyLocationOverlay class crash on the new Droid X

上記ページの対応により、無事エラーがなくなりました。
同様の問題にはまっている方は参考にしていただければと思います。

yoshike2 at 15:11|PermalinkComments(0)TrackBack(0)この記事をクリップ!Android | YourGolf

2010年07月05日

Android 2.2のSDへのアプリインストールについて

Android2.2から可能になったSDへのアプリインストールですが、アプリ側で対応が必要とのことでしたので、メモとして残します。

簡単です。
AndroidManifest.xmlファイルへ
android:installLocation="preferExternal"
を記述するだけでOKです。

preferExternalを指定することで、SDへアプリをインストールするように設定できます。ただし、100%保証する訳ではなく、SDの容量がフルの場合などは内部に保存されます。

preferExternal以外には"auto"や"internalOnly"を指定することができます。

"auto"に設定した場合は、デフォルトでは端末内部に保存されますが、容量がフルの場合やユーザーが設定から移動する場合にSD上へ保存されます。

"internalOnly"では必ず内部に保存され、容量がフルの場合はインストールに失敗します。


実際に指定をする場合は、プロジェクトの設定でターゲットをAPI Level 8に変更し、上記内容をManifestへ指定、android:minSdkVersionにサポートしたい最小バージョンを指定してあげるとOKです。


以上です。
詳細は以下リンクを参考にしてください。

App Install Location
http://developer.android.com/intl/ja/guide/appendix/install-location.html

android:installLocation
http://developer.android.com/intl/ja/guide/topics/manifest/manifest-element.html#install


※2010/07/15追記
SDへ保存したアプリの領域にアクセスしたい場合は、新たにAPIが追加されてます。
public abstract File getExternalFilesDir (String type)
また、SDですのでアクセスする場合はstorage stateの確認が必要になります。
そして、一番重要なこととして、端末内のアプリ領域と違って全てのアプリケーションがこの領域への読み書き権限があります。つまりセキュリティレベルが違うので注意が必要とのことです。

yoshike2 at 16:29|PermalinkComments(0)TrackBack(0)この記事をクリップ!Android | 新機能

2010年06月25日

データフォルダからの動画(音声)再生方法について

データフォルダからの動画再生についてはまったのでメモ残します。

動画を再生する場合、SDカードに保存したファイルを読み込むのは問題ないのですが、データフォルダから再生するにはいくつかハードルが存在します。
(※ただでさえ端末の容量少ないんだから、そんなとこに動画なんて置かないよ!!というのはごもっともの意見というのはもちろん承知しておりますので・・・。)

SDと同じ方法で、データフォルダに置いたファイルをMediaPlayerで再生しようとすると再生できません。
なぜかというとPermissionが原因です。
下記にも記述されておりますが、MediaPlayerはセキュリティー上ルートアクセス権限がないため、アプリのデータフォルダにはアクセスできません。
File permission about MediaPlayer


どうしようかと思いましたが、そういえば・・・
新規作成ファイルのパーミッションについて
こんなのがあったなぁと思い出し、早速コードを引用させてもらいexecメソッドを使いMediaPlayerへパーミッションを付与してみました。
裏技的だし、問題ないかなぁと不安をかかえつつもEmulatorで確認し、オーケー!
Xperiaでも問題なく再生でき、これで問題解決!!



・・・・・・・・・と
・・・・・・・・・思
・・・・・・・・・い
・・・・・・・・・ま
・・・・・・・・・し
・・・・・・・・・た
・・・・・・・・・が



HTC Desireでアウト!NexusOneでもOut!!
execメソッド実行でエラー出ちゃいました。
やはり、裏技は良ろしくないということですね。


さて、これからどうしようと困ったのですが、上記一番初めに記載したリンク先のポストをもう一度見返すと、
Your app can explicitly grant MediaPlayer temporary access to secure
files by opening the file and passing the file descriptor to
MediaPlayer using the setDataSource(FileDescriptor fd) method.
と書いてます。
なるほど。FileDescriptorを使えば良いんですね。

というわけで、FileDescriptorを使用して動画再生実行!

        ・
        ・
        ・
        ・
        ・

再生できません・・・。
MediaPlayerのsetDataSourceでnullなcontentはopenできないよと言われ、落ちちゃいます・・・。
ここからなんでだーと、調べても分からず、相当な時間を費やしてしまいましたが、先程解決しました。
NG、OKなパターンはそれぞれ以下になります!


<NGなパターン>
FileInputStream is = new FileInputStream(file);
FileDescriptor fd = is.getFD();
mp.setDataSource(fd);

<OKなパターン>
mp.setDataSource(new FileInputStream(file).getFD());


ちなみにmp.setDataSource(is.getFD());もダメです。
とりあえずこれで再生できるようにはなったのですが、なぜこうしないと再生できないのか理由が分からない・・・。
どなたか分かる方がいたらぜひご教授頂きたいです。


yoshike2 at 19:28|PermalinkComments(0)TrackBack(0)この記事をクリップ!Android | 動画