I'm writing an app that lets a user choose a photo already on their phone and uploads it to a server. Unfortunately when I click the button to send the photo to the sever, in logcat I see:
Could not find class 'org.apache.http.entity.mime.MultipartEntity', referenced from method com.example.crescentcameraapp.MainActivity$ImageUploadTask.doInBackground
I've seen all the similar questions that exist on stack overflow:
There are a few more, but the point is, none of them have a good answer. Solutions include:
"Download all the necessary jars from http://hc.apache.org/downloads.cgi and add them to the Java Build Path in Eclipse." ** Doesn't work. I've tried it, cleaned the project, closed/opened Eclipse. Nothing.
"Add all the jars to the libs folder in your project, Android does the rest." **Still, it doesn't work. I don't know why.
For some reason, even though it posts this error to logcat, it continues running and only crashes later when I try to use the MultiPartEntity object I created in the code. Here's the rest of the logcat:
06-17 21:21:34.396: E/dalvikvm(14917): Could not find class 'org.apache.http.entity.mime.MultipartEntity', referenced from method com.example.crescentcameraapp.MainActivity$ImageUploadTask.doInBackground
06-17 21:21:34.396: W/dalvikvm(14917): VFY: unable to resolve new-instance 652 (Lorg/apache/http/entity/mime/MultipartEntity;) in Lcom/example/crescentcameraapp/MainActivity$ImageUploadTask;
06-17 21:21:34.396: D/dalvikvm(14917): VFY: replacing opcode 0x22 at 0x002b
06-17 21:21:34.396: I/dalvikvm(14917): DexOpt: unable to optimize static field ref 0x0422 at 0x2d in Lcom/example/crescentcameraapp/MainActivity$ImageUploadTask;.doInBackground
06-17 21:21:34.396: D/dalvikvm(14917): DexOpt: unable to opt direct call 0x10e8 at 0x2f in Lcom/example/crescentcameraapp/MainActivity$ImageUploadTask;.doInBackground
06-17 21:21:34.396: D/dalvikvm(14917): DexOpt: unable to opt direct call 0x10eb at 0x56 in Lcom/example/crescentcameraapp/MainActivity$ImageUploadTask;.doInBackground
06-17 21:21:34.396: D/dalvikvm(14917): DexOpt: unable to opt direct call 0x10eb at 0x62 in Lcom/example/crescentcameraapp/MainActivity$ImageUploadTask;.doInBackground
06-17 21:21:34.396: D/dalvikvm(14917): DexOpt: unable to opt direct call 0x10ea at 0x6e in Lcom/example/crescentcameraapp/MainActivity$ImageUploadTask;.doInBackground
06-17 21:21:34.396: D/dalvikvm(14917): DexOpt: unable to opt direct call 0x10eb at 0x85 in Lcom/example/crescentcameraapp/MainActivity$ImageUploadTask;.doInBackground
06-17 21:21:34.401: W/dalvikvm(14917): threadid=11: thread exiting with uncaught exception (group=0x412192a0)
06-17 21:21:34.406: E/AndroidRuntime(14917): FATAL EXCEPTION: AsyncTask #1
06-17 21:21:34.406: E/AndroidRuntime(14917): java.lang.RuntimeException: An error occured while executing doInBackground()
06-17 21:21:34.406: E/AndroidRuntime(14917): at android.os.AsyncTask$3.done(AsyncTask.java:299)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
06-17 21:21:34.406: E/AndroidRuntime(14917): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.lang.Thread.run(Thread.java:856)
06-17 21:21:34.406: E/AndroidRuntime(14917): Caused by: java.lang.NoClassDefFoundError: org.apache.http.entity.mime.MultipartEntity
06-17 21:21:34.406: E/AndroidRuntime(14917): at com.example.crescentcameraapp.MainActivity$ImageUploadTask.doInBackground(MainActivity.java:244)
06-17 21:21:34.406: E/AndroidRuntime(14917): at com.example.crescentcameraapp.MainActivity$ImageUploadTask.doInBackground(MainActivity.java:1)
06-17 21:21:34.406: E/AndroidRuntime(14917): at android.os.AsyncTask$2.call(AsyncTask.java:287)
06-17 21:21:34.406: E/AndroidRuntime(14917): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
06-17 21:21:34.406: E/AndroidRuntime(14917): ... 5 more
06-17 21:21:43.731: I/Choreographer(14917): Skipped 534 frames! The application may be doing too much work on its main thread.
06-17 21:21:44.856: E/WindowManager(14917): Activity com.example.crescentcameraapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@41c93710 that was originally added here
06-17 21:21:44.856: E/WindowManager(14917): android.view.WindowLeaked: Activity com.example.crescentcameraapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@41c93710 that was originally added here
There's more, but you get the point. Below is the relevant code. ImageUploadTask is an inner class:
class ImageUploadTask extends AsyncTask <Void, Void, String>{
@SuppressWarnings("deprecation")
@Override
protected String doInBackground(Void... unsued) {
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(
getString(R.string.web_url_text)
+ "/test.php"
);
MultipartEntity entity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
imageBMP.compress(CompressFormat.JPEG, 100, bos);
byte[] data = bos.toByteArray();
entity.addPart("photoId", new StringBody(getIntent()
.getStringExtra("photoId")));
entity.addPart("returnformat", new StringBody("json"));
entity.addPart("uploaded", new ByteArrayBody(data,
"myImage.jpg"));
String captionText = findViewById(R.string.caption_text).toString();
entity.addPart("photoCaption", new StringBody(captionText));
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost,
localContext);
BufferedReader reader = new BufferedReader(
new InputStreamReader(
response.getEntity().getContent(), "UTF-8"));
String sResponse = reader.readLine();
return sResponse;
} catch (Exception e) {
if (dialog.isShowing())
dialog.dismiss();
Toast.makeText(getApplicationContext(),
"Error sending file to server...",
Toast.LENGTH_LONG).show();
Log.e(e.getClass().getName(), e.getMessage(), e);
return null;
}//end of catch
}
protected void onPostExecute(String sResponse) {
Toast.makeText(getApplicationContext(), "Upload completed.", Toast.LENGTH_LONG).show();
}//onPostExecute()
}//end of class ImageUploadTask
Thanks.
I figured it out, based in part on the solutions provided in the relevant questions I linked to. I cleaned the project, restarted eclipse, and then I downloaded and added mime4j to my build path:
http://james.apache.org/download.cgi#Apache_Mime4J
The above page is the official download, but it didn't work for me. Try sourceforge for an alternative:
http://sourceforge.net/projects/mime4j/?source=dlp
Beware:
Adding this will almost certainly cause issues with bin/dexedLibs in your project. If so, you're probably in for a bit of a nightmare. You'll get console error messages about certain objects/classes/exceptions being defined across multiple jars. This is because the dexedLibs folder ostensibly contains copies of the jars in your libs folder. Just delete the original copy (the one in your libs folder) from your project, clean the solution, and build it again. You might get new complains in the console about multiply defined classes, but that just means you have more jars to delete. This is how I solved the problem.