Reputation: 6357
I take a picture using the android.hardware.Camera
API. I then convert it to a Bitmap of half the actual size, compress it to a JPEG of quality 80, convert it to Base64
and send it to the server as follows.
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.NO_WRAP);
String json_response = "";
try {
URL url = new URL("https://example.com/api_endpoint");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write("?reg=" + regCode);
writer.write("&img=" + encoded);
writer.flush();
writer.close();
os.close();
Log.d("Auth", conn.getResponseCode() + "");
InputStreamReader in = new InputStreamReader(conn.getInputStream());
BufferedReader br = new BufferedReader(in);
String text = "";
while ((text = br.readLine()) != null) {
json_response += text;
}
conn.disconnect();
} catch (IOException e) {
Log.d(getClass().getName(), "" + e.getMessage());
}
This works as expected. Now, If I don't resize the image and keep the quality 100%, how should I go about to avoid an OutOfMemoryError
? My application requires the image to be in the full resolution and best quality possible.
My questions are:
OutOfMemoryError
i.e. how to optimize RAM usage in this process?Upvotes: 0
Views: 4697
Reputation: 5788
I think problem not with downloading to server. If I understand correctly, you getting image from camera and sending it. Note, that if you using simple request intent, that returns in onActivityResult() - Bitmap Image - this may be point of OutOfMemoryException...
Solution it's use another form on Intent() method, (that can get storage path in his parameters) for getting photo from camera, that doesn't return Bitmap image. But save photo to path, which you specified. And now you can do anything with photo in path, without OutOfMemoryException...
Sample starting correct Intent:
File destination = new File(Environment.getExternalStorageDirectory(),
"image.jpg");
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(destination));
startActivityForResult(intent, CAMERA_PICTURE);
Let me know, this helps...
Upvotes: 0
Reputation: 1819
If you have the control over the API endpoint. Then try to implement the POST request to accept multi-part uploading from client side.
On client-side, have something like this to upload the image to API (with Okhttp client)
private static final String IMGUR_CLIENT_ID = "...";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "Square Logo")
.addFormDataPart("image", "logo-square.png",
RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
Upvotes: 1
Reputation: 1031
Here is my image/file uploader class:
public class ImageUploader extends AsyncTask<String, String, String> {
File imageFile = null;
String fileName = null;
public ImageUploader(File imageFile, String fileName){
this.imageFile = imageFile;
this.fileName = fileName;
}
@Override
protected String doInBackground(String... params) {
String url_str = params[0];
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
String Tag="fSnd";
try {
URL url = new URL(url_str);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("POST");
c.setDoInput(true);
c.setDoOutput(true);
c.setRequestProperty("Connection", "Keep-Alive");
c.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
c.connect();
DataOutputStream dos = new DataOutputStream(c.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + this.fileName + "\"" + lineEnd);
dos.writeBytes(lineEnd);
FileInputStream fin = new FileInputStream(imageFile);
int bytesAvailable = fin.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[ ] buffer = new byte[bufferSize];
int bytesRead = fin.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fin.available();
bufferSize = Math.min(bytesAvailable,maxBufferSize);
bytesRead = fin.read(buffer, 0,bufferSize);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
fin.close();
dos.flush();
dos.close();
StringBuilder response = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return response.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
}
return null;
}
}
Usage:
new ImageUploader(pictureFile, "sample.jpg"){
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
}
}.execute("http://example/upload.php");
PHP:
<?php
$file = explode('.', $_FILES['file']['name']);
$ext = $file[count($file) - 1];
$name = substr($_FILES['file']['name'], 0, (strlen($ext) + 1) * -1);
$location = 'images/';
$cntr = 1;
$tmp_name = $name;
if(move_uploaded_file($_FILES['file']['tmp_name'], $location.$tmp_name.'.'.$ext)){
echo "Image was uploaded.";
}else{
echo "Image was not uploaded.";
}
?>
Upvotes: 2