I am developing a project where user store some information and image into SQLite database. The image is stored as BLOB data. Now I want to upload all data into my MySQL database. I am using Volley to upload all rows one by one from SQLite to MySQL server with a AsyncTask calling a Web API.
Everything working fine without the image BLOB data. I do not know is there any way to upload blob data using Volley. I have search a lot into StackOverflow but did not get any solution, please help me.
I am giving some code example to make my question better understandable.
Here is my function calling in a AsyncTask:
/**
* function to upload data into server
* */
private void SyncTaskDoInBack(final dataDB data) {
// Tag used to cancel the request
String tag_string_req = "Inserting Online";
StringRequest strReq = new StringRequest(Method.POST, AppConfig.API_LINK, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
Log.d(TAG, "Success");
} else {
// Error in found
String errorMsg = jObj.getString("error_msg");
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
}
}) {
@Override
protected Map<String, String> getParams() {
// Posting parameters to login url
Map<String, String> params = new HashMap<String, String>();
params.put("ID", data._id);
params.put("PersonName", data.pName);
params.put("Photo", data.photo.toString());
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
My "dataDB" Class is as follows:
public class dataDB implements Comparable<dataDB>{
String _id = null;
String pName = null;
byte[] photo = null;
@Override
public int compareTo(dataDB o) {
//return title.toLowerCase().compareTo(o.title.toLowerCase());
return 0;
}
}
List Data Model class is follows:
public class ListDataModel {
private int _id;
private String name;
private byte[] image;
public ListDataModel() { }
public ListDataModel(String name, String thumbnailUrl) {
this.name = name;
this.thumbnailUrl = thumbnailUrl;
}
// getting ID
public int getID() {
return this._id;
}
// setting id
public void setID(int keyId) {
this._id = keyId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte[] getImage() {
return this.image;
}
public void setImage(byte[] image) {
this.image = image;
}
}
After searching a lot into StackOverflow, I have come up with the following formula, which appears to produce the camera image into Base64 String and Vice-versa. Hope this will help others.
I am using Apache Commons Codec for Base64 encode/decode from here http://commons.apache.org/proper/commons-codec/ (I think one can use Android default Base64 class too, I am using this for other purposes also)
Here is my onActivityResult function
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK)
return;
switch (requestCode) {
case CAMERA_REQUEST:
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap myImage = extras.getParcelable("data");
ByteArrayOutputStream bao = new ByteArrayOutputStream();
myImage.compress(Bitmap.CompressFormat.JPEG, 90, bao);
imageInByte = bao.toByteArray();
imageInBase64Str = Base64.encodeBytes(imageInByte); // using internal class
}
break;
}
}
Then I'm passing the Base64 String imageInBase64Str to my insert statement of SQlite and MySQL online database.
When getting image Base64 encoded data from SQLite or MySQL to view, I'm processing my image like the following way:
try {
byte[] decodedByte = Base64.decode(imageData, 0);
theImage = BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
}catch (IOException io){
Log.d("ViewRecord",io.getMessage());
}
That's it :)