0

I'm struggling for few days with this problem and you are my last chance solving it.

The Goal:

To upload a bitmap from android client to google app engine and save it in datastore.

  • I'm using Serialization to transfer object from client to server and vise versa.

Things I have tried:

  • sending a Bitmap
    • but i got java.io.NotSerializableException: android.graphics.Bitmap
  • then I tried create from the Bitmap Blob at the client like this:

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
    Byte[] bArray = bos.toByteArray();
    Blob blob = new Blob(bArray); 
    

    But at the client side I dont have the google app engine classes (for Blob), So I tried to brute force it by extract specific classess but it created new problems.

So I am asking in which dierction I can go from to solve this problem.
Thanks.

Rami
  • 2,098
  • 5
  • 25
  • 37
  • 1
    For serializing the bitmap, see this question: http://stackoverflow.com/questions/5871482/serializing-and-de-serializing-android-graphics-bitmap-in-java – Moishe Lettvin May 16 '12 at 16:40
  • Toda Moishe , But I get java.io.EOFException at java.io.ObjectInputStream$BlockDataInputStream.readFully(ObjectInputStream.java:2699) – Rami May 16 '12 at 17:03
  • Instead of trying to create the blob on Android, send the byte array as the body of the request (see Peter's answer for more details). – Nick Johnson May 17 '12 at 00:18

3 Answers3

3

Few notes:

  1. Do not use Java serialization to transfer data between JVMs. Java serialization is not standardized and is not guaranteed to be compatible between JVMs (or even between versions).

  2. To send binary data it's best to use HTTP POST and set Content-Type appropriately (e.g. application/octet-stream).

So, to make this work do this:

  1. Create a servlet which handles POST and gets the binary data. Use servletRequest.getInputStream() to get hold of binary data.

  2. Use Blobstore FileService API to save data to blobstore.

  3. On Android side use a http client to make a POST request and add your bitmap's binary data to it. If you need to add some metadata use Http headers.

Peter Knego
  • 79,991
  • 11
  • 123
  • 154
0

This might be useful

How to upload and store an image with google app engine (java)

Alternatively, you can try blobstore api

http://code.google.com/appengine/docs/java/blobstore/overview.html

Community
  • 1
  • 1
user1302884
  • 783
  • 1
  • 8
  • 16
0

Here is a production tested way:

Use GAE appengine to upload your bitmap to, and serve for future clients.

On the Android code, follow these steps:

  1. Get an Upload URL from GAE
  2. Upload your bitmap to GAE, and get a blobkey back
  3. Later on, use the blobkey to serve the image to your clients.

GAE Servlet code:

getUploadURL:

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
String url = blobstoreService.createUploadUrl(path_to_your_upload_servlet);

uploadServlet - stores in blobstore, returns the blobkey to the uploader

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Map<String, List<BlobKey>> uploads = blobstoreService.getUploads(request);
String fileName = uploads.keySet().iterator().next();
final BlobKey blobKey = uploads.get(fileName).get(0);
response.getWriter().println(blobKey.getKeyString());

Android client code:

String uploadUrl = getUrlAsString(..your getUrl servlet path...)
// Upload to GAE (include apache-mime4j.jar and httpmime.jar in your project for this code)
File file = new File(imageFilePath);
HttpPost postRequest = new HttpPost(uploadUrl);
MultipartEntity entity = new MultipartEntity();
entity.addPart("file", new FileBody(file));
postRequest.setEntity(entity);
HttpResponse httpResponse;
HttpClient httpClient = new DefaultHttpClient();
httpClient.getParams().setBooleanParameter("http.protocol.handle-redirects",false);

httpResponse = httpClient.execute(postRequest);
int status = httpResponse.getStatusLine().getStatusCode();
String blobKey = getInputStreamAsString(httpResponse.getEntity().getContent())
Guy
  • 12,250
  • 6
  • 53
  • 70
  • Why do you assume he has the image in a file? It's clearly an in-memory bitmap. – Nick Johnson May 17 '12 at 00:17
  • Holding bitmaps in android memory could be very tricky. The bitmap memory is allocated externally, and is scarse. If the bitmap is created dynamically, I would first write it to storage, and then try a more lengthy upload process. In real life applications, Keeping the bitmap in memory would most likely over time prevent the app from displaying and processing other bitmaps. – Guy May 17 '12 at 05:09
  • I don't think having an `android.graphics.Bitmap` necesarily means it's being stored in video memory. And regardless, the problem the OP had was trying to upload a bitmap; if writing it to the file is a step you think they should take, you should document that. – Nick Johnson May 17 '12 at 12:05