写真を撮り、その写真をサーバーにアップロードするアプリを作成しようとしています。ここまでは順調ですね。問題は、最初の写真をアップロードした後に別の写真を撮りたいときです。OutOfMemory エラーのように見えますが、私の人生では理解できません。
public class HomePage extends Activity implements OnClickListener {
private static final int TAKE_PICTURE = 0;
private Uri mUri;
private Bitmap mPhoto;
TextView welcomeText;
String username;
// Alert Dialog Manager
AlertDialogManager alert = new AlertDialogManager();
// Session Manager Class
SessionManagement session;
// Button Logout
Button btnLogout;
// Photo File
File photoFile;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// Session class instance
session = new SessionManagement(getApplicationContext());
// Check that user is logged in
session.checkLogin();
// get user data from session
HashMap<String, String> user = session.getUserDetails();
// username
username = user.get(SessionManagement.KEY_USERNAME);
welcomeText = (TextView) findViewById(R.id.welcometext);
((Button) findViewById(R.id.snap)).setOnClickListener(this);
((Button) findViewById(R.id.rotate)).setOnClickListener(this);
((Button) findViewById(R.id.upload)).setOnClickListener(this);
// Button logout
((Button) findViewById(R.id.btnLogout)).setOnClickListener(this);
welcomeText.setText("Hello, " + username);
}
@Override
これは、ボタンを開始した場所です。R.id.snap で写真を撮影し、R.id.upload ボタンでアップロードします。R.id.rotate を無視します。
public void onClick(View v) {
if (v.getId()== R.id.snap) {
Intent i = new Intent("android.media.action.IMAGE_CAPTURE");
photoFile = new File(Environment.getExternalStorageDirectory(), username + ".jpg");
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
mUri = Uri.fromFile(photoFile);
startActivityForResult(i, TAKE_PICTURE);
}
else if(v.getId() == R.id.rotate)
{
if (mPhoto!=null) {
Matrix matrix = new Matrix();
matrix.postRotate(90);
mPhoto = Bitmap.createBitmap(mPhoto , 0, 0, mPhoto.getWidth(), mPhoto.getHeight(), matrix, true);
((ImageView)findViewById(R.id.photo_holder)).setImageBitmap(mPhoto);
}
}
else if (v.getId() == R.id.upload)
{
try {
welcomeText.setText("Uploading image");
executeMultipartPost();
//welcomeText.setText("Upload Complete");
} catch (Exception e) {
// TODO Auto-generated catch block
welcomeText.setText("Upload Failed");
e.printStackTrace();
}
}
else if (v.getId() == R.id.btnLogout)
{
session.logoutUser();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PICTURE:
if (resultCode == Activity.RESULT_OK) {
getContentResolver().notifyChange(mUri, null);
ContentResolver cr = getContentResolver();
try {
mPhoto = android.provider.MediaStore.Images.Media.getBitmap(cr, mUri);
((ImageView)findViewById(R.id.photo_holder)).setImageBitmap(mPhoto);
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
}
そして、これがファイルのアップロードが行われる場所です。
@SuppressWarnings("deprecation")
public void executeMultipartPost() throws Exception {
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(
"http://www.neurobomber.com/cfc/upload_nologin.php?method=post");
ImageView jpgView = (ImageView)findViewById(R.id.photo_holder);
Bitmap bitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
jpgView.setImageBitmap(bitmap);
FileBody bin = new FileBody(photoFile);
MultipartEntity reqEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
//Adding the file and username to be sent to the server
reqEntity.addPart("userfile", bin);
reqEntity.addPart("username",new StringBody(username));
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
HttpEntity entity = response.getEntity();
InputStream webs = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(webs, "iso-8859-1"),8);
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
welcomeText.setText(s);
} catch (Exception e) {
// handle exception here
//infotext.setText("Uploading image");
Log.e(e.getClass().getName(), e.getMessage());
}
}
}
クラッシュした後のログ出力は次のとおりです。
07-16 01:36:27.236: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$START@40105c38,-1,0,-1,0)
07-16 01:36:27.236: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$END@4010fa20,-1,0,-1,0)
07-16 01:36:27.236: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$START@40105c38,-1,0,-1,0)
07-16 01:36:27.236: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$END@4010fa20,-1,0,-1,0)
07-16 01:36:27.256: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$START@40105c38,-1,0,-1,0)
07-16 01:36:27.256: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$END@4010fa20,-1,0,-1,0)
07-16 01:36:27.256: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$START@40105c38,-1,0,-1,0)
07-16 01:36:27.256: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$END@4010fa20,-1,0,-1,0)
07-16 01:36:27.256: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$START@40105c38,-1,0,-1,0)
07-16 01:36:27.256: I/[POST_RESELECT](3783): [spanChange] (o, oldStart, newStart, oldEnd, newEnd)=(android.text.Selection$END@4010fa20,-1,0,-1,0)
07-16 01:36:36.045: D/dalvikvm(3783): GC_EXTERNAL_ALLOC freed 127K, 48% free 2833K/5447K, external 0K/0K, paused 41ms
07-16 01:36:37.607: D/dalvikvm(3783): GC_EXTERNAL_ALLOC freed 53K, 49% free 2788K/5447K, external 12444K/14492K, paused 23ms
07-16 01:36:38.157: D/dalvikvm(3783): DexOpt: couldn't find static field
07-16 01:36:38.157: W/dalvikvm(3783): VFY: unable to resolve static field 3345 (INSTANCE) in Lorg/apache/http/message/BasicHeaderValueParser;
07-16 01:36:38.157: D/dalvikvm(3783): VFY: replacing opcode 0x62 at 0x001b
07-16 01:36:38.167: D/dalvikvm(3783): VFY: dead code 0x001d-0043 in Lorg/apache/http/entity/ContentType;.parse (Ljava/lang/String;)Lorg/apache/http/entity/ContentType;
07-16 01:36:38.167: D/dalvikvm(3783): DexOpt: couldn't find static field
07-16 01:36:38.167: W/dalvikvm(3783): VFY: unable to resolve static field 3339 (INSTANCE) in Lorg/apache/http/message/BasicHeaderValueFormatter;
07-16 01:36:38.167: D/dalvikvm(3783): VFY: replacing opcode 0x62 at 0x0015
07-16 01:36:38.167: D/dalvikvm(3783): VFY: dead code 0x0017-001c in Lorg/apache/http/entity/ContentType;.toString ()Ljava/lang/String;
07-16 01:36:54.453: D/dalvikvm(3783): GC_CONCURRENT freed 91K, 46% free 3029K/5575K, external 24888K/26936K, paused 2ms+1ms
07-16 01:36:54.483: D/dalvikvm(3783): GC_EXTERNAL_ALLOC freed 4K, 46% free 3025K/5575K, external 24888K/26936K, paused 31ms
07-16 01:36:54.493: E/dalvikvm-heap(3783): 12742656-byte external allocation too large for this process.
07-16 01:36:54.493: E/dalvikvm(3783): Out of memory: Heap Size=5575KB, Allocated=3025KB, Bitmap Size=24888KB, Limit=32768KB
07-16 01:36:54.493: E/dalvikvm(3783): Trim info: Footprint=5575KB, Allowed Footprint=5575KB, Trimmed=844KB
07-16 01:36:54.493: E/GraphicsJNI(3783): VM won't let us allocate 12742656 bytes
07-16 01:36:54.513: D/dalvikvm(3783): GC_FOR_MALLOC freed 181K, 49% free 2843K/5575K, external 24888K/26936K, paused 19ms
07-16 01:36:54.513: D/skia(3783): --- decoder->decode returned false
07-16 01:36:54.513: D/AndroidRuntime(3783): Shutting down VM
07-16 01:36:54.513: W/dalvikvm(3783): threadid=1: thread exiting with uncaught exception (group=0x4001d5a0)
07-16 01:36:54.523: E/AndroidRuntime(3783): FATAL EXCEPTION: main
07-16 01:36:54.523: E/AndroidRuntime(3783): java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=7367KB, Allocated=2843KB, Bitmap Size=24888KB)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:690)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:749)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:560)
07-16 01:36:54.523: E/AndroidRuntime(3783): at com.neurobomber.photothrice.HomePage.onActivityResult(HomePage.java:145)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.app.Activity.dispatchActivityResult(Activity.java:4010)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.app.ActivityThread.deliverResults(ActivityThread.java:2879)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.app.ActivityThread.handleSendResult(ActivityThread.java:2925)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.app.ActivityThread.access$2000(ActivityThread.java:132)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1063)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.os.Handler.dispatchMessage(Handler.java:99)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.os.Looper.loop(Looper.java:143)
07-16 01:36:54.523: E/AndroidRuntime(3783): at android.app.ActivityThread.main(ActivityThread.java:4196)
07-16 01:36:54.523: E/AndroidRuntime(3783): at java.lang.reflect.Method.invokeNative(Native Method)
07-16 01:36:54.523: E/AndroidRuntime(3783): at java.lang.reflect.Method.invoke(Method.java:507)
07-16 01:36:54.523: E/AndroidRuntime(3783): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
07-16 01:36:54.523: E/AndroidRuntime(3783): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
07-16 01:36:54.523: E/AndroidRuntime(3783): at dalvik.system.NativeStart.main(Native Method)
07-16 01:36:56.225: I/Process(3783): Sending signal. PID: 3783 SIG: 9