I'm trying to design an application that starts a camera intent, uploads a photo, (and hopefully, work in progress: parse an XML response from the server, then move to another activity and fill in some form fields).
The problem is that so far the upload code is executed the 1st time I run the application, the 2nd time it gets skipped, the 3rd time works fine, 4th skips and so on.
MainActivity:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// buttons
Button lunchCamBtn = (Button) findViewById(R.id.lunchVerBtn);
lunchCamBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
}
});
Button lunchCaptBtn = (Button) findViewById(R.id.lunchCaptBtn);
lunchCaptBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
dispatchTakePictureIntent();
}
});
}
String path;
String picfname;
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
Random rnd = new Random(System.currentTimeMillis());
DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy");
Date date = new Date();
String picfname = "bul "+dateFormat.format(date)+" "+rnd.nextInt(90)+".png";
File output = new File(dir,picfname);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(output));
path = output.getAbsolutePath();
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Toast.makeText(getApplicationContext(), path.toString(),
Toast.LENGTH_LONG).show();
UploadFiles upld =new UploadFiles(MainActivity.this);
upld.execute(path.toString());
}
UploadFiles:
public class UploadFiles extends AsyncTask<String, Integer, Boolean> {
WeakReference<Activity> mActivityReference;
public UploadFiles(Activity activity){
this.mActivityReference = new WeakReference<Activity>(activity);
}
#Override
protected Boolean doInBackground(String... params) {
Boolean succesz = true;
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;
String selectedPath = params[0];
String pathToOurFile = selectedPath;
String urlServer = "http://192.168.0.104/upload2.php";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
try {
Bitmap bmp = BitmapFactory.decodeFile(pathToOurFile);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 90, bos);
InputStream fileInputStream = new ByteArrayInputStream(bos.toByteArray());
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setChunkedStreamingMode(1024);
connection.setReadTimeout(25000 /* milliseconds */);
connection.setConnectTimeout(30000 /* milliseconds */);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream
.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ pathToOurFile + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens
+ lineEnd);
InputStream stream = connection.getInputStream();
InputStreamReader isReader = new InputStreamReader(stream);
String line = "";
line = convertStreamToString(stream);
System.out.print(line);
fileInputStream.close();
outputStream.flush();
outputStream.close();
} catch (Exception ex) {
}
return succesz;
}
private String convertStreamToString(InputStream is) {
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (Exception e) {
//Toast.makeText(this, "Stream Exception", Toast.LENGTH_SHORT).show();
}
return total.toString();
}
#Override
protected void onPostExecute(Boolean result) {
if (result && mActivityReference.get() != null) {
Activity activity = mActivityReference.get();
Intent iinent= new Intent(activity,TestActivity.class);
activity.startActivity(iinent);
//activity.finish();
}
}}
I know now that this issue is caused by the convertStreamToString method in class UploadFiles but I can't understand what exactly causes it. When I remove it completely everything works fine. Thank you in advance!
The first minor problem:
Using available is basically wrong, though it might work.
The second minor problem:
Do not use DataOutputStream here. I guess it is done to be able to write Strings to an OutputStream.
response.setContentType("...; charset=Windows-1252");
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(os, "Windows-1252"));
Somehow also specifying the encoding/charset may help.
Problem with the convertStreamToString:
In no extra encoding parameter is added to the InputStreamReader, the default platform encoding is used. UTF-8 on Android. That would fail relatively fast.
You might give a less strict single-byte encoding a try to see what happens:
BufferedReader rd = new BufferedReader(new InputStreamReader(is, "Windows-1252"));
In general encoding is not handled: URLConnection.getContentEncoding() maybe is informative.
You are doing couple of things wrong here.
Don't leave exception blocks empty. It hides all the error. Use Log.e to print that.
Don't use System.out.println. Use Log.* only for logging.
Don't use AsyncTask to upload your file. Use IntentService Instead. And using localbroadcastmanager broadcast upload events for your activity to listen. It will be more configuration change friendly.
Instead of doing all this file upload sorcery yourself. Use httpmime library instead. It works simply awesome on android. I have my apps on production using this. Something like this you have to do.
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(urlToUpload);
MultipartEntity entity = new MultipartEntity();
Bitmap bmp = BitmapFactory.decodeFile(sourceFileUri);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 50, bos);
InputStream in = new ByteArrayInputStream(bos.toByteArray());
ContentBody imageContent = new InputStreamBody(in, "image/jpeg", sourceFile.getName());
entity.addPart("file", imageContent);
post.setEntity(entity);
HttpResponse response = client.execute(post);
You will have your everything in 'response' for you to read.
String responseBody = EntityUtils.toString(response.getEntity());
From here you can download this library http://repo1.maven.org/maven2/org/apache/httpcomponents/httpmime/4.2.5/
I have used this https://github.com/alexbbb/android-upload-service for file uploads.
I handle all the response-related logic inside the Broadcast receiver, where I'm waiting for the upload responses.
Related
I face a problem during downlonading an image in Android.
The problematic image link:
https://via.placeholder.com/150/92c952
I can use postman to download the image successfully (200).
But when I code in Android, using HttpConnection, it responds me with error status code 410.
(And then triggers FileNotFounedException.)
Below is my code,
URL url = new URL(fileURL);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
int responseCode = httpConn.getResponseCode();
// always check HTTP response code first
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType();
int contentLength = httpConn.getContentLength();
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 10,
disposition.length() - 1);
}
} else {
// extracts file name from URL
fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,
fileURL.length());
}
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int bytesRead = -1;
byte[] buffer = new byte[1024];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
System.out.println("File downloaded");
httpConn.disconnect();
return outputStream.toByteArray();
} else {
httpConn.disconnect();
throw new RuntimeException("Error code: " + responseCode);
}
My code can successfully download images from Imgur, but as for this link, it fails.
Please share any idea, I do appreciated a lot!
It's quite a simple reason.
The cause is not at your Java program side but at the server side.
The server rejects your connection by responding HTTP 410 Gone.
To dodge the server's behavior, just set any popular User-Agent string on your request before doing actual request.
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpCon.setRequestProperty(
"User-Agent",
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; ja-JP-mac; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6"
);
int responseCode = httpConn.getResponseCode();
...
if you wanna download image and show it on ImageView you can use glide or picasso. its pretty easy to implement, on glide you can just
Glide.with(context).load("https://via.placeholder.com/150/92c952").into(myImageView);
Use this method to download image from URL
// DownloadImage AsyncTask
private class DownloadImage extends AsyncTask<String, Void, Bitmap> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Bitmap doInBackground(String... URL) {
String imageURL = URL[0];
Bitmap bitmap = null;
try {
// Download Image from URL
InputStream input = new java.net.URL(imageURL).openStream();
// Decode Bitmap
bitmap = BitmapFactory.decodeStream(input);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
// set this bitmap to image view
// NOW USE THIS BITMAP TO SAVE IMAGE IN MEMORY, I SAVED IN INTERNAL MEMORY
if (result != null) {
File destination = new File(getActivity().getCacheDir(),
"profile" + ".jpg");
try {
destination.createNewFile();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
result.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
FileOutputStream fos = new FileOutputStream(destination);
fos.write(bitmapdata);
fos.flush();
fos.close();
selectedFile = destination;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Now call this method like this
new DownloadImage().execute("https://via.placeholder.com/150/92c952");
I am writing an app to upload images to my server from gallery and from camera
the problem I am having is when i take a picture from the camera and I click my upload button it crashes out of the app
according to the debug logs it has something to do with the bitmap pointing to a null object refrence as well as bitmap failing to decode the stream
there are a few answers on SO pretaining to this but non have worked so far
Error log
E/BitmapFactory: Unable to decode stream: java.lang.NullPointerException
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.smartpractice.myapplication, PID: 18010
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
at com.smartpractice.myapplication.MainActivity.upload(MainActivity.java:79)
at com.smartpractice.myapplication.MainActivity.access$100(MainActivity.java:41)
at com.smartpractice.myapplication.MainActivity$2.onClick(MainActivity.java:67)
at android.view.View.performClick(View.java:6663)
at android.view.View.performClickInternal(View.java:6635)
at android.view.View.access$3100(View.java:794)
at android.view.View$PerformClick.run(View.java:26199)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7593)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
Activity java
public class MainActivity extends Activity {
Button btpic, btnup;
private Uri fileUri;
String picturePath;
Uri selectedImage;
Bitmap photo;
String ba1;
public static String URL = "Paste your URL here";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btpic = (Button) findViewById(R.id.cpic);
btpic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
clickpic();
}
});
btnup = (Button) findViewById(R.id.up);
btnup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
upload();
}
});
}
private void upload() {
// Image location URL
Log.e("path", "----------------" + picturePath);
// Image
Bitmap bm = BitmapFactory.decodeFile(picturePath);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 0, bao);
byte[] ba = bao.toByteArray();
ba1 = Base64.encodeToString(ba, Base64.NO_WRAP);
Log.e("base64", "-----" + ba1);
// Upload image to server
new uploadToServer().execute();
}
private void clickpic() {
// Check Camera
if (getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
// Open default camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, 100);
} else {
Toast.makeText(getApplication(), "Camera not supported", Toast.LENGTH_LONG).show();
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode == RESULT_OK) {
selectedImage = data.getData();
photo = (Bitmap) data.getExtras().get("data");
Bitmap photo = (Bitmap) data.getExtras().get("data");
ImageView imageView = (ImageView) findViewById(R.id.Imageprev);
imageView.setImageBitmap(photo);
}
}
public class uploadToServer extends AsyncTask<Void, Void, String> {
private ProgressDialog pd = new ProgressDialog(MainActivity.this);
protected void onPreExecute() {
super.onPreExecute();
pd.setMessage("Wait image uploading!");
pd.show();
}
#Override
protected String doInBackground(Void... params) {
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("base64", ba1));
nameValuePairs.add(new BasicNameValuePair("ImageName", System.currentTimeMillis() + ".jpg"));
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(URL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
String st = EntityUtils.toString(response.getEntity());
Log.v("log_tag", "In the try Loop" + st);
} catch (Exception e) {
Log.v("log_tag", "Error in http connection " + e.toString());
}
return "Success";
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
pd.hide();
pd.dismiss();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==REQUEST_CAMERA)
{
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),"temp.jpg");
FileOutputStream fo;
try {
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
new uploadFileToServerTask().execute(destination.getAbsolutePath());
}
}
Uploading File to server
private class uploadFileToServerTask extends AsyncTask<String, String, Object> {
#Override
protected String doInBackground(String... args) {
try {
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
#SuppressWarnings("PointlessArithmeticExpression")
int maxBufferSize = 1 * 1024 * 1024;
java.net.URL url = new URL((ApplicationConstant.UPLOAD_IMAGE_URL) + IMAGE + customer_id);
Log.d(ApplicationConstant.TAG, "url " + url);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs.
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Set HTTP method to POST.
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
FileInputStream fileInputStream;
DataOutputStream outputStream;
{
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
String filename = args[0];
outputStream.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + filename + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
Log.d(ApplicationConstant.TAG, "filename " + filename);
fileInputStream = new FileInputStream(filename);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
}
int serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
Log.d("serverResponseCode", "" + serverResponseCode);
Log.d("serverResponseMessage", "" + serverResponseMessage);
fileInputStream.close();
outputStream.flush();
outputStream.close();
if (serverResponseCode == 200) {
return "true";
}
} catch (Exception e) {
e.printStackTrace();
}
return "false";
}
#Override
protected void onPostExecute(Object result) {
}
}
I have the following file upload function:
public void uploadFile(Context context, File file) {
String urlServer = "https://u-database.000webhostapp.com/recieve_file.php";
if(file.isFile() && file.exists()) {
String fileName = file.getAbsolutePath();
try {
HttpURLConnection conn = null;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
Toast toastw = Toast.makeText(context, "Inside TRY", Toast.LENGTH_SHORT);
toastw.show();
FileInputStream fileInputStream = new FileInputStream(file);
URL url = new URL(urlServer);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("textLog", fileName);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"textLog\";filename=\""+fileName+"\""+lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
int serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
Toast toast = Toast.makeText(context, "Uploading", Toast.LENGTH_SHORT);
toast.show();
if(serverResponseCode == 200){
file.delete();
Toast toasto = Toast.makeText(context, "success", Toast.LENGTH_SHORT);
toasto.show();
}
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
Toast toast = Toast.makeText(context, "Malformed URL", Toast.LENGTH_SHORT);
toast.show();
} catch (Exception e) {
Toast toast = Toast.makeText(context, "Exception", Toast.LENGTH_SHORT);
toast.show();
}
}
}
Each time it is executed, a toast appears stating Inside TRY and then another appears stating "Exception".
I have been debugging a lot and any kind of help would be really appreciated :)
UPDATE
When I did e.toString and printed it out to a toast, I got: android.os.NetworkOnMainThreadException
The answer is simple then. You should run your network calls on a background thread. You need to extend AsyncTask and move your code into it. Something like:
private class InitTask extends AsyncTask<Void, Void, Void>{
protected Void doInBackground(Void... p){
// Call upload file code here
}
}
I am uploading a file from android to my webserver using the DataOutputStream with the following code:
public class SnapshotUploadTask extends AsyncTask<Object, Integer, Void> {
private final File file;
private final ProgressDialog progressDialog;
private final Activity activity;
public SnapshotUploadTask(File file, ProgressDialog progressDialog, Activity activity) {
this.progressDialog = progressDialog;
this.file = file;
this.activity = activity;
}
#Override
protected void onPreExecute() {
progressDialog.setProgress(0);
}
#Override
protected Void doInBackground(Object... arg0) {
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead;
int bytesAvailable;
int bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 512;
try {
FileInputStream fileInputStream = new FileInputStream(file);
URL url = new URL("http://bla.bla.bla/upload");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("ENCTYPE", "multipart/form-data");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
connection.setRequestProperty("uploaded_file", file.getName());
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\"" + file.getName() + "\"" + lineEnd);
dataOutputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
final int hundredPercent = bytesAvailable;
progressDialog.setMax(hundredPercent);
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
final int restBytes = bytesAvailable;
final int uploadedBytes = hundredPercent - restBytes;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setProgress((int) uploadedBytes);
if (restBytes <= 0) {
progressDialog.setMessage(activity.getString(R.string.camera_uploading_done));
}
}
});
}
dataOutputStream.writeBytes(lineEnd);
dataOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
int serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
if (serverResponseCode == 200) {
progressDialog.dismiss();
}
fileInputStream.close();
dataOutputStream.flush();
dataOutputStream.close();
} catch (Exception e) {
progressDialog.dismiss();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
Now what happens is that i update my progressDialog as soon as i have written a certain amount of bytes into the OutputStream which leads to the progressDialog reaching 100% before the data is actually received by the server.
I only know when the transmission is complete when i get to connection.getResponseCode();
What i want instead is to update the progress when the data chunks are actually received by the server. Is there a way to do that?
You need to be aware that HttpURLConnection buffers all the output unless you set fixed-length or chunked transfer mode, which you should certainly do instead of implementing it yourself. It does that so it can set the Content-Length header accurately. If you use one of these transfer modes there is no buffering.
NB You're misusing available(): see the Javadoc; and you're writing junk in most cases:
dataOutputStream.write(buffer, 0, bufferSize);
should be
dataOutputStream.write(buffer, 0, bytesRead);
You don't need all that fiddling around with available() inside the read loop either. Something like this is sufficient:
long total = 0;
int maxBufferSize = 8192; // at least. 512 is far too small.
while ((bytesRead = fileInputStream.read(buffer, 0, bufferSize)) > 0) {
dataOutputStream.write(buffer, 0, bytesRead);
total += bytesRead;
final long uploadedBytes = total;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setProgress(uploadedBytes);
}
});
}
}
// at this point we are at end of stream
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setMessage(activity.getString(R.string.camera_uploading_done));
}
}
E&OE
I want to call startUpload(position); method in loginbutton.setOnClickListener(new View.OnClickListener() {} like this:
loginbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SaveData();
alertDialog.dismiss();
startUpload(position);
}
but always getting : position cannot be resolved to a variable
so where i am doing mistake, how can i resolve this issue..?
//Upload
public void startUpload(final int position) {
Runnable runnable = new Runnable() {
public void run() {
handler.post(new Runnable() {
public void run() {
View v = lstView.getChildAt(position - lstView.getFirstVisiblePosition());
// Show ProgressBar
ProgressBar progress = (ProgressBar)v.findViewById(R.id.progressBar);
progress.setVisibility(View.VISIBLE);
// Status
TextView status = (TextView)v.findViewById(R.id.ColStatus);
status.setText("Uploading..");
new UploadFileAsync().execute(String.valueOf(position));
}
});
}
};
new Thread(runnable).start();
}
// Async Upload
public class UploadFileAsync extends AsyncTask<String, Void, Void> {
String resServer;
int position;
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
position = Integer.parseInt(params[0]);
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
int resCode = 0;
String resMessage = "";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
// File Path
strSDPath = ImageList.get(position).toString();
// Upload to PHP Script
String strUrlServer = "http://10.0.2.2/res/uploadFile.php";
try {
/** Check file on SD Card ***/
File file = new File(strSDPath);
if(!file.exists())
{
resServer = "{\"StatusID\":\"0\",\"Error\":\"Please check path on SD Card\"}";
return null;
}
FileInputStream fileInputStream = new FileInputStream(new File(strSDPath));
URL url = new URL(strUrlServer);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
DataOutputStream outputStream = new DataOutputStream(conn
.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream
.writeBytes("Content-Disposition: form-data; name=\"filUpload\";filename=\""
+ strSDPath + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Response Code and Message
resCode = conn.getResponseCode();
if(resCode == HttpURLConnection.HTTP_OK)
{
InputStream is = conn.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int read = 0;
while ((read = is.read()) != -1) {
bos.write(read);
}
byte[] result = bos.toByteArray();
bos.close();
resMessage = new String(result);
}
Log.d("resCode=",Integer.toString(resCode));
Log.d("resMessage=",resMessage.toString());
fileInputStream.close();
outputStream.flush();
outputStream.close();
resServer = resMessage.toString();
} catch (Exception ex) {
// Exception handling
return null;
}
return null;
}
protected void onPostExecute(Void unused) {
statusWhenFinish(position,resServer);
}
}
// when upload finish
protected void statusWhenFinish(int position, String resServer) {
View v = lstView.getChildAt(position - lstView.getFirstVisiblePosition());
// Show ProgressBar
ProgressBar progress = (ProgressBar)v.findViewById(R.id.progressBar);
progress.setVisibility(View.GONE);
// Status
TextView status = (TextView)v.findViewById(R.id.ColStatus);
/*** Default Value ***/
String strStatusID = "0";
String strMessage = "Unknow Status!";
try {
JSONObject c = new JSONObject(resServer);
strStatusID = c.getString("StatusID");
strMessage = c.getString("Message");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Prepare Status
if(strStatusID.equals("0"))
{
// When update Failed
status.setText( strMessage );
status.setTextColor(Color.RED);
// Enabled Button again
Button btnUpload = (Button) v.findViewById(R.id.btnUpload);
btnUpload.setText("Already Uploaded");
btnUpload.setTextColor(Color.RED);
btnUpload.setEnabled(true);
}
else
{
status.setText("Upload Completed.");
status.setTextColor(Color.GREEN);
}
}
}
The declaration of position is key here.
Make sure it is in the method that contains this loginButton.onClickListener code and make sure it is declared as final
If it can be resolved as a variable it's not because of your method,
it's because position is not an attribute.
So, delcare it as :
int position = -1;
And then set it to use your method.
TRY IT
Create a Global variable POSITION then assign POSITION=position in your startUpload() method , it'll work.
When referencing variables, they must be definitive within the scope of the method.
So for methods, make sure it is either passed as a parameter, or it is defined as a global variable within the class.