HttpUrlConnection multipart file upload with progressBar - android

I want to check progress of uploading file by HttpUrlConnection. How I can do this? I've tried to calculate bytes when writing data in OutputStream but it's wrong, cause real uploading happens only when I call conn.getInputStream(), so I need somehow to check inputStream. Here is my code:
public static void uploadMovie(final HashMap<String, String> dataSource, final OnLoadFinishedListener finishedListener, final ProgressListener progressListener) {
if (finishedListener != null) {
new Thread(new Runnable() {
public void run() {
try {
String boundary = getMD5(dataSource.size()+String.valueOf(System.currentTimeMillis()));
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.setCharset(Charset.forName("UTF-8"));
for (String key : dataSource.keySet()) {
if (key.equals(MoviesFragmentAdd.USERFILE)) {
FileBody userFile = new FileBody(new File(dataSource.get(key)));
multipartEntity.addPart(key, userFile);
continue;
}
multipartEntity.addPart(key, new StringBody(dataSource.get(key),ContentType.APPLICATION_JSON));
}
HttpEntity entity = multipartEntity.build();
HttpURLConnection conn = (HttpsURLConnection) new URL(URL_API + "/video/addForm/").openConnection();
conn.setUseCaches(false);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("Content-length", entity.getContentLength() + "");
conn.setRequestProperty(entity.getContentType().getName(),entity.getContentType().getValue());
OutputStream os = conn.getOutputStream();
entity.writeTo(os);
os.close();
//Real upload starting here -->>
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//<<--
JsonObject request = (JsonObject) gparser.parse(in.readLine());
if (!request.get("error").getAsBoolean()) {
//do something
}
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}

Because you have to deal with upload, I'd suppose most time is taken when doing entity.writeTo(os);. Maybe the first contact to the server takes some time as well (DNS resolution, SSL-handshake, ...). The markers you set for "the real upload" are not correct IMO.
Now it depends on your Multipart-library, whether you can intercept writeTo. If it is clever and resource-efficient, it's iterating over the parts and streams the content one-by-one to the output stream. If not, and the .build() operation is creating a big fat byte[], then you could take this array, stream it in chunks to the server and tell your user how many percent of the upload is already done.
From a resource perspective I'd prefer not really knowing what happens. But if feedback is that important and if the movies are only a few megabytes in size, you could stream the Multipart-Entity first to a ByteArrayOutputStream and then write little chunks of the created byte-array to the server while notifying your user about progress. The following code is not validated or tested (you can see it as pseudo-code):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
entity.writeTo(baos);
baos.close();
byte[] payload = baos.toByteArray();
baos = null;
OutputStream os = conn.getOutputStream();
int totalSize = payload.length;
int bytesTransferred = 0;
int chunkSize = 2000;
while (bytesTransferred < totalSize) {
int nextChunkSize = totalSize - bytesTransferred;
if (nextChunkSize > chunkSize) {
nextChunkSize = chunkSize;
}
os.write(payload, bytesTransferred, nextChunkSize); // TODO check outcome!
bytesTransferred += nextChunkSize;
// Here you can call the method which updates progress
// be sure to wrap it so UI-updates are done on the main thread!
updateProgressInfo(100 * bytesTransferred / totalSize);
}
os.close();
A more elegant way would be to write an intercepting OutputStream which registers progress and delegates the real write-operations to the underlaying "real" OutputStream.
Edit
#whizzzkey wrote:
I've re-checked it many times - entity.writeTo(os) DOESN'T do a real upload, it does conn.getResponseCode() or conn.getInputStream()
Now it's clear. HttpURLConnection is buffering your upload data, because it doesn't know the content-length. You've set the header 'Content-length', but oviously this is ignored by HUC. You have to call
conn.setFixedLengthStreamingMode(entity.getContentLength());
Then you should better remove the call to conn.setRequestProperty("Content-length", entity.getContentLength() + "");
In this case, HUC can write the headers and entity.writeTo(os) can really stream the data to the server. Otherwise the buffered data is sent when HUC knows how many bytes will be transferred. So in fact, getInputStream() tells HUC that you're finished, but before really reading the response, all the collected data has to be sent to the server.
I wouldn't recommend changing your code, but for those of you who don't know the exact size of the transferred data (in bytes, not characters!!), you can tell HUC that it should transfer the data in chunks without setting the exact content-length:
conn.setChunkedStreamingMode(-1); // use default chunk size

Right this code in your activity...
public class PublishPostToServer extends AsyncTask implements
ProgressListenerForPost {
public Context pContext;
public long totalSize;
private String response;
public PublishPostToServer(Context context) {
pContext = context;
}
protected void onPreExecute() {
showProgressDialog();
}
#Override
protected Boolean doInBackground(Void... params) {
boolean success = true;
try {
response = NetworkAdaptor.getInstance()
.upLoadMultipartImageToServer(
"",
"",
"", this, this); // Add file path, Authkey, caption
} catch (Exception e) {
success = false;
}
return success;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
//validateResponse(result, response);
}
#Override
protected void onProgressUpdate(Integer... values) {
try {
if (mProgressDialog != null) {
mProgressDialog.setProgress(values[0]);
}
} catch (Exception exception) {
}
}
#Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
}
private void showProgressDialog() {
try {
String dialogMsg = "Uploading Image...";
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(dialogMsg);
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
} catch (Exception exception) {
}
}
Now, Make a NetworkAdapter Class
public String upLoadMultipartImageToServer(String sourceFileUri,
String auth_key, String caption, ProgressListenerForPost listiner,
PublishPostToServer asyncListiner) {
String upLoadServerUri = "" + "upload_image";
HttpPost httppost = new HttpPost(upLoadServerUri);
File file = new File(sourceFileUri);
if (file.exists()) {
FileBody filebodyVideo = new FileBody(file);
CustomMultiPartEntity multipartEntity = new CustomMultiPartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE, listiner);
try {
multipartEntity.addPart("auth_key", new StringBody(auth_key));
multipartEntity.addPart("caption", new StringBody(caption));
multipartEntity.addPart("image", filebodyVideo);
asyncListiner.totalSize = multipartEntity.getContentLength();
httppost.setEntity(multipartEntity);
}
catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
DefaultHttpClient mHttpClient = new DefaultHttpClient();
String response = "";
try {
response = mHttpClient.execute(httppost,
new MovieUploadResponseHandler());
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return response;
} else {
return null;
}
}
#SuppressWarnings("rawtypes")
private class MovieUploadResponseHandler implements ResponseHandler {
#Override
public Object handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
HttpEntity r_entity = response.getEntity();
String responseString = EntityUtils.toString(r_entity);
// DebugHelper.printData("UPLOAD", responseString);
return responseString;
}
}
public static boolean isValidResponse(String resultData) {
try {
} catch (Exception exception) {
//DebugHelper.printException(exception);
}
return true;
}
public String upLoadVideoToServer(String currentFilePath, String string,
PublishPostToServer publishPostToServer,
PublishPostToServer publishPostToServer2) {
// TODO Auto-generated method stub
return null;
}

Related

How Android Async Task Works with UrlConnection

I am new with the android. I am developing an app that will load content from target url in file. If the url didn't work, it will contact our server to request the correct url. If still fail, then it will ask the url from user input dialog. And it will try to initialize again. I have code like this:
if (initialize(target)!=true) {
JSONObject jsonParam = new JSONObject();
try {
jsonParam.put("sns", getSerial(PREF_NAME));
jsonParam.put("code", pwd);
} catch (JSONException e) {
e.printStackTrace();
}
target = getContent(samURL + "/sam_ip", jsonParam);
if (initialize(target)!=true) {
askIpUserDialog();
}
}
and the initialize() as follow
private boolean initialize(String url) {
Boolean success = false;
if ((!url.trim().startsWith("http://")) && (!url.trim().startsWith("https://"))) {
url = "http://" + url;
}
if (url.endsWith("/")) {
url = url.substring(0,url.length()-1);
}
String sUrl = url + "/android_view";
URL pUrl;
HttpURLConnection urlConn = null;
try {
DataOutputStream printout;
DataInputStream input;
pUrl = new URL (sUrl);
urlConn = (HttpURLConnection) pUrl.openConnection();
urlConn.setDoInput (true);
urlConn.setDoOutput (true);
urlConn.setUseCaches (false);
urlConn.setRequestProperty("Content-Type","application/json");
urlConn.setRequestProperty("Host", "android.schoolportal.gr");
urlConn.connect();
//Create JSONObject here
JSONObject jsonParam = new JSONObject();
jsonParam.put("snc", serialClient);
jsonParam.put("code", pwd);
printout = new DataOutputStream(urlConn.getOutputStream());
String str = jsonParam.toString();
byte[] data = str.getBytes("UTF-8");
printout.write(data);
printout.flush();
printout.close ();
int HttpResult = urlConn.getResponseCode();
if(HttpResult == HttpURLConnection.HTTP_OK){
success = true;
WebView view=(WebView) this.findViewById(R.id.webView);
view.setWebChromeClient(new WebChromeClient());
view.setWebViewClient(new WebViewClient());
view.getSettings().setJavaScriptEnabled(true);
view.loadUrl(sUrl);
}else{
success = false;
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally{
if(urlConn!=null)
urlConn.disconnect();
}
return success;
}
I just know that in android, url connection should run in separate thread. That's why I got the following error:
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
My question is, how do I use AsyncTask to avoid the error?
I saw there is doInBackground() which I can put the initialize() function there.
I saw also there is onPostExecute() event which I can check the result from the doInBackground(), but I don't understand yet how do I retrieve the return of initialize() which placed inside doInBackground()?
Bonus question, later I'd like to place all this job inside an intentservice. Do I need to stil use the asynctask? Does intentservice itself is an asynctask?
you can try some thing like this and also u can use a different thread
final Handler h = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
final File file = new File(path);
Log.i("path",path);
downloadFile(url[j], file);
h.post(new Runnable(){
#Override
public void run() {
txt.setText(""+jp);
jp++;
}
});
}
}
};
new Thread(r).start();
}
private static void downloadFile(String url, File outputFile) {
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
Log.i("len","" + contentLength);
Log.i("url1","Streaming from "+url+ "....");
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
fos.write(buffer);
fos.flush();
fos.close();
} catch(FileNotFoundException e) {
Log.v("FileError" , e.toString());
return; // swallow a 404
} catch (IOException e) {
Log.v("FileError" , e.toString());
return; // swallow a 404
}
catch (Exception e) {
Log.v("FileError" , e.toString());
return; // swallow a 404
}
}
and also you cant access ui elements on different thread you have to use handler or run on ui thread.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try{
this.pd = ProgressDialog.show(this, "Loading..", "Please Wait...", true, false);
new AsyncAction().execute();
}catch (Exception e) {
e.printStackTrace();
}
}
private class AsyncAction extends AsyncTask<String, Void, String> {
protected Void doInBackground(String... args) {
//do your stuff here }
}
}
Network traffic (and all other logic which takes some time to process) should always be handled by a background thread and never on the Main thread.
Use an ASyncTask to execute the logic.
private class YourTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// perform your network logic here
return "YourResult";
}
#Override
protected void onPostExecute(String result) {
// Update your screen with the results.
}
}
Call the ASyncTask in your code:
new YourTask().execute("");

