2011年12月5日月曜日

ファイルの拡張子を除外、取得【java】【file】【拡張子】

このような感じでできそうです。

たとえは、ファイルの名前の変更を行うようなダイアログを表示する際には、
拡張子なしのファイル名を表示するのが、おそらくは無難でしょう。
しかし、実際にファイルの名前の変更をする際には、拡張子が必要です。
そのようなときに、下記のようなメソッドが有効です。

    /**
* ファイル名から拡張子を返します。
* @param fileName ファイル名
* @return ファイルの拡張子
*/

public String getSuffix(String fileName) {
if (fileName == null)
return null;
int point = fileName.lastIndexOf(".");
if (point != -1) {
return fileName.substring(point + 1);
}
return fileName;
}
/**
* ファイル名から拡張子除いたファイル名を返します。
* @param fileName ファイル名
* @return 拡張子無しのファイル名
*/

public String removeFileExtension(String filename) {
int lastDotPos = filename.lastIndexOf('.');

if (lastDotPos == -1) {
return filename;
} else if (lastDotPos == 0) {
return filename;
} else {
return filename.substring(0, lastDotPos);
}
}

2011年11月28日月曜日

String.xmlの内容をString型でjavaで扱う【android】【String.xml】【多言語化】

すでにあるvaluesフォルダと同じ階層にvalues-jaを作成し、同じXMLファイルを置いてやることで、
日本語専用のXMLファイルを用意することができ、本体の言語設定に応じて、どちらのXMLファイル
を使用するか選択させることができます。

このような仕組みをandroidでは「多言語化」と呼んでいますが、このような多言語化を行った際に
String.xmlの内容をString型で取得したい。とすぐになります。

一般的なString.xmlファイルからの値の取得方法は、下記のようになりますが、これでは、R.java
に記載されている「id」しか取得できません。

R.string.select_dir
※select_dirはString.xmlに定義されているものとします。

この解決方法として、android.content.Context.getStringメソッドを使用する方法があります。

String str = getString(R.string.select_dir);

としてやることで、String型でString.xmlファイルから値の取得ができます。


この方法は、Activity内では上記のように使用することができますが、共通部品のような、他の
クラスではContextが見つけられない事から、getStringメソッドが見つけられないため、使用
することができません。その場合のひとつの解決方法として、共通部品の引数にContextを増やし、
引数で、thisを渡してあげることで、解決することができます。

2011年11月20日日曜日

画像を画面サイズに合わせる(縮尺・縮小する)の続き【android】【画像表示】【エラー】

以前の投稿の続きです。↓
⇒画像を画面サイズに合わせる(縮尺・縮小する)【android】【画像表示】【エラー】

以前、紹介した画像を画面サイズに合わせる方法ですが、いざ、自分で使ってみると
GC(ガーベッジコレクション)が画像毎に発生して、処理が非常に遅いという問題
が発生しました。
※画像表示処理もそこそこに遅いのに、GCがさらに悪化させているようでした。

なんとかGCの発生を抑制したくいろいろ調べた結果、Bitmap作成処理を下記のように
書き換えることで、GCの発生を抑え、処理時間を短くすることができました。

以前の方法では、画像をそのままBitmapに読み込んでから縮尺していたようで、
メモリにごみができやすいという問題があったようです。
今回は画像のサイズをあらかじめ読み込んでおき、画像の読み込みのタイミングで
縮尺しているので、メモリを無駄なく使用することができます。

あと、不本意ではあるのですが、androidでは短命なオブジェクトや変数を生成しない
ようにしたほうがパフォーマンスがあがるという情報を得て、できるだけクラス変数
で、変数を宣言するようにしています。
※ほかにも下記のようなパフォーマンス対策がありました。
  ・setterやgetterは使用しない。
  ・オブジェクトを作成しない(コードはベタ書きすべき)。
  ・処理が遅くなっても問題ない箇所でGCするようにする。
  ・定数はfinalで宣言する。

ただし、そのままこの情報を受け取ってコーディングをすると、非常に見づらい
コードとなってしまいそうなので何か対策を立てる必要がありそうです。


    //setBitmap変数
Bitmap bmImage;
int zoomWidth;
int zoomHeight;

/**
* ディレクトリリストに表示するBitmapを設定する。
* @param File file(設定するBitmapファイル)
* @return Bitmap bmImage(設定されたBitmap)
* @exception なし
*/

