ユーザーが連絡先アイコンを設定できるようにしたいのですが、ユーザーは写真を撮るか、ギャラリーから選択できます。ここでは 2 つの異なる処理を行いますが、代わりに同じように処理する必要があります。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Constants.TAKE_PHOTO:
if (resultCode == RESULT_OK) {
Uri selectedImage = data.getData();
File file = new File(selectedImage.getPath());
mPhoto = decodeFile(file);
Bitmap croppedImage = cropImage(mPhoto);
Bitmap resized = Bitmap.createScaledBitmap(croppedImage, 100, 100, true);
Bitmap finalPhoto = getRoundedRectBitmap(resized, 100);
imageView.setImageBitmap(finalPhoto);
}
break;
case Constants.CHOOSE_PHOTO:
if (resultCode == RESULT_OK) {
Uri selectedImage = data.getData();
imageView.setImageURI(selectedImage);
}
break;
}
2 番目のケース、CHOOSE_PHOTO は機能します。ギャラリーから写真を選択すると、ImageView に配置されます。問題は、最初のケースで作成したメソッドである TAKE_PHOTO が重要であり、ビットマップが円に再形成され、それに応じてトリミングされることです。小さなサイズの写真の場合、これはまさに私が望んでいた方法で機能しました。主なエラーはメモリ不足でした。SOで調べたところ、これを処理する次の方法が見つかりました。
private Bitmap decodeFile(File f) {
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
//The new size we want to scale to
final int REQUIRED_SIZE = 70;
//Find the correct scale value. It should be the power of 2.
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
scale *= 2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
}
return null;
}
これはビットマップの寸法を取り、ビットマップをメモリにロードする前に記録し、ロードする前にビットマップをスケーリングして、OOM エラーが完全に回避されるようにすると考えました。ただし、コードを実行すると、OOM エラーが実際に発生したかのように、選択のために撮影した写真を確認しようとするとアプリがクラッシュしました。クラッシュ時に次の Logcat がありました。
07-25 11:01:51.396 13054-13054/com.example.android.home E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=0, result=-1, data=Intent { act=inline-data (has extras) }} to activity {com.example.android.home/com.tabletnanny.ChildSelection}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:3322)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3365)
at android.app.ActivityThread.access$1200(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1315)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5059)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.tabletnanny.ChildSelection.onActivityResult(ChildSelection.java:126)
at android.app.Activity.dispatchActivityResult(Activity.java:5242)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3318)
私はこれを数時間にわたって調査してきましたが、ビットマップを効果的にロードする方法をまだ理解していないようです。Android Dev サイトを調べたところ、大きなビットマップを処理するための便利なチュートリアルがありましたが、その解決策は SO でdecodeFile
メソッドで見つけたものと非常に似ていました。ここで何が欠けていますか?