Uploading file to server in background

I'm developing an app that allows to users to upload mediafiles(such as images, photos, videos) to server and I've got a little bit problem with large files - is too long to wait and view a progress bar in activity while its uploading and another problem - if app dies upload dies too so I need to transfer my uploading code to service. So here my troubles begins - if I'll transfer my upload code to server how can I send progress updates(%) to activity?
here's my upload method's code:
public static void uploadMovie(final HashMap<String, String> dataSource, final OnResponseListener finishedListener, final ProgressListener progressListener) {
if (finishedListener != null) {
new Thread(new Runnable() {
public void run() {
try {
//Prepare data-->
String boundary = getMD5(dataSource.size() + String.valueOf(System.currentTimeMillis()));
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.setCharset(Charset.forName("UTF-8"));
for (String key : dataSource.keySet()) {
if (key.equals(MoviesFragmentAdd.USERFILE)) {
FileBody userFile = new FileBody(new File(dataSource.get(key)));
multipartEntity.addPart(key, userFile);
continue;
}
multipartEntity.addPart(key, new StringBody(dataSource.get(key), ContentType.APPLICATION_JSON));
}
HttpEntity entity = multipartEntity.build();
//<--
//Prepare Connection-->
trustAllHosts();
HttpsURLConnection conn = (HttpsURLConnection) new URL(SAKH_URL_API + "/video/addForm/").openConnection();
conn.setUseCaches(false);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("Content-length", entity.getContentLength() + "");
conn.setRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());
conn.connect();
//<--
// Upload-->
OutputStream os = conn.getOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
entity.writeTo(baos);
baos.close();
byte[] payload = baos.toByteArray();
baos = null;
int totalSize = payload.length;
int bytesTransferred = 0;
int chunkSize = 2000;
while (bytesTransferred < totalSize) {
int nextChunkSize = totalSize - bytesTransferred;
if (nextChunkSize > chunkSize) {
nextChunkSize = chunkSize;
}
os.write(payload, bytesTransferred, nextChunkSize);
bytesTransferred += nextChunkSize;
//Progress update-->
if (progressListener != null) {
progressListener.onProgressUpdate((100 * bytesTransferred / totalSize));
}
//<--
}
os.flush();
//<--
//Get server response-->
int status = conn.getResponseCode();
if (conn.getResponseCode() == HttpsURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
JsonObject request = (JsonObject) gparser.parse(in.readLine());
if (!request.get("error").getAsBoolean()) {
finishedListener.onLoadFinished(new Object());
}
} else {
throw new IOException("Server returned non-OK status: " + status);
}
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
finishedListener.onNotConnected();
}
}
}).start();
}
}
1-Create a bindable service and implement the necessary Binder
Start your service BEFORE binding to it or in other case if your app is closed the service will also close
2-Expose a public function like StartDownload(url, IUpdateTarget) on your service.
3-Create an interface (IUpdateTarget) with a function like UpdateProgress(somevalues);
4-Implement the IUpdateTarget interface in the View which should receive the update notifications
5-Bind to the service and retrieve the running service's instance
6-Now you have the instance of your service, call to StartDownload passing the URL and the target view for notifications.
7-Whenever you must update the interface from the service call to UpdateProgress from the IUpdateProgress instance passed to the service (the target view).
Beware with cross-threading calls, remember that you must always update interface on main thread.
Use Handler to send process
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
android.os.Message msg = new android.os.Message();
Bundle bundle = new Bundle();
bundle.putInt("process", process);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
}).start();
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
int process = msg.getData().getInt("process");
};
};

