とりあえず雑記帳(跡地)
Android
最終更新:
fujiyan
-
view
(作成中)
WebコミックLibraryhttp://web-comi.appspot.com/ GAE/JとSlim3で作成してみた、各出版社から配信されているWebコミックをまとめて閲覧できるサイトです。只今、実験運用中… |
参考サイト
ActivityとView
- Activityは、画面を表す。
- ViewはUIを構成する部品。ActivityにViewを設定することで、画面を構築する。
- Viewの構成方法は2つ
- (静的)レイアウトXMLを記述してコンパイルしたものを設定。お手軽。通常はこっち
- (動的)Viewオブジェクトを適宜生成して設定。前もって作成するViewが決まらない場合はこっち。
XMLでViewを定義
- res/layout以下に.xmlファイルを作成
- 作成すると、R.layout.[ファイル名]という定数名で、作成したViewを表すIDが定義される(ファイル名がmain_layout.xmlなら、R.layout.main_layoutという定数が定義される)。
- 定義されたIDをActivity#setContentView()に渡す。
- 複数のView定義が必要な場合は、その分だけxmlファイルを作れば良い。
画面切り替え
参考
アンドロドロ
アンドロドロ
- バックボタンで前画面に戻したい場合はActivity切り替えで実装。バックボタンを押すと、アクティブなActivityに対してfinish()が呼び出され、直前のActivityがアクティブになる。ブラウザの「戻る」感覚だろうから、こっちが通常なんでしょう。
- グローバルリソース(カメラ等)の取得/解放は、よほどの事情が無い限り、onResume()/onPause()で行うこと。
- でも、カメラでよくやるような、SurfaceHolderのsurfaceCreated()/surfaceDestroyed()は、Activity切り替え時のタイミングで呼ばれるっぽいので、ここでカメラの取得/解放を行っても大丈夫っぽい(あやふや)。
Activityを2つ用意するのか、1つのActivity内でViewFlipperを使うかは悩み中。多分、メモリ管理を細かく制御して、OSに負担を掛けないようにするのはActivity2つなんでしょう。次画面のActivity起動時に次画面用のリソースを取得、前画面のリソースを解放とか、onStop()/onRestart()でリソースの一時解放/再取得とか。ViewFlipperの場合は、全ての画面のリソースをまとめてメモリにロードするんじゃないかと。
アプリケーションの終了
- 単一Activityの場合はfinish()で良い。
- 複数Activityの場合は、最後に開始したActivityから順次finish()していき、最後にroot Activityをfinish()させるのが良いと思う。
- これは、Activityはスタックに詰まれていくことに由来。LIFOでfinish()していく。
- 多分、ActivityからTaskを終了させる方法は無い。何故なら、Activityは、さまざまなTaskから呼ばれることを想定しているため、自分を呼んだTaskを勝手に終了させるわけにはいけないから、かと。
- moveTaskToBack()でTaskをバックグラウンドに追いやって、そのうちOSに掃除してもらう、という方法もある。こっちがAndroidの標準だ、という話もあるけど、何となく、うーん。
- だって、この方法だと、再起動したときに、前の状態から開始されてしまうし…。
- moveTaskToBack()はあくまで「中断」であり、「終了」はやっぱり地道にfinish()していくべきだと思うの
- 一般的な実装としては、startActivityForResult()でchild Activityを開始し、child Activityの終了後に呼ばれるonActivityResult()で、自身もfinish()する
- System.exit(0)で終わらせてはゼッタイダメ。
カメラ(Android 2.1 API Level 7)
AndroidManifest.xmlの記述
参考
プログラマのネタ帳
プログラマのネタ帳
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.flash" />
uses-permissionで、カメラ利用の許可が必要であることを宣言し、残りの3つでカメラ、オートフォーカス、フラッシュの機能を使用することを宣言します。
また、Activityの属性に下記を追加。
android:screenOrientation="landscape" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
screenOrientationの設定は、なんか、カメラは水平でしか使えないらしいため…。
themeの設定は、アプリをフルスクリーン表示にするため。カメラアプリは基本的にフルスクリーン。
themeの設定は、アプリをフルスクリーン表示にするため。カメラアプリは基本的にフルスクリーン。
MediaStore.Images.Media.insertImage()で保存すると画質が落ちる
参考
日本Androidの会
日本Androidの会
画像を加工しない場合は、生成されたjpegデータをそのまま保存する。
// Camera#takePicture()の第3引数に渡す、コールバックオブジェクト private Camera.PictureCallback pictureListener = new Camera.PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { try { insertImageToMediaStore(data); } catch (IOException e) { throw new RuntimeException(e); } //後処理を記述 } }; // dataに格納されたjpegデータを保存 private void insertImageToMediaStore(byte[] data) throws IOException { ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); ByteArrayInputStream in = new ByteArrayInputStream(data); try { int size; final int BUFFER_SIZE = 8192; byte[] buffer = new byte[BUFFER_SIZE]; BufferedOutputStream out = new BufferedOutputStream(resolver.openOutputStream(uri)); try { while ((size = in.read(buffer, 0, buffer.length)) > 0) { out.write(buffer, 0, size); } out.flush(); } finally { out.close(); } } finally { in.close(); } }
画像を加工して保存
- なんか、下の方法みたいに、カメラの撮影サイズでBitmapの別インスタンスを生成すると、メモリ不足で落ちるっぽいぞ…。エミュレーション環境では普通に動くけど、実機でカメラ撮影後に突然落ちるような場合は原因の一つとして疑ってみてもいいかも
- コールバックメソッドに渡されるjpegデータをBitmapに変換して、Canvasで描画をする。その後、Bitmapをjpegで保存する。
- jpeg→ビットマップ→jpegの変換を行うので、画質が落ちたり、ファイルサイズが増えたり…。
- BitmapFactory.decodeByteArray()で作るBitmapがimmutableなため、copy()でmutableなBitmapを再作成する。
- API Level 11なら、decodeByteArray()のオプションでmutableなBitmapを直接作れるかも?
// Camera#takePicture()の第3引数に渡す、コールバックオブジェクト private Camera.PictureCallback pictureListener = new Camera.PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { Bitmap orgBmp = BitmapFactory.decodeByteArray(data, 0, data.length); Bitmap bmp = orgBmp.copy(Bitmap.Config.ARGB_8888, true); Canvas canvas = new Canvas(bmp); // canvasで描画 try { insertImageToMediaStore(bmp); } catch (IOException e) { throw new RuntimeException(e); } camera.startPreview(); } }; // Bitmapをjpegで保存 private void insertImageToMediaStore(Bitmap bmp) throws IOException { ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); BufferedOutputStream out = new BufferedOutputStream(resolver.openOutputStream(uri)); try { bmp.compress(Bitmap.CompressFormat.JPEG, 100, out); out.flush(); } finally { out.close(); } }
GPSとジオコーディング(Android 2.1 API Level 7)
- LocationManagerを取得する。
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
onLocationChanged()が呼ばれなくなる
- LocationManager#removeUpdates()を呼ばずにActivityを終了させると、次回起動時にonLocationChanged()が呼ばれなくなるらしいです。必ず呼びましょう。
配布と署名
- アプリケーションはapkファイルにパッケージングして配布する。
- 署名付きapkファイルじゃないと、端末にインストールされません。
署名のためのkeytool使用法
- keyalgで指定するアルゴリズムはDSAとRSAがサポートされているらしい。通常はRSAにしておきましょう。
- keysizeについては2048以上を推奨とされています。
- validityで指定する有効期限については、10000日以上を推奨されています。
ということで、推奨されるkeytoolのオプションは
keytool -genkey -v -keystore [keystoreファイル名] -alias [エイリアス] -keyalg RSA -keysize 2048 -validity 10000
- 1つのkeystoreに対して、複数の鍵を生成できる。
- keystoreの中で、鍵を識別するためにエイリアスを用いる。
- なので例えば、keystoreファイル名はワークスペース名、エイリアスはプロジェクト名(=アプリケーション名)、みたいな感じにすると良い(あくまで例)。
keytool -genkey -v -keystore workspace.keystore -alias app1 -keyalg RSA -keysize 2048 -validity 10000 keytool -genkey -v -keystore workspace.keystore -alias app2 -keyalg RSA -keysize 2048 -validity 10000
- keystoreファイルやパスワードは失くしたり忘れたりしないようにね
あれ、keytoolいらなくね?(ADT Plugin for Eclipseがあれば)
- apkを作成したいアプリのプロジェクトのルートのコンテキストメニューから、[Export...]→[Android]-[Export Android Application]を選択する。
- [Project Checks]で、何もエラーが無いことを確認して[Next>]
- [Keystore selection]では、最初にkeystoreファイルを作る場合は[Create new keystore]を選択
- [Location]には、keystoreファイルのフルパスを入力
- 失くさないように、ワークスペース内に、keystoreファイル格納用のプロジェクトを作成し、そこに作成すると良いかも。
- [Password]と[Confirm]には、keystoreファイルにアクセスするためのパスワードを入力する。
- [Location]には、keystoreファイルのフルパスを入力
- [Key Creation]では、下記を入力
- [Alias]には鍵のエイリアスを入力。まぁ普通はアプリケーション名
- [Password]と[Confirm]には、鍵にアクセスするためのパスワードを入力する。
- [Validity]には年を入力するので注意。推奨は25年以上です。
- [First and Last Name]から[Country Code (XX)]については、どれか1つにでも入力すればOK。
- [Destination and key/certificate checks]では、下記を入力
- [Destination APK file]に、出力するapkファイルをフルパスで入力。
あらまぁ簡単