public Bitmap setBitmap(File file){
// ビットマップ作成オブジェクトの設定
BitmapFactory.Options bmfOptions = new BitmapFactory.Options();
// RGBでそれぞれ 5/6/5 ビットの色を使用(メモリ対策)
bmfOptions.inPreferredConfig = Config.RGB_565;
// アプリケーション内でのピクセル密度を設定
bmfOptions.inScreenDensity = DisplayMetrics.DENSITY_LOW;
// 画像の大きさだけ取得
bmfOptions.inJustDecodeBounds = true;
bmImage = BitmapFactory.decodeFile(file.getPath(),bmfOptions);

// 画面のサイズの1/4で画像を縮尺するよう、縮尺率を設定
if (displayMetrics != null) {
zoomWidth = (int)Math.floor(bmfOptions.outWidth / (displayMetrics.widthPixels / REDUCTION_SIZE));
zoomHeight = (int)Math.floor(bmfOptions.outHeight / (displayMetrics.heightPixels / REDUCTION_SIZE));
bmfOptions.inSampleSize = Math.max(zoomWidth, zoomHeight);
}
// 画像そのものを設定された縮尺率で取得
bmfOptions.inJustDecodeBounds = false;
bmImage = BitmapFactory.decodeFile(file.getPath(),bmfOptions);

return bmImage;
}
}

2011年11月7日月曜日

画像を画面サイズに合わせる(縮尺・縮小する)【android】【画像表示】【エラー】

以前の投稿の続きです。↓
⇒java.lang.OutOfMemoryError: bitmap size exceeds VM budget【android】【画像表示】【エラー】 の続き


画像の表示について追記します。

以前、画像の縮小について下記の方法を書きましたが、

// 画像を1/20サイズに縮小(メモリ対策)
bmfOptions.inSampleSize = 20;


実際、表示されるすべての画像を均一に縮小するやり方はよくないということで、
画面の表示サイズを取得し、そこから必要に応じて縮小するやり方を紹介します。
以前紹介した、etBitmap(File file)を下記に変更してみました。
改善点等ございましたら、ご教授くださいませ。

    public Bitmap setBitmap(File file){
// ビットマップ作成オブジェクトの設定
BitmapFactory.Options bmfOptions = new BitmapFactory.Options();
// RGBでそれぞれ 5/6/5 ビットの色を使用(メモリ対策)
bmfOptions.inPreferredConfig = Config.RGB_565;
// GridViewの要素が横に3つ並ぶ想定で、余白も考慮し、画像の縮尺サイズを1/4に設定
// 画面のサイズに縮尺した後に、1/4にさらに縮尺
int reductionSize = Const.COLUMN_IMAGE_GRID_VIEW + 1;

if (metrics == null) {
// 現在の表示メトリクスの取得
DisplayMetrics dm = this.getResources().getDisplayMetrics();
// ビットマップのサイズを現在の表示メトリクスに合わせる(メモリ対策)
bmfOptions.inDensity = dm.densityDpi;
}
// システムメモリ上に再利用性の無いオブジェクトがある場合に勝手に解放(メモリ対策)
bmfOptions.inPurgeable = true;
// システム側で設定されているピクセル密度を無視して設定値を元に画像がスケール
bmfOptions.inScreenDensity = DisplayMetrics.DENSITY_LOW;

// 画像ファイルオブジェクトとビットマップ作成オブジェクトから、ビットマップオブジェクト作成
Bitmap bmImage = BitmapFactory.decodeFile(file.getPath(),bmfOptions);

if (metrics != null) {
float imageWidth = (float)bmImage.getWidth() / (float)metrics.widthPixels;
float imageHeight = (float)bmImage.getHeight() / (float)metrics.heightPixels;
float imageScale = Math.max(imageWidth, imageHeight);
if (imageScale > (1 / reductionSize)){
int newImageWidth = (int)((bmImage.getWidth() / imageScale) / reductionSize);
int newImageHeight = (int)((bmImage.getHeight() / imageScale) / reductionSize);
bmImage = Bitmap.createScaledBitmap(bmImage,newImageWidth,newImageHeight,false);
}else{
bmImage = Bitmap.createScaledBitmap(bmImage,bmImage.getWidth(),bmImage.getHeight(),false);
}
}
return bmImage;
}




【クラス変数宣言】
private DisplayMetrics metrics;


【onCreateメソッドで】
metrics = new DisplayMetrics();
display.getMetrics(metrics);




と、こんな感じです。
Const.COLUMN_IMAGE_GRID_VIEWは画面に表示している画像の列数です。
私のアプリでは、画像が3列表示されているので、余白も考え、
画面のサイズ/4 のサイズに縮小しています。
画面いっぱいいっぱいのサイズなら、reductionSizeを1にするとよいでしょう。

如何でしょうか?やっつけで作ったので、ちょっと不安ですが、
一応、今のところ、元気に動いているようですw

2011年10月31日月曜日

アプリにSDカードへの書き込み権限を付与する【android】【SDカード】【権限】

SDカードに書き込みを行う為には、下記の内容を AndroidManifest.xml に書いておく必要があります。


    </application>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>



他にも、下記のような権限の設定が可能です。


権限の名前 内容
android.permission.ACCESS_COARSE_LOCATION 低精度の位置情報の取得
android.permission.ACCESS_FINE_LOCATION 高精度の位置情報の取得
android.permission.ACCESS_MOCK_LOCATION デバッグ用の位置情報の取得
android.permission.CONTROL_LOCATION_UPDATES 位置情報の更新
android.permission.ACCESS_NETWORK_STATE ネットワーク状態を取得
android.permission.ACCESS_WIFI_STATE WiFiの状態を取得
android.permission.BLUETOOTH BlueToothを操作
android.permission.BLUETOOTH_ADMIN BlueToothの探索と接続
android.permission.CALL_PHONE 電話のダイアル(救急と警察を除く)
android.permission.CALL_PRIVILEGED 電話のダイアル(救急と警察を含む)
android.permission.PROCESS_OUTGOING_CALLS 電話の発信処理への介入
android.permission.MODIFY_PHONE_STATE 電話の状態の書き換え
android.permission.VIBRATE バイブ機能の利用
android.permission.DEVICE_POWER 低水準電源管理の利用
android.permission.WAKE_LOCK 高水準電源管理の利用
android.permission.CAMERA カメラの利用
android.permission.RECORD_AUDIO 音声録音の利用
android.permission.MODIFY_AUDIO_SETTINGS 音声機能の設定の書き換え
android.permission.FORCE_BACK 「戻る」ボタンに相当する処理
android.permission.READ_INPUT_STATE キーとスイッチの直接の読み込み
android.permission.INTERNET インターネットへの接続
android.permission.WRITE_GSERVICES Google mapサービスの利用
android.permission.READ_HISTORY_BOOKMARKS 履歴とお気に入りの読み込み
android.permission.WRITE_HISTORY_BOOKMARKS 履歴とお気に入りの書き込み
android.permission.SET_TIME 日付と時刻の設定
android.permission.SET_TIME_ZONE タイムゾーンの設定
android.permission.READ_CONTACTS 「連絡先」データの読み込み
android.permission.WRITE_CONTACTS 「連絡先」データの書き込み
android.permission.WRITE_SETTINGS 「設定」データの書き込み
android.permission.MOUNT_FORMAT_FILESYSTEMS SDカードのフォーマット
android.permission.MOUNT_UNMOUNT_FILESYSTEMS SDカードのマウント・アンマウント
android.permission.WRITE_EXTERNAL_STORAGE SDカードの書き込み
android.permission.REBOOT Androidの再起動
android.permission.RECEIVE_BOOT_COMPLETED Androidの起動完了の検出

2011年10月24日月曜日

TextViewの文字列を一行に収め、改行しないようにする【android】【TextView】【Layout】

TextViewの内容をユーザが入力する場合、想定されたサイズを超過して、
2行に渡り表示されてしまうようなことが、しばしばあります。

このようなときに、長い文字列の先頭や中間、最後について「…」に
置き換えて表示するオプションがTextViewに存在しています。

android:scrollHorizontally="true"
android:ellipsize="start"

scrollHorizontally については固定で"true"を設定し、ellipsize
について、先頭を省略したい場合は"start",中間を省略したい場合は"middle"、
最後を省略したい場合は、"end"を指定します。


たとえば、下記のように設定すると、画面の操作で入力されたテキストについて、
先頭が「…」で省略され、表示されます。

    <TextView android:id="@+id/textview11"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
android:layout_gravity="left"
android:layout_marginLeft="2dip"
android:layout_marginTop="2dip"
android:textColor="@color/white"
android:textSize="35dip"
android:textStyle="bold"
android:scrollHorizontally="true"
android:ellipsize="start"
/>

Re-installation failed due to different application signatures.【android】【エラー】【実機】

私はHTC製の端末を普段使用しておりますが、その端末で開発したアプリの
デバッグをしてみようとしたところ、下記のようなメッセージか出力され、
インストールできませんでした。

Re-installation failed due to different application signatures.

上記の原因は、前回インストールしたPCとは違うPCから端末へアプリケーションの
インストールする場合、あらかじめ、端末からそのアプリケーションをアンインストール
する必要があるとの事でした。

実際に、端末の操作でアンインストールを行った後にインストールを行うと
正常にインストールが完了しました。


【ドコモ HTC端末でデバッグ】
http://wikiwiki.jp/android/?%A5%C9%A5%B3%A5%E2%20HTC%C3%BC%CB%F6%A4%C7%A5%C7%A5%D0%A5%C3%A5%B0#driver

【コラム:Androidアプリ開発初心者がつまずきやすい7のポイント】
http://www.dm-android.com/column/begginer.html

2011年10月17日月曜日

Error generating final archive: Debug Certificate expired on…【Eclipse】【開発環境】【エラー】

Android のアプリを eclipse で作っていると何かをトリガーに
下記のエラーが発生することがあります。

… Error generating final archive: Debug Certificate expired on …

私は、マシンの電源を手動で消してしまったことがおそらくの原因でした。
しばらく、開発環境を使っていなくてもなるそうです。


このような類のエラーは大抵、更新とクリーンで何とかなるものが多いのですが、
上記のエラーに関してはそれではうまくいかなかったので、解決方法をご紹介いたします。


①: C:\Documents and Settings\XXXX\.android の下にある
   debug.keystore を削除する
②: Windows の時計のタイムゾーンの設定が「大阪,札幌,東京」
   となってるのを,適当に違うタイムゾーンに変更する(一時的に)
   例えば「東部標準時」とかにする.
③: Project メニューの Clean... を実行する.これで debug.
   keystore が作り直される.
④: タイムゾーンを元に戻す.


参考:http://d.hatena.ne.jp/hypercrab/20100619/1276925032

2011年10月11日火曜日

colors.xml設定集【android】【colors.xml】【values】

アプリ内の色を管理する「colors.xml」の設定集です。
使うたびに探すのは非常にめんどくさいので、ここから必要なものをとってくるとよいでしょう。

情報入手元リンク
http://stackoverflow.com/questions/3769762/android-color-xml-resource-file



<?xml version="1.0" encoding="utf-8"?> 
<resources>
<color name="White">#FFFFFF</color>
<color name="Ivory">#FFFFF0</color>
<color name="LightYellow">#FFFFE0</color>
<color name="Yellow">#FFFF00</color>
<color name="Snow">#FFFAFA</color>
<color name="FloralWhite">#FFFAF0</color>
<color name="LemonChiffon">#FFFACD</color>
<color name="Cornsilk">#FFF8DC</color>
<color name="Seashell">#FFF5EE</color>
<color name="LavenderBlush">#FFF0F5</color>
<color name="PapayaWhip">#FFEFD5</color>
<color name="BlanchedAlmond">#FFEBCD</color>
<color name="MistyRose">#FFE4E1</color>
<color name="Bisque">#FFE4C4</color>
<color name="Moccasin">#FFE4B5</color>
<color name="NavajoWhite">#FFDEAD</color>
<color name="PeachPuff">#FFDAB9</color>
<color name="Gold">#FFD700</color>
<color name="Pink">#FFC0CB</color>
<color name="LightPink">#FFB6C1</color>
<color name="Orange">#FFA500</color>
<color name="LightSalmon">#FFA07A</color>
<color name="DarkOrange">#FF8C00</color>
<color name="Coral">#FF7F50</color>
<color name="HotPink">#FF69B4</color>
<color name="Tomato">#FF6347</color>
<color name="OrangeRed">#FF4500</color>
<color name="DeepPink">#FF1493</color>
<color name="Fuchsia">#FF00FF</color>
<color name="Magenta">#FF00FF</color>
<color name="Red">#FF0000</color>
<color name="OldLace">#FDF5E6</color>
<color name="LightGoldenrodYellow">#FAFAD2</color>
<color name="Linen">#FAF0E6</color>
<color name="AntiqueWhite">#FAEBD7</color>
<color name="Salmon">#FA8072</color>
<color name="GhostWhite">#F8F8FF</color>
<color name="MintCream">#F5FFFA</color>
<color name="WhiteSmoke">#F5F5F5</color>
<color name="Beige">#F5F5DC</color>
<color name="Wheat">#F5DEB3</color>
<color name="SandyBrown">#F4A460</color>
<color name="Azure">#F0FFFF</color>
<color name="Honeydew">#F0FFF0</color>
<color name="AliceBlue">#F0F8FF</color>
<color name="Khaki">#F0E68C</color>
<color name="LightCoral">#F08080</color>
<color name="PaleGoldenrod">#EEE8AA</color>
<color name="Violet">#EE82EE</color>
<color name="DarkSalmon">#E9967A</color>
<color name="Lavender">#E6E6FA</color>
<color name="LightCyan">#E0FFFF</color>
<color name="BurlyWood">#DEB887</color>
<color name="Plum">#DDA0DD</color>
<color name="Gainsboro">#DCDCDC</color>
<color name="Crimson">#DC143C</color>
<color name="PaleVioletRed">#DB7093</color>
<color name="Goldenrod">#DAA520</color>
<color name="Orchid">#DA70D6</color>
<color name="Thistle">#D8BFD8</color>
<color name="LightGrey">#D3D3D3</color>
<color name="Tan">#D2B48C</color>
<color name="Chocolate">#D2691E</color>
<color name="Peru">#CD853F</color>
<color name="IndianRed">#CD5C5C</color>
<color name="MediumVioletRed">#C71585</color>
<color name="Silver">#C0C0C0</color>
<color name="DarkKhaki">#BDB76B</color>
<color name="RosyBrown">#BC8F8F</color>
<color name="MediumOrchid">#BA55D3</color>
<color name="DarkGoldenrod">#B8860B</color>
<color name="FireBrick">#B22222</color>
<color name="PowderBlue">#B0E0E6</color>
<color name="LightSteelBlue">#B0C4DE</color>
<color name="PaleTurquoise">#AFEEEE</color>
<color name="GreenYellow">#ADFF2F</color>
<color name="LightBlue">#ADD8E6</color>
<color name="DarkGray">#A9A9A9</color>
<color name="Brown">#A52A2A</color>
<color name="Sienna">#A0522D</color>
<color name="YellowGreen">#9ACD32</color>
<color name="DarkOrchid">#9932CC</color>
<color name="PaleGreen">#98FB98</color>
<color name="DarkViolet">#9400D3</color>
<color name="MediumPurple">#9370DB</color>
<color name="LightGreen">#90EE90</color>
<color name="DarkSeaGreen">#8FBC8F</color>
<color name="SaddleBrown">#8B4513</color>
<color name="DarkMagenta">#8B008B</color>
<color name="DarkRed">#8B0000</color>
<color name="BlueViolet">#8A2BE2</color>
<color name="LightSkyBlue">#87CEFA</color>
<color name="SkyBlue">#87CEEB</color>
<color name="Gray">#808080</color>
<color name="Olive">#808000</color>
<color name="Purple">#800080</color>
<color name="Maroon">#800000</color>
<color name="Aquamarine">#7FFFD4</color>
<color name="Chartreuse">#7FFF00</color>
<color name="LawnGreen">#7CFC00</color>
<color name="MediumSlateBlue">#7B68EE</color>
<color name="LightSlateGray">#778899</color>
<color name="SlateGray">#708090</color>
<color name="OliveDrab">#6B8E23</color>
<color name="SlateBlue">#6A5ACD</color>
<color name="DimGray">#696969</color>
<color name="MediumAquamarine">#66CDAA</color>
<color name="CornflowerBlue">#6495ED</color>
<color name="CadetBlue">#5F9EA0</color>
<color name="DarkOliveGreen">#556B2F</color>
<color name="Indigo">#4B0082</color>
<color name="MediumTurquoise">#48D1CC</color>
<color name="DarkSlateBlue">#483D8B</color>
<color name="SteelBlue">#4682B4</color>
<color name="RoyalBlue">#4169E1</color>
<color name="Turquoise">#40E0D0</color>
<color name="MediumSeaGreen">#3CB371</color>
<color name="LimeGreen">#32CD32</color>
<color name="DarkSlateGray">#2F4F4F</color>
<color name="SeaGreen">#2E8B57</color>
<color name="ForestGreen">#228B22</color>
<color name="LightSeaGreen">#20B2AA</color>
<color name="DodgerBlue">#1E90FF</color>
<color name="MidnightBlue">#191970</color>
<color name="Aqua">#00FFFF</color>
<color name="Cyan">#00FFFF</color>
<color name="SpringGreen">#00FF7F</color>
<color name="Lime">#00FF00</color>
<color name="MediumSpringGreen">#00FA9A</color>
<color name="DarkTurquoise">#00CED1</color>
<color name="DeepSkyBlue">#00BFFF</color>
<color name="DarkCyan">#008B8B</color>
<color name="Teal">#008080</color>
<color name="Green">#008000</color>
<color name="DarkGreen">#006400</color>
<color name="Blue">#0000FF</color>
<color name="MediumBlue">#0000CD</color>
<color name="DarkBlue">#00008B</color>
<color name="Navy">#000080</color>
<color name="Black">#000000</color>
</resources>

2011年9月19日月曜日

java.lang.OutOfMemoryError: bitmap size exceeds VM budget の続き【android】【画像表示】【エラー】

前回の続きです。前回↓
⇒java.lang.OutOfMemoryError: bitmap size exceeds VM budgetandroid】【画像表示】【エラー】

Activityの状態遷移(ライフサイクル)というのは、いったいどのようなものなのでしょうか。
世のサンプルソースにはonCreateメソッドのメソッドばかり実装したものが多く、
他のメソッドはどのように実装すればよいのでしょうか。

そのヒントになるのが、@IT様の下記の記事です。
⇒Androidアプリ作成の基本“Activity”とは何か?

下記のイメージ図は上記サイトの転載です。
























onCreateメソッドを実行することで、基本的に実行中までアプリの状態が遷移することから、
通常のアプリでは、onStartメソッドやonRestartメソッドは実装しなくてよさそうです。
※私自身探り探り調べながらやっていますので、何か情報持っている方は共有していただければ幸いです。


下記の場合、onPauseメソッドやonStopメソッド、onDestroyメソッドが呼ばれそうなので、
そのタイミングで、不要なデータをクリアする処理を入れるとリソースを有効的に使えそうです。

【onPauseメソッドやonStopメソッド、onDestroyメソッドが呼ばれそうなタイミング】
 ・アプリケーションを終了
 ・画面の向きを変えることでの再表示
 ・戻るボタン
 ・次の画面に遷移



何か情報が入れば追記します。

2011年9月10日土曜日

java.lang.OutOfMemoryError: bitmap size exceeds VM budget【android】【画像表示】【エラー】

下記にこの記事の内容に関連する記事があります。ご参考ください。
⇒画像を画面サイズに合わせる(縮尺・縮小する)



カメラで撮影した画像のような高画質な画像を表示すると、たびたび下記のような
メッセージが出力され、アプリケーションが強制終了してしまいます。


09-10 06:27:57.701: ERROR/dalvikvm-heap(2168): 7680000-byte external allocation too large for this process.
09-10 06:27:57.701: ERROR/GraphicsJNI(2168): VM won't let us allocate 7680000 bytes
09-10 06:27:57.712: DEBUG/skia(2168): --- decoder->decode returned false
09-10 06:27:57.732: DEBUG/AndroidRuntime(2168): Shutting down VM
09-10 06:27:57.732: WARN/dalvikvm(2168): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): FATAL EXCEPTION: main
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459)
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:271)

※EclipseのDDMSのLogCatにLogは表示されています。


この場合の対処方法として、下記のようなものがあげられます。
 ・Bitmap.Configの設定をARGB_8888をやめて、RGB_565やARGB_4444を使用する(デフォルトRGB_565)
  これらは解像度の設定。
 ・inSampleSizeを設定し、画像ファイルのサイズを小さくして表示する。

  BitmapFactory.Options bmfOptions = new BitmapFactory.Options();
  bmfOptions.inSampleSize = 4;

  とすると、1辺4分の1のサイズとなり、面積は16分の1。

 ・システムメモリ上に再利用性の無いオブジェクトがある場合に勝手に解放するように設定する。
  bmfOptions.inPurgeable = true;

 ・ビットマップのサイズを現在の表示メトリクスに合わせる。
  DisplayMetrics dm = this.getResources().getDisplayMetrics();
  bmfOptions.inDensity = dm.densityDpi;

 ・使わなくなったタイミングでBitmapデータの解放を行う。
  Bitmap.recycle();
  ※Bitmap変数をクラス変数として持ち、onPause()メソッドでBitmap.recycle();
   とすればよいですが、System.gc()でよい気もします。

 ・ガーベッジコレクションを行う。
  System.gc();


ざっとこんなところですが、Bitmap.recycle()は使用したことがないので、情報いただければ幸いです。



私は今のところ下記のような対処を行い、OutOfMemoryErrorを防いでいます。
(不要な処理もありかもしれません)

①ビットマップ設定メソッドで、BitmapFactory.Optionsの設定を行う。
    /**
* ディレクトリリストに表示するBitmapを設定する。
* @param File file(設定するBitmapファイル)
* @return Bitmap bmImage(設定されたBitmap)
* @exception なし
*/

private Bitmap setBitmap(File file){

// ビットマップ作成オブジェクトの設定
BitmapFactory.Options bmfOptions = new BitmapFactory.Options();
// ARGBでそれぞれ0~127段階の色を使用(メモリ対策)
bmfOptions.inPreferredConfig = Config.ARGB_4444;
// 画像を1/20サイズに縮小(メモリ対策)
bmfOptions.inSampleSize = 20;
// システムメモリ上に再利用性の無いオブジェクトがある場合に勝手に解放(メモリ対策)
bmfOptions.inPurgeable = true;
// 現在の表示メトリクスの取得
DisplayMetrics dm = this.getResources().getDisplayMetrics();
// ビットマップのサイズを現在の表示メトリクスに合わせる(メモリ対策)
bmfOptions.inDensity = dm.densityDpi;
// 画像ファイルオブジェクトとビットマップ作成オブジェクトから、ビットマップオブジェクト作成
Bitmap bmImage = BitmapFactory.decodeFile(file.getPath(),bmfOptions);

return bmImage;
}

 

②アプリケーション終了時(戻るボタン押下時など)にSystem.gc();を行う。
 ※次回、Activityのライフサイクルも含めて説明します。



日本Androidの会がOutOfMemoryErrorについて纏めてくださっております。
http://mtnk.org/down/PDF/OutOfMemoryError.pdf

2011年9月5日月曜日

ListViewの一行をクリックし、別の画面に遷移【android】【ListView】【画面遷移】

ListViewの一行をクリックし、別の画面に遷移する場合には、
onListItemClick()をオーバーライドします。
※別の方法もあるようですが、この方法が比較的綺麗にコーディングできそうです。

オーバーライドしたonListItemClick()の中で、intentインスタンスを作成し、
startActivity()を実行します。
Intent intent = new Intent(遷移元のクラス.this, 遷移先のクラス.class);
と作成してください。

Intent.putExtra()を使用することにより、値の受け渡しも可能です。

    /**

* クリックされたListに対して、ImageListViewに遷移する。
* (非 Javadoc)
* @see android.widget.AdapterView$OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long)
* @param AdapterView parent(未使用)
* @param View view(未使用)
* @param int position(クリックされたポジション)
* @param long id(未使用)
* @return void
* @exception なし
*/

@Override
public void onListItemClick(ListView listView, View v, int position,long id) {
super.onListItemClick(listView, v, position, id);

String dir = dirList.get(position);
Log.v("onClick", String.format("onListItemClick: %s", dir));

// ディレクトリリストからクリックされたディレクトリを取得
String imageDirPath = dirList.get(position);
// ImageListViewクラスに、ディレクトリを渡す為のIntentを作成
Intent intent = new Intent(DirListView.this, ImageGridView.class);
// Intentにクリックされたディレクトリを設定
intent.putExtra("IMAGE_DIR_PATH", imageDirPath);
// ImageListViewに遷移
startActivity(intent);
}

2011年9月4日日曜日

別パッケージのActivityに遷移【android】【画面遷移】【エラー】

前回の続きです。前回↓

⇒android.content.ActivityNotFoundException

別Activityに遷移する際、前回記載した
        </activity>

<activity android:name="ImageListView"></activity>


では同様のエラーとなり、Activityを見つけることができず、エラーとなってしまいます。
これは、AndroidManifest.xmlの 「「package="」は1つしか記述できないようですので、2つ目からはパッケージ込みで記述する必要があります。


上記をまとめると下記となります。

【現象】
別パッケージのActivityに遷移しようとするとエラーになる。

【LogCat】
…android.content.ActivityNotFoundException: Unable to find explicit activity class
※デバイス上でのログは、EclipseのDDMSのLogCatに表示されます。

【原因】
AndroidManifest.xmlに遷移先のアクティビティをパッケージ込みで記述していない為、
AndroidManifest.xmlに遷移先のアクティビティが設定されていないと判断されている。

【解決策】
AndroidManifest.xmlに遷移先のアクティビティを設定する。
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jp.co.vacaposi.android.iv.iv.iv0010"
android:versionCode="1"
android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".DirListView"
android:label="@string/app_name">

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="jp.co.vacaposi.android.iv.iv.iv0020.ImageGridView"></activity>
</application>
<uses-sdk android:minSdkVersion="7" />
</manifest>

android.content.ActivityNotFoundException【android】【画面遷移】【エラー】

この投稿の続きがあります↓

⇒別パッケージのActivityに遷移【android】【画面遷移】【エラー】


デバイス上でのログは、EclipseのDDMSのLogCatに表示されます。

【現象】
画面遷移時に「…has stopped unexpectiedly. Please try again.」というダイアログが表示され、
アプリケーションが終了してしまう。

【LogCat】
…android.content.ActivityNotFoundException: Unable to find explicit activity class 
※デバイス上でのログは、EclipseのDDMSのLogCatに表示されます。

【原因】
AndroidManifest.xmlに遷移先のアクティビティが設定されていない。

【解決策】
AndroidManifest.xmlに遷移先のアクティビティを設定する。



        </activity>

<activity android:name="ImageListView"></activity>

2011年8月29日月曜日

ファイルの拡張子をチェック【java】【file】【チェック処理】

取得したファイルが画像であるかどうかを拡張子から判断します。
画像拡張子リストに宣言されている文字列の中に一致するものがあれば、trueを返します。
このチェック処理ではあくまでファイル名のチェックであり、中身が本当に画像であるか、
または読み取り可能であるか等のチェックは行っておりません。

画像拡張子リストを変更すれば、別の拡張子にも使用できます。

import java.io.File;


public class Check {
protected boolean checkImageFile(File checkedFile){
// チェック結果
boolean checkResultFlag = false;
// 画像拡張子リスト
final String[] IMAGE_EXTENSION_ARRAY = {".bmp",".gif",".jpg",".jpeg",".png"};

// nullチェック
if(checkedFile == null){
return checkResultFlag;
}
// isFileチェック
if(!checkedFile.isFile()){
return checkResultFlag;
}
// ファイル名取得チェック
if(checkedFile.getName() == null || checkedFile.getName().length() == 0){
return checkResultFlag;
}
// ファイルの末尾が画像拡張子リストの中にあるかチェック
for(int i=0;i<IMAGE_EXTENSION_ARRAY.length;i++){
if (checkedFile.getName().endsWith(IMAGE_EXTENSION_ARRAY[i].toLowerCase()) ||
checkedFile.getName().endsWith(IMAGE_EXTENSION_ARRAY[i].toUpperCase())){
checkResultFlag = true;
break;
}
}
return checkResultFlag;
}
}

2011年8月22日月曜日

複数の要素(View)を重ねて表示の続き【android】【FrameLayout】【重ねて表示】

前回の続きです。前回↓
⇒複数の要素(View)を重ねて表示

前回は、1つのImageViewの上に、1つのTextViewを表示していましたが、
今度は、複数のImageViewの上に、1つのTextViewを表示してみます。

気をつけないといけない点は、custom_list_item.xml内のそれぞれの
ImageViewについては重なってはいけない、という点です。

その為、FrameLayoutの中でそれぞれのImageViewを、LinearLayoutで
囲んでいます。
※画像を横並びにする為に、android:orientation="horizontal"を
指定しています。)

結果、下記のように表示されました。


















■custom_list.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"
android:layout_height="fill_parent">

<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
/>

</FrameLayout>




■custom_list_item.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:paddingLeft="2dip"
android:paddingRight="2dip">

<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<ImageView
android:id="@+id/imageview"
android:layout_width="50dip"
android:layout_height="50dip"
android:scaleType="centerCrop"
android:padding="2dip"
android:layout_gravity="left"
android:layout_marginRight="2dip"
/>

<ImageView
android:id="@+id/imageview2"
android:layout_width="50dip"
android:layout_height="50dip"
android:scaleType="centerCrop"
android:padding="2dip"
android:layout_gravity="left"
android:layout_marginRight="2dip"
/>

<ImageView
android:id="@+id/imageview3"
android:layout_width="50dip"
android:layout_height="50dip"
android:scaleType="centerCrop"
android:padding="2dip"
android:layout_gravity="left"
android:layout_marginRight="2dip"
/>

<ImageView
android:id="@+id/imageview4"
android:layout_width="50dip"
android:layout_height="50dip"
android:scaleType="centerCrop"
android:padding="2dip"
android:layout_gravity="left"
android:layout_marginRight="2dip"
/>

<ImageView
android:id="@+id/imageview5"
android:layout_width="50dip"
android:layout_height="50dip"
android:scaleType="centerCrop"
android:padding="2dip"
android:layout_gravity="left"
android:layout_marginRight="2dip"
/>

<ImageView
android:id="@+id/imageview6"
android:layout_width="50dip"
android:layout_height="50dip"
android:scaleType="centerCrop"
android:padding="2dip"
android:layout_gravity="left"
android:layout_marginRight="2dip"
/>

</LinearLayout>
<TextView android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
android:layout_gravity="left"
android:layout_marginLeft="2dip"
android:layout_marginTop="2dip"
android:textColor="@color/white"
android:textSize="35dip"
android:textStyle="bold"
/>

</FrameLayout>

2011年8月18日木曜日

複数の要素(View)を重ねて表示【android】【FrameLayout】【重ねて表示】

次回に下記をカスタマイズした記事があります。
⇒複数の要素(View)を重ねて表示の続き

画像に重ねて文字を出力したいときなど、Viewを重ねて表示する場合には、
FrameLayout』を使用します。

SDカードの画像格納ディレクトリ一覧を表示する画面をイメージしたレイアウトが
下記になります。
後から宣言されたViewが上に表示されます。


















■custom_list_item.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"
android:layout_height="fill_parent">

<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
/>

</FrameLayout>
 
 
■custom_list_item.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:paddingLeft="2dip"
android:paddingRight="2dip">

<ImageView
android:id="@+id/imageview"
android:layout_width="50dip"
android:layout_height="50dip"
android:scaleType="centerCrop"
android:padding="2dip"
android:layout_gravity="left"
/>

<TextView android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"
android:layout_gravity="left"
android:layout_marginLeft="2dip"
android:layout_marginTop="2dip"
android:textColor="@color/white"
android:textSize="35dip"
android:textStyle="bold"
/>

</FrameLayout>