Android Thread / AsyncTask, ExceptionInInitializerError and RuntimeException on "runOnUiThread"

I need your help with two Errors I´m getting on
Creating a Thread, where I`m creating a file
After the file stuff, a AsyncTask getting executed to send the file to a server (multipart/form-data)
Thats how the first part looks like:
public void startResultTransfer(final int timestamp, final int duration, final String correction, final float textSize, final int age, final int switch_count, final Activity activity){
synchronized(DataTransmission.class){
new Thread() {
public void run() {
FileWriter fw = null;
//1.Check if file exists
File file = new File(FILE_PATH);
if(!file.exists()){
//File does not exists, when we have to generate the head-line
try {
fw = new FileWriter(FILE_PATH);
fw.append("timestamp\tduration\tcorrection\ttext_size\tage\tswitch_count"); //Headline
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//2. Write Result
try {
if(fw == null)
fw = new FileWriter(FILE_PATH);
fw.append("\n"+String.valueOf(timestamp)+"\t");
fw.append(""+String.valueOf(duration)+"\t");
fw.append(""+correction+"\t");
fw.append(""+String.valueOf(textSize)+"\t");
fw.append(""+String.valueOf(age)+"\t");
fw.append(""+String.valueOf(switch_count)+"\t");
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//3. File Transfer
if(isOnline(activity))
transferFileToServer(activity);
}
}.start();
}
}
The function "transferFileToServer" looks like this:
public synchronized void transferFileToServer(Activity activity){
String id = id(activity);
File file = new File(FILE_PATH);
if(id != null && file.exists()){
final String url = URL+id;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
TransmissionTask task = new TransmissionTask();
task.execute(url);
}
});
}
}
Now, I`m getting an "ExceptionInInitializerError" with the explanatory message
Caused by java.lang.RuntimeException Can't create handler inside thread that has not called Looper.prepare()"
at the line "activity.runOnUiThread".
In the first function I need to call "transferFileToServer" after some pre settings. But the function should be called unattached from the first function, too.
Should I maybe implement a MessageHandler for executing the AsyncTask at the end of Thread?
http://developer.android.com/reference/android/os/Looper.html
Or should I maybe Change the "AsyncTask" in the "transferFileToServer" function to a Thread, because I don`t do any UI operations?
Edit: The method started from the Async-Task
class TransmissionTask extends AsyncTask<String, Void, String> {
public TransmissionTask() {
}
#Override
protected String doInBackground(String... params) {
synchronized(DataTransmission.class){
try {
HttpURLConnection urlConn;
java.net.URL mUrl = new java.net.URL(params[0]);
urlConn = (HttpURLConnection) mUrl.openConnection();
urlConn.setDoOutput(true);
urlConn.setRequestMethod("POST");
String boundary = "---------------------------14737809831466499882746641449";
String contentType = "multipart/form-data; boundary="+boundary;
urlConn.addRequestProperty("Content-Type", contentType);
DataOutputStream request = new DataOutputStream(urlConn.getOutputStream());
request.writeBytes("\r\n--"+boundary+"\r\n");
request.writeBytes("Content-Disposition: form-data; name=\"userfile\"; filename=\""+FILE_NAME+"\"\r\n");
request.writeBytes("Content-Type: application/octet-stream\r\n\r\n");
File myFile = new File(FILE_PATH);
int size = (int) myFile.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(myFile));
buf.read(bytes, 0, bytes.length);
buf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
request.write(bytes);
request.writeBytes("\r\n--"+boundary+"--\r\n");
request.flush();
request.close();
InputStream responseStream = new BufferedInputStream(urlConn.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null)
{
stringBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = stringBuilder.toString();
responseStream.close();
urlConn.disconnect();
return response;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(result != null){
if(result.toLowerCase().contains("erfolgreich")){
//If successfull delete File
File file = new File(FILE_PATH);
file.delete();
}
}
}
}
Remove runOnUiThread:
public synchronized void transferFileToServer(Activity activity){
String id = id(activity);
File file = new File(FILE_PATH);
if(id != null && file.exists()){
final String url = URL+id;
TransmissionTask task = new TransmissionTask();
task.execute(url);
}
}
The main idea of AsyncTask to run background operation/logic without Threads or Handlers.
You don't need wrap AsyncTask with additional Thread and bind with UI Thread what you did
From your code:
public void startResultTransfer(/* ... */){
....
new Thread() {
.....
transferFileToServer(/* ... */); // its wrong!!!
....
}.start()
}
transferFileToServer starts your AsyncTask and you run it not in main UI Thread but in single Thread.
This is a problem.
Start your AsyncTask from Activity.

FourSquare Photo upload on checkin with Android

I need to upload photo on checkin using FourSquare.If anybody has done it,Please help me in passing parameters.I have referred FourSquare Offical Document :
https://developer.foursquare.com/docs/photos/add. I am facing issue in Last three parameters.
Please Help me if you have done it.Thank You in Advance...
The parameters postUrl, postContentId, and postText are optional, so you do not need to provide them. postUrl and postContentId are used to provide a link that your photo can link to for more information. postText is a short comment about the photo.
/*
* put foursquare sdk file into projects libs folder and the later code into the Activity file
*/
todaydate = Latest Date;
venueId = The Venue Id is important.
URL = The image url from which the image will be downloaded to sd card;
foursquare = new Foursquare(
"Your Client Id", //*client id
"Your Client Secret", //*client secret
"Callback Url");
foursquare.authorize(ActivityName.this, new FoursquareAuthenDialogListener());
// Creates Bitmap from InputStream and returns it
private Bitmap downloadImage(String url) {
Bitmap bitmap = null;
InputStream stream = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1;
try {
stream = getHttpConnection(url);
bitmap = BitmapFactory.decodeStream(stream, null, bmOptions);
stream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return bitmap;
}
// Makes HttpURLConnection and returns InputStream
private InputStream getHttpConnection(String urlString)
throws IOException {
InputStream stream = null;
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
try {
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("GET");
httpConnection.connect();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return stream;
}
#SuppressLint("SdCardPath")
private class FoursquareAuthenDialogListener implements DialogListener {
#Override
public void onComplete(Bundle values) {
foursquareAccessToken = Foursquare.mAccessToken;
//Toast.makeText(getApplicationContext(), "TOKEN: " + foursquareAccessToken, Toast.LENGTH_LONG).show();
new downloadUploadedImage().execute();
}
#Override
public void onFoursquareError(FoursquareError e) {
// TODO Auto-generated method stub
}
#Override
public void onError(DialogError e) {
// TODO Auto-generated method stub
}
#Override
public void onCancel() {
// TODO Auto-generated method stub
}
}
/*
* downloadUploadedImage Class will download image from url and convert to bitmap image,
* using that bitmap image then convert it to file and get the file path from sd card
* to upload image to fs from sdcard.
*/
public class downloadUploadedImage extends AsyncTask<String, Void, String>{
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = ProgressDialog.show(MyActivityName.this, "", "Posting Image to Foursquare...", true);
}
#Override
protected String doInBackground(String... params) {
bitMapImage = downloadImage(URL);
writeExternalToCache(bitMapImage, file);
return null;
}
#Override
protected void onPostExecute(String result){
super.onPostExecute(result);
if(file.exists()){
//Toast.makeText(getApplicationContext(), "PIC PATH: " + file.toString(), Toast.LENGTH_LONG).show();
//Toast.makeText(getApplicationContext(), "PIC PATH: " + picPATH, Toast.LENGTH_LONG).show();
picturePath = file.toString();
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(picturePath,options);
final int REQUIRED_SIZE=200;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(options.outWidth/scale/2>=REQUIRED_SIZE && options.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
preview_bitmap = BitmapFactory.decodeFile(picturePath,o2);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
preview_bitmap.compress(CompressFormat.JPEG, 75, bos);
fileContent = bos.toByteArray(); //byte array static byte[] fileContent;
new UploadImageToFsProfile().execute();
} else {
//Toast.makeText(getApplicationContext(), "Image not exist in sdcard.", Toast.LENGTH_LONG).show();
}
}
}
public class UploadImageToFsProfile extends AsyncTask<String, Void, String>{//params,progress,result
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#SuppressWarnings("deprecation")
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://api.foursquare.com/v2/photos/add");
try
{
#SuppressWarnings("deprecation")
/*
* To use MultipartEntity class use httpclient-X.x.jar , httpcore-X.x.jar ,httpmime-X.x.jar
* and apachemime4jcore-X.x.jar
*/
MultipartEntity entity = new MultipartEntity();
entity.addPart("v", new StringBody(todaydate));
entity.addPart("venueId", new StringBody(venueId));
entity.addPart("public", new StringBody("1"));
entity.addPart("oauth_token", new StringBody(foursquareAccessToken));
ByteArrayBody imgBody = new ByteArrayBody(ChFsLogin.fileContent, "image/jpeg", "FS_image");
entity.addPart("image",imgBody);
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost);
responseResult = inputStreamToString(response.getEntity().getContent()).toString();
}
catch (ClientProtocolException e)
{ }
catch (IOException e)
{ }
return responseResult;
}
#Override
protected void onPostExecute(String result){
super.onPostExecute(result);
dialog.dismiss();
System.out.println("RES"+responseResult);
JSONObject obj;
try {
obj = new JSONObject(result);
//JSONArray meta =
obj = obj.getJSONObject("meta");
code = obj.getInt("code");
if(obj.has("errorDetail")){
Toast.makeText(getApplicationContext(), obj.getString("errorDetail"), Toast.LENGTH_LONG).show();
}
//Toast.makeText(getApplicationContext(), "code:"+code, Toast.LENGTH_LONG).show();
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (code ==200) {
Toast.makeText(getApplicationContext(), "Your Image Has Successfully Posted to FourSquare.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Unable to Post Image to FourSquare.", Toast.LENGTH_LONG).show();
}
File fileToDelete = new File(file.toString());
boolean deleted = fileToDelete.delete();
if (deleted) {
} else {
}
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
}
catch (IOException e) {
e.printStackTrace();
}
return answer;
}
}
I successfully uploaded the images to Foursquare via the code below:
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] bitmapdata = stream.toByteArray();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://api.foursquare.com/v2/photos/add");
try
{
MultipartEntity entity = new MultipartEntity();
entity.addPart("v", new StringBody("20121210"));
entity.addPart("venueId", new StringBody(venue.getId()));
entity.addPart("public", new StringBody("1"));
entity.addPart("oauth_token", new StringBody(mAccessToken));
ByteArrayBody imgBody = new ByteArrayBody(bitmapdata, "image/jpeg", "FS_image");
entity.addPart("image",imgBody);
httppost.setEntity(entity);
HttpResponse response = httpclient.execute(httppost);
Log.v("response","" +response);
responseResult = inputStreamToString(response.getEntity().getContent()).toString();
}
catch (ClientProtocolException e)
{
Log.d(TAG, "Opening URL " +e);
}

I need know how much bytes has been uploaded for update a progress bar android

I am developing an app for upload video to a Apache/PHP Server. In this moment I already can upload videos. I need show a progress bar while the file is being uploaded. I have the next code using AsyncTask and HTTP 4.1.1 Libraries for emulate the FORM.
class uploadVideo extends AsyncTask<Void,Void,String>{
#Override
protected String doInBackground(Void... params) {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.youtouch.cl/videoloader/index.php");
try {
// Add your data
File input=new File(fileName);
MultipartEntity multi=new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multi.addPart("video", new FileBody(input));
httppost.setEntity(multi);
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(
new InputStreamReader(
entity.getContent(), "UTF-8"));
String sResponse = reader.readLine();
return sResponse;
} catch (ClientProtocolException e) {
Log.v("Uri Galeria", e.toString());
e.printStackTrace();
} catch (IOException e) {
Log.v("Uri Galeria", e.toString());
e.printStackTrace();
}
return "error";
}
#Override
protected void onProgressUpdate(Void... unsued) {
//Here I do should update the progress bar
}
#Override
protected void onPostExecute(String sResponse) {
try {
if (pd.isShowing())
pd.dismiss();
if (sResponse != null) {
JSONObject JResponse = new JSONObject(sResponse);
int success = JResponse.getInt("SUCCESS");
String message = JResponse.getString("MESSAGE");
if (success == 0) {
Toast.makeText(getApplicationContext(), message,
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Video uploaded successfully",
Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
e.getMessage(),
Toast.LENGTH_LONG).show();
Log.e(e.getClass().getName(), e.getMessage(), e);
}
}
I need know where I can get how much bytes has been uploaded. File.length is the total size.
Have you tried extending FileBody? Presumably the POST will either call getInputStream() or writeTo() in order to actually send the file data to the server. You could extend either of these (including the InputStream returned by getInputStream()) and keep track of how much data has been sent.
thank to cyngus's idea I have resolved this issue. I have added the next code for tracking the uploaded bytes:
Listener on upload button:
btnSubir.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//pd = ProgressDialog.show(VideoAndroidActivity.this, "", "Subiendo Video", true, false);
pd = new ProgressDialog(VideoAndroidActivity.this);
pd.setMessage("Uploading Video");
pd.setIndeterminate(false);
pd.setMax(100);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.show();
//Thread thread=new Thread(new threadUploadVideo());
//thread.start();
new UploadVideo().execute();
}
});
Asynctask for run the upload:
class UploadVideo extends AsyncTask<Void,Integer,String> {
private FileBody fb;
#Override
protected String doInBackground(Void... params) {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.youtouch.cl/videoloader/index.php");
int count;
try {
// Add your data
File input=new File(fileName);
// I created a Filebody Object
fb=new FileBody(input);
MultipartEntity multi=new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multi.addPart("video",fb);
httppost.setEntity(multi);
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
//get the InputStream
InputStream is=fb.getInputStream();
//create a buffer
byte data[] = new byte[1024];//1024
//this var updates the progress bar
long total=0;
while((count=is.read(data))!=-1){
total+=count;
publishProgress((int)(total*100/input.length()));
}
is.close();
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(
new InputStreamReader(
entity.getContent(), "UTF-8"));
String sResponse = reader.readLine();
return sResponse;
} catch (ClientProtocolException e) {
Log.v("Uri Galeria", e.toString());
e.printStackTrace();
} catch (IOException e) {
Log.v("Uri Galeria", e.toString());
e.printStackTrace();
}
return "error";
}
#Override
protected void onProgressUpdate(Integer... unsued) {
pd.setProgress(unsued[0]);
}
#Override
protected void onPostExecute(String sResponse) {
try {
if (pd.isShowing())
pd.dismiss();
if (sResponse != null) {
Toast.makeText(getApplicationContext(),sResponse,Toast.LENGTH_SHORT).show();
Log.i("Splash", sResponse);
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
e.getMessage(),
Toast.LENGTH_LONG).show();
Log.e(e.getClass().getName(), e.getMessage(), e);
}
}
}
The progress bar load is bit slow (in starting seems be freeze and then load of 1 to 100 very fast), but works.
Sorry, my english is regular :(.
Check my answer here, I guess it answers your question:
But update the file path of the image to your to be uploaded video
https://stackoverflow.com/questions/15572747/progressbar-in-asynctask-is-not-showing-on-upload
What I used to do is to extends org.apache.http.entity.ByteArrayEntity and override the writeTo function like below, while bytes output it will pass though writeTo(), so you can count current output bytes:
#Override
public void writeTo(final OutputStream outstream) throws IOException
{
if (outstream == null) {
throw new IllegalArgumentException("Output stream may not be null");
}
InputStream instream = new ByteArrayInputStream(this.content);
try {
byte[] tmp = new byte[512];
int total = (int) this.content.length;
int progress = 0;
int increment = 0;
int l;
int percent;
// read file and write to http output stream
while ((l = instream.read(tmp)) != -1) {
// check progress
progress = progress + l;
percent = Math.round(((float) progress / (float) total) * 100);
// if percent exceeds increment update status notification
// and adjust increment
if (percent > increment) {
increment += 10;
// update percentage here !!
}
// write to output stream
outstream.write(tmp, 0, l);
}
// flush output stream
outstream.flush();
} finally {
// close input stream
instream.close();
}
}

Categories

